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
Active Record with Delegate and Conditions
Error: While Executing Gem ... (Typeerror) Incompatible Marshal File Format (Can't Be Read)
Controlling Tor Client with Ruby
Can Activerecord Connect to Postgresql Remotely and Protect the Db Password
Ruby Amazon S3 Access Denied When Listing Buckets
Good Explanation of Ruby Object Model -- Mainly, 'Classes Are Objects'
Invoke Delayed_Job Capistrano Tasks Only on Specific Servers
Single Occurrence Event with Ice_Cube Gem Using Start_Time and End_Time
Rails Activerecord Query Date Range
What Are Tainted Objects, and When Should We Untaint Them
How to Mock Aws Sdk (V2) with Rspec
Differencebetween 'Size' and 'Length' Methods
Split Array Up into N-Groups of M Size
What's the Cleanest Way to Override Activerecord's Find for Both Models and Collections