If I have this class:
class A
attr_accessor :b,:c,:d
end
and this code:
a = A.new
h = {"b"=>10,"c"=>20,"d"=>30}
is it possible to initialize the object directly from the hash, without me needing to go over each pair and call instance_variable_set
? Something like:
a = A.new(h)
which should cause each instance variable to be initialized to the one that has the same name in the hash.
You can define an initialize function on your class:
class A
attr_accessor :b,:c,:d
def initialize(h)
h.each {|k,v| public_send("#{k}=",v)}
end
end
Or you can create a module and then "mix it in"
module HashConstructed
def initialize(h)
h.each {|k,v| public_send("#{k}=",v)}
end
end
class Foo
include HashConstructed
attr_accessor :foo, :bar
end
Alternatively you can try something like constructor
OpenStruct
is worth considering:
require 'ostruct' # stdlib, no download
the_hash = {"b"=>10, "c"=>20, "d"=>30}
there_you_go = OpenStruct.new(the_hash)
p there_you_go.c #=> 20
instance_variable_set
is intended for this kind of use case:
class A
def initialize(h)
h.each {|k,v| instance_variable_set("@#{k}",v)}
end
end
It's a public method, so you could also call it after construction:
a = A.new({})
a.instance_variable_set(:@foo,1)
But note the implied warning in the documentation:
Sets the instance variable names by symbol to object, thereby frustrating the efforts of the class’s author to attempt to provide proper encapsulation. The variable did not have to exist prior to this call.
精彩评论