我在我的类中动态创建了一个实例变量:
class Mine
attr_accessor :some_var
def intialize
@some_var = true
end
def my_number num
self.instance_variable_set "@my_#{num}", num
end
end
如何将@my_#{num}
现在设为attr值?
e.g。我希望能够做到这一点:
dude = Mine.new
dude.my_number 1
dude.my_1
=> 1
答案 0 :(得分:27)
这个答案没有污染类空间,例如..如果我mine.my_number 4
那么Mine
的其他实例将不会得到my_4
方法...这是因为我们发生了使用对象的单例类而不是类。
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
答案 1 :(得分:24)
这可以使用__send__
来完成。在这里:
class Mine
attr_accessor :some_var
def intialize
@some_var = true
end
def my_number num
self.class.__send__(:attr_accessor, "my_#{num}")
self.__send__("my_#{num}=", num)
end
end
dude = Mine.new
dude.my_number 1
puts dude.my_1
=> 1
答案 2 :(得分:10)
易。您可以在my_number方法中动态定义属性读取器:
def my_number num
self.instance_variable_set "@my_#{num}", num
self.class.class_eval do
define_method("my_#{num}") { num }
end
end
看看它是否适合你
答案 3 :(得分:5)
这里有两个方法存在一个问题...如果在一个实例中设置了一个实例变量,它的访问器将可用于所有实例,因为你在self.class
而不是在self上定义方法。
dude = Mine.new
dude.my_number 1
puts dude.my_1
dudette = Mine.new
dudette.my_1 = 2 # works, but probably shouldn't
dudette.my_number 2
dude.my_2 = 3 # works, but probably shouldn't
您可能想要做的只是修改具有实例变量的实例:
class Mine
# ...
def my_number num
class << self
attr_accessor "my_#{num}"
end
self.send("my_#{num}=", num)
end
end
这样,实例变量只能访问为其创建的对象的访问器。我也没有打扰instance_variable_set,因为如果你正在设置一个访问器,那么我认为重用它会更好。但这是一种风格调用。最重要的是调用class << self
而不是self.class
。
答案 4 :(得分:3)
您可能想要使用OpenStruct:
require "ostruct"
class Mine < OpenStruct
end
dude = Mine.new
dude.my_number = 1
dude.my_number # => 1
我不知道为什么你希望dude.my_1
返回1 - 这不是能让你回到已有的东西吗?
答案 5 :(得分:0)
较旧的帖子,但我觉得它很有用,谢谢你。这是代码Dorkus Prime的答案,但也从哈希的名称\值中获取实例变量
@cookies = browser.cookies.to_a
@cookies.each do |cookie|
self.class.__send__(:attr_accessor, "#{cookie[:name]}")
self.__send__("#{cookie[:name]}=",cookie[:value])
end
答案 6 :(得分:0)
define_singleton_method
又是另一个解决方案:
class Mine
def my_number num
define_singleton_method("num_#{num}") { num }
end
end
所有这些解决方案的一个副作用是,如果用不同的数字多次调用它,最终将在对象上产生一堆方法:
dude = Mine.new
dude.my_number 1
dude.my_number 5
dude.my_1
=> 1
dude.my_5
=> 5
我们可以通过删除旧方法来解决此问题:
class Mine
def my_number num
old_num = @num
if @num
# need to use `old_num` local variable
# instance var scope is different inside `class_eval`
singleton_class.class_eval { remove_method("num_#{old_num}") }
end
@num = num
define_singleton_method("num_#{num}") { @num }
end
end