Reputation: 2166
I have a Project model which accepts nested attributes for tasks. And Task has a virtual attribute "name". So every time I change the name, it gets persisted as encrypted_task_name before update. On the project edit page the form has a input field for task name (and not encrypted_task_name). When I change the name and since name is a virtual attribute, Rails doesn't detect a change in Task and doesn't update that task while updating Project.
How do I make sure that task is saved even if its virtual attributes are changed during Project update?
One option that I don't want to use is :autosave => true on task.rb since I task is rarely updated.
Upvotes: 10
Views: 3344
Reputation: 1643
For Rails 5.1 and up it's advisable to use attribute
instead of attr_accessor
as it dirties up the object, thus triggering the validation.
class Task < ActiveRecord::Base
attribute :name, :string
end
Upvotes: 2
Reputation: 1147
Check out Attribute Filters gem. It takes care of virtual attributes tracking (automagically wrapping setter methods) by adding attr_virtual
DSL keyword and lets you do other things, like declarative filtering of attributes:
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
Upvotes: 0
Reputation: 1997
I ran into the same problem. Using :autosave => true
didn't even work for me. I managed to solve it by adding attribute_will_change!(:my_virtual_attribute)
to the writer for my virtual attribute. So, in your case:
class Task < ActiveRecord::Base
..
def name=(the_name)
attribute_will_change!(:name)
..
end
..
end
This marks the object as unchanged or dirty, and that makes update_attributes save the nested model correctly.
Links:
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
Upvotes: 26
Reputation: 33752
In general, I'd recommend RailsCasts.com - episodes 167 and 16
http://railscasts.com/episodes/167-more-on-virtual-attributes and
http://railscasts.com/episodes/16-virtual-attributes
In episode 167, Ryan does something very similar
If this doesn't help, could you post the relevant code for your Project and Task models?
Upvotes: 0