覆盖默认访问者时更新属性时出现问题

时间:2014-03-07 01:02:44

标签: ruby-on-rails ruby methods overwrite accessor

我正在使用Ruby on Rails 4,我用这种方式覆盖了一些默认的访问器方法:

class Article < ActiveRecord::Base
  def title
    self.get_title
  end

  def content
    self.get_content
  end
end

self.get_titleself.get_content方法会返回一些计算值,如下所示(注意:has_one_association:has_one ActiveRecord::Association

def get_title
  self.has_one_association.title.presence || read_attribute(:title)
end

def get_content
  self.has_one_association.content.presence || read_attribute(:content)
end

当我从数据库中找到并阅读@article个实例时,所有实例都按预期工作:titlecontent值分别与self.has_one_association.titleself.has_one_association.content一起输出。

但是,我发现当属性分配给@article时,@article对象未按预期更新。也就是说,在我的控制器中给出了:

def update
  # params # => {:article => {:title => "New title", :content => "New content"})}

  ...

  # BEFORE UPDATING
  # @article.title   # => "Old title"   # Note: "Old title" come from the 'get_title' method since the 'title' accessor implementation
  # @article.content # => "Old content" # Note: "Old content" come from the 'get_content' method since the 'content' accessor implementation

  if @article.update_attributes(article_params)

    # AFTER UPDATING
    # @article.title   # => "Old title"
    # @article.content # => "Old content"

    ...
  end
end

def article_params
  params.require(:article).permit(:title, :content)
end

即使@article有效,它还没有在数据库中更新(!),我想是因为我覆盖访问器的方式和/或Rails的方式{{1 }}。当然,如果我删除了getter方法,那么一切都按预期工作。

这是一个错误吗?我该如何解决这个问题?或者,我应该采用另一种方法来实现我想要完成的任务吗?


另见https://github.com/rails/rails/issues/14307

1 个答案:

答案 0 :(得分:0)

在这种情况下,

update_attributes只是调用title=content=save的快捷方式。如果您没有覆盖设置者,只是吸气剂,那就不相关了。

您正确地更新了这些值,但Rails并没有读取您正在设置的值,原因是覆盖了要从关联中读取的getter。您可以通过选中@article.attributes或查看数据库中的文章记录来验证这一点。

此外,您的get_content正在尝试read_attribute(:title)而不是:content