Accepts a nested attribute with a virtual attribute

I have a Project model that accepts nested attributes for tasks. And the task has a virtual attribute "name". Therefore, every time I change the name, it is saved as encrypted_task_name before updating. On the project editing page, the form has an input field for the name of the task (and not encrypted_task_name). When I change the name and since the name is a virtual attribute, Rails does not detect a change in the Task and does not update this task when updating Project.

How can I guarantee that the task will be saved even if its virtual attributes are changed during the update of Project?

One option that I don't want to use is: autosave => true on task.rb, since I rarely update.

+6
source share
3 answers

I ran into the same problem. Usage :autosave => true didn't even work for me. I was able to solve this problem by adding attribute_will_change!(:my_virtual_attribute) to the author for my virtual attribute. So in your case:

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

This means that the object is immutable or dirty, and this makes update_attributes the correct way to save the nested model.

References:

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

+23
source

All in all, I would 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 does not help, can you post the appropriate code for your projects and task models?

0
source

Check gem attribute filters . It tracks virtual attribute tracking (automatically wrapping setter methods) by adding the attr_virtual DSL keyword and letting you do other things, such as declarative attribute filtering:

 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 
0
source

Source: https://habr.com/ru/post/885541/


All Articles