Ruby: Dynamically Generate Attribute_Accessor

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



Leave a reply



Submit