在属性名称中使用插值(避免评估)
Using interpolation within an attribute name (avoiding eval)
我正在定义我自己的方法,允许我将给定对象的多个属性更新为另一个对象的多个属性 new_car
。许多属性具有相似的名称,例如“entered_text_1”、“entered_text_2”、“entered_text_3”直至“entered_text_10”(在下面的示例中,我最多只做了 3 个来说明)。
问题
想知道如何在属性名称本身中使用插值,例如 car.entered_text_"#{i}"
(这是不正确的)
期望的结果
下面的代码可以工作并且可以满足我的要求,但是我已经看到很多关于使用 eval
的警告 - 我想知道在这种情况下更好的选择是什么?
# class Car and class NewCar exist with the same attribute names (:entered_text_1, :entered_text_2, :entered_text_3)
def self.copy_attributes(car, new_car)
i = 1
until i > 3
eval("car.entered_text_#{i} = new_car.entered_text_#{i}")
puts eval("car.entered_text_#{i}")
i += 1
end
end
current_car = Car.new('White', 'Huge', 'Slow')
golf = NewCar.new('Red', 'Small', 'Fast')
copy_attributes(current_car, golf)
# => Red, Small, Fast
非常感谢!
您可以利用这样一个事实,像 user.name = 'John'
这样的赋值实际上是方法调用,可以这样写:user.name=('John')
,其中 name=
是方法的名称。我们可以使用 send
(调用任何方法)或 public_send
(调用 public 方法动态调用方法,如果方法存在但是私有的,将引发错误)。
car.public_send("entered_text_#{i}=", new_car.public_send("entered_text_#{i}"))
puts car.public_send("entered_text_#{i}")
我正在定义我自己的方法,允许我将给定对象的多个属性更新为另一个对象的多个属性 new_car
。许多属性具有相似的名称,例如“entered_text_1”、“entered_text_2”、“entered_text_3”直至“entered_text_10”(在下面的示例中,我最多只做了 3 个来说明)。
问题
想知道如何在属性名称本身中使用插值,例如 car.entered_text_"#{i}"
(这是不正确的)
期望的结果
下面的代码可以工作并且可以满足我的要求,但是我已经看到很多关于使用 eval
的警告 - 我想知道在这种情况下更好的选择是什么?
# class Car and class NewCar exist with the same attribute names (:entered_text_1, :entered_text_2, :entered_text_3)
def self.copy_attributes(car, new_car)
i = 1
until i > 3
eval("car.entered_text_#{i} = new_car.entered_text_#{i}")
puts eval("car.entered_text_#{i}")
i += 1
end
end
current_car = Car.new('White', 'Huge', 'Slow')
golf = NewCar.new('Red', 'Small', 'Fast')
copy_attributes(current_car, golf)
# => Red, Small, Fast
非常感谢!
您可以利用这样一个事实,像 user.name = 'John'
这样的赋值实际上是方法调用,可以这样写:user.name=('John')
,其中 name=
是方法的名称。我们可以使用 send
(调用任何方法)或 public_send
(调用 public 方法动态调用方法,如果方法存在但是私有的,将引发错误)。
car.public_send("entered_text_#{i}=", new_car.public_send("entered_text_#{i}"))
puts car.public_send("entered_text_#{i}")