通过字符串引用对象属性

时间:2012-05-25 16:52:35

标签: ruby-on-rails ruby

我正在尝试干掉我需要在三个不同属性上执行相同任务的方法。像这样:

if !@item.picture.blank?
  picture_copy = Picture.new
  picture_copy.save!
  item_copy.picture = picture_copy
end

if !@item.picture_for_x.blank?
  picture_for_x_copy = PictureForX.new
  picture_for_x_copy.save!
  item_copy.picture_for_x = picture_for_x_copy
end

if !@item.picture_for_y.blank?
  picture_for_y_copy = PictureForY.new
  picture_for_y_copy.save!
  item_copy.picture_for_y = picture_for_y_copy
end

所以基本上我运行相同的代码,但实例化不同的对象,然后将它们分配给不同的属性。感觉应该有一种方法来使用反射干掉这个视图。有没有办法可以将这些属性和对象称为传递给辅助方法的字符串?

由于各种原因,我不能只使用.clone或.dup:主要是因为涉及二进制文件指针,我还需要深层拷贝。

2 个答案:

答案 0 :(得分:2)

{
  picture:       Picture,
  picture_for_x: PictureForX,
  picture_for_y: PictureForY
}.each do |name,klass|
  if !@item.send(name).blank?
    copy = klass.new
    copy.save!
    item_copy.send("#{name}=",copy)
  end
end

请记住,在Ruby中, 没有外部可用的属性或属性,只是方法(您可以选择不使用括号调用,以便看起来就像您正在访问一个属性,有时可能只是返回一个实例变量的值。)

Object#send是一种神奇的方法,可让您根据存储在变量中的名称调用方法。

答案 1 :(得分:1)

def picture_for_x_blank?(s = "")
  s = "_for_#{s}" unless s.empty?
  m = "picture#{s}"

  unless @item.send(m).blank?
    copy = Kernel::const_get(m.camelize).new
    copy.save!
    item_copy.send("#{m}=", copy)
  end
end

picture_for_x_blank?
picture_for_x_blank?("x")
picture_for_x_blank?("y")