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

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}")