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'}}
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
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)
.
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
Set dynamic values when generating setter methods using attr_accessor in ruby
attr_accessor
has no magic embedded. For each of params passed to it, it basically executes something like (the code is simplified and lacks necessary checks etc):
def attr_accessor(*vars)
vars.each do |var|
define_method var { instance_variable_get("@#{var}") }
define_method "#{var}=" { |val| instance_variable_set("@#{var}", val) }
end
end
That said, the attr_accessor :var1, :var2
DSL simply brings new 4 plain old good ruby methods. For what you are asking, one might take care about defining these methods (or some of them, or none,) themselves. For instance, for cumbersome setting with checks one might do:
attr_reader :variable # reader is reader, no magic
def variable=(val) do
raise ArgumentError, "You must be kidding" if val.nil?
@variable = val
end
The above is called as usual:
instance.variable = 42
#⇒ 42
instance.variable = nil
#⇒ ArgumentError: You must be kidding
How to declare custom attribute accessor with dynamic argument in Ruby?
footnote_attrs :title, :body
is a method invocation. If you want to call the method in your class like this:
class Foo
footnote_attrs :title, :body
end
You have to define the method accordingly:
class Foo
def self.footnote_attrs(*args)
@footnote_attrs = args unless args.empty?
@footnote_attrs
end
# if footnote_attrs is to be accessed like an instance method
def footnote_attrs
self.class.footnote_attrs
end
footnote_attrs :title, :body
end
Foo.footnote_attrs #=> [:title, :body]
footnote_attrs #=> [:title, :body]
The implementation is very basic. If the method is called with arguments, it sets the instance variable accordingly. If it is called without arguments, it just returns it.
You might want to return an empty array if footnote_attrs
has not been called yet (currently it would return nil
). It might also be a good idea to return a copy (dup
) instead of the actual array to prevent modification.
Dynamically assigning attributes using strings as attribute setters in Ruby
Use thing.send("#{k}=", v)
instead.
How to access Model attributes dynamically in a loop in ruby?
You can do like this:
item.send((attr + "="), values from some other source)
or:
hash = {}
['item_url','item_url','item_label'].each do |attr|
hash[attr] = value
end
item.attributes = hash
Related Topics
How to Deal with the Conflict Between Activesupport::JSON and the JSON Gem
How to Ensure That Ruby Uses an Openssl Not Vulnerable to Heartbleed
Do Ruby 'Require' Statements Go Inside or Outside the Class Definition
Why Many People Use "-%>" Instead of "%>" in Rails
Generate a Powerset of a Set Without Keeping a Stack in Erlang or Ruby
Tell Ruby Program to Wait Some Amount of Time
Rails - the System Cannot Find the Path Specified
Error While Installing Nokogiri (1.6.7) on El Capitan
Active Record - Find Records Which Were Created_At Before Today
How to Remove Gem from Ruby on Rails Application
Finding the Element of a Ruby Array with the Maximum Value for a Particular Attribute
Is It Possible for Rspec to Expect Change in Two Tables
Portable Ruby on Rails Environment
How to Map and Remove Nil Values in Ruby
How to Have Multiple Versions of Ruby and Rails, and Their Combinations on Windows
Error Installing Nokogiri on Bundle Install But Already Installed