使用虚拟属性接受嵌套属性

时间:2011-04-09 00:44:53

标签: ruby-on-rails activerecord

我有一个Project模型,它接受任务的嵌套属性。而Task有一个虚拟属性“name”。因此,每次更改名称时,它都会在更新前保持为encrypted_task_name。在项目编辑页面上,表单具有任务名称的输入字段(而不是encrypted_task_name)。当我更改名称并且因为name是虚拟属性时,Rails不检测任务中的更改,并且在更新Project时不会更新该任务。

如果在项目更新期间更改了虚拟属性,如何确保保存任务?

我不想使用的一个选项是:autosave =>在task.rb上为true,因为我的任务很少更新。

4 个答案:

答案 0 :(得分:26)

我遇到了同样的问题。使用:autosave => true甚至不适合我。我设法通过将attribute_will_change!(:my_virtual_attribute)添加到我的虚拟属性的编写器来解决它。所以,在你的情况下:

class Task < ActiveRecord::Base
  ..
  def name=(the_name)
    attribute_will_change!(:name)
    ..
  end
  ..
end

这会将对象标记为未更改或脏,并使update_attributes正确保存嵌套模型。

链接:

http://apidock.com/rails/ActiveRecord/Dirty/attribute_will_change%21 http://ryandaigle.com/articles/2008/3/31/what-s-new-in-edge-rails-dirty-objects

答案 1 :(得分:0)

一般来说,我推荐RailsCasts.com - 第167和第16集

http://railscasts.com/episodes/167-more-on-virtual-attributes
http://railscasts.com/episodes/16-virtual-attributes

在第167集中,Ryan做了类似的事情

如果这没有帮助,您可以发布项目和任务模型的相关代码吗?

答案 2 :(得分:0)

查看Attribute Filters gem。它通过添加attr_virtual DSL关键字来处理虚拟属性跟踪(自动包装setter方法),并允许您执行其他操作,例如声明性过滤属性:

class User < ActiveRecord::Base
  include ActiveModel::AttributeFilters::Common::Split

  split_attribute   :real_name => [ :first_name, :last_name ]
  before_validation :filter_attributes

  attr_virtual  :real_name
  attr_accessor :real_name
end

答案 3 :(得分:0)

对于Rails 5.1及更高版本,建议使用attribute而不是attr_accessor,因为它会使对象变脏,从而触发验证。

class Task < ActiveRecord::Base
  attribute :name, :string
end