在属性名称中使用插值避免评估

问题描述

我正在定义自己的方法,该方法将使我可以将给定对象的多个属性更新为另一个对象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(调用公共方法,如果方法存在但为私有方法会引发错误)动态地调用方法。

car.public_send("entered_text_#{i}=",new_car.public_send("entered_text_#{i}"))
puts car.public_send("entered_text_#{i}")