Dynamically Create Class Attributes with Attr_Accessor

Dynamically Create Class Attributes with attr_accessor

One way (there are others) is to use instance_variable_set and instance_variable_get as so:

class Test
def create_method( name, &block )
self.class.send( :define_method, name, &block )
end

def create_attr( name )
create_method( "#{name}=".to_sym ) { |val|
instance_variable_set( "@" + name, val)
}

create_method( name.to_sym ) {
instance_variable_get( "@" + name )
}
end
end

t = Test.new
t.create_attr( "bob" )
t.bob = "hello"
puts t.bob

Ruby: dynamically generate attribute_accessor

You need to call the (private) class method attr_accessor on the Event class:

    self.class.send(:attr_accessor, name)

I recommend you add the @ on this line:

    instance_variable_set("@#{name}", value)

And don't use them in the hash.

    data = {:datetime => '2011-11-23', :duration => '90', :class => {:price => '£7', :level => 'all'}}

How do I set an attr_accessor for a dynamic instance variable?

this answer doesn't pollutes the class space, example.. if i do mine.my_number 4 then the other instances of Mine will not get the my_4 method.. this happens because we use the singleton class of the object instead of the class.

class Mine
def my_number num
singleton_class.class_eval { attr_accessor "my_#{num}" }
send("my_#{num}=", num)
end
end

a = Mine.new
b = Mine.new
a.my_number 10 #=> 10
a.my_10 #=> 10
b.my_10 #=> NoMethodError

Dynamically assigning attributes using strings as attribute setters in Ruby

Use thing.send("#{k}=", v) instead.

Does Ruby's attr_accessor automatically create instance variables for attributes?

No. Instance variables are not defined until you assign to them, and attr_accessor doesn't do so automatically.

Attempting to access an undefined instance variable returns nil, but doesn't define that variable. They don't actually get defined until you write to them. attr_accessor relies on this behaviour and doesn't do anything except define a getter/setter.

You can verify this by checking out .instance_variables:

class Test
attr_accessor :something
end

A new instance of x has no instance variables:

x = Test.new # => #<Test:0xb775314c>
x.instance_variables # => []

Invoking the getter does not cause @something to become defined:

x.something # => nil
x.instance_variables # => []

Invoking the setter does cause @something to become defined:

x.something = 3 # => 3
x.instance_variables # => ["@something"]

Setting something back to nil doesn't cause instance_variables to revert, so we can be sure that the first empty array returned isn't simply a case of instance_variables omitting nil values:

x.something = nil # => nil
x.instance_variables # => ["@something"]

You can also verify that this isn't simply behaviour specific to attr_accessor:

class Test
def my_method

@x # nil

instance_variables # []

@x = 3

instance_variables # ["@x"]
end
end

Test.new.my_method

Dynamically building accessors in ruby on object initialization

You can create attributes with attr_accessor inside the initialize method. You only need to reach to it like below:

module Learning360
class User
def initialize(options = {})
options.each do |(k, v)|
self.class.attr_accessor(k)
send("#{k}=", v)
end
end
end
end

user = Learning360::User.new({ name: "Matz" })
puts user.name # Matz

It is also possible to use class name diectly just like User.attr_accessor(k).

Ruby - dynamically add property to class (at runtime)

The method_missing approach would work, but if you're going to use the accessors a lot after adding them, you might as well add them as real methods, like this:

class Client
def add_attrs(attrs)
attrs.each do |var, value|
class_eval { attr_accessor var }
instance_variable_set "@#{var}", value
end
end
end

This will make them work like normal instance variables, but restricted to just one client.

Ruby - How to set value for dynamic attribute in class

You should call

a.send "#{attr}=", 1
a.save!


Related Topics



Leave a reply



Submit