在保存之前插入属性的键

Interpolating an attribute's key before save

我正在使用 Rails 4 并有一个 Article 模型,该模型具有 answerside_effectsbenefits 作为属性。

我正在尝试创建一个 before_save 方法来自动查看副作用和好处,并创建与网站上另一篇文章相对应的链接。

我不想编写两个几乎相同的方法,一个用于副作用,一个用于好处,我想使用相同的方法并检查以确保属性不等于 answer

到目前为止我有这样的东西:

before_save :link_to_article

private 

def link_to_article
  self.attributes.each do |key, value|
    unless key == "answer" 
      linked_attrs = []
      self.key.split(';').each do |i|
        a = Article.where('lower(specific) = ?', i.downcase.strip).first
        if a && a.approved?
          linked_attrs.push("<a href='/questions/#{a.slug}' target=_blank>#{i.strip}</a>")
        else
          linked_attrs.push(i.strip)
        end
      end
      self.key = linked_attrs.join('; ')
    end
  end
end

但是像那样链接密钥给了我 undefined method 'key'.

如何在属性中进行插值?

在这一点中:self.key 你要求它从字面上调用一个名为 key 的方法,但你想要的是调用存储在变量键中的方法名称.

您可以改用:self.send(key),但这可能有点危险。 如果有人在他们的浏览器上破解了一个新表单来向您发送名为 delete! 的属性,您不希望使用 send 意外调用它,因此最好使用 read_attributewrite_attribute.

示例如下:

def link_to_article
  self.attributes.each do |key, value|
    unless key == "answer" 
      linked_attrs = []
      self.read_attribute(key).split(';').each do |i|
        a = Article.where('lower(specific) = ?', i.downcase.strip).first
        if a && a.approved?
          linked_attrs.push("<a href='/questions/#{a.slug}' target=_blank>#{i.strip}</a>")
        else
          linked_attrs.push(i.strip)
        end
      end
      self.write_attribute(key, linked_attrs.join('; '))
    end
  end
end

我还建议在控制器中使用强属性,以确保您只允许允许的属性集。


OLD(在我知道这将用于所有属性之前)

那是说...为什么要遍历每个属性并且只在属性被调用时才做某事 answer?为什么不直接浏览属性并直接查看答案呢?

例如:

def link_to_article
  linked_attrs = []
  self.answer.split(';').each do |i|
    a = Article.where('lower(specific) = ?', i.downcase.strip).first
    if a && a.approved?
      linked_attrs.push("<a href='/questions/#{a.slug}' target=_blank>#{i.strip}</a>")
    else
      linked_attrs.push(i.strip)
    end
  end
  self.answer = linked_attrs.join('; ')
end