Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accepts Nested Attribute with a virtual attribute

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.

like image 665
Swamy g Avatar asked Apr 09 '11 00:04

Swamy g


People also ask

What are nested attributes?

Nested attributes are a way of applying sub-categories to your attributes. For instance, instead of having a single searchable attribute price , you may set up some sub-categories: price.net , price.

What is a virtual attribute?

A Virtual Attribute is a type of AttributeTypes in which the Attribute Value are not actually stored in the Back-end but are rather dynamically generated in some manner. Virtual Attributes may or may NOT be part of the entry's defined ObjectClass Type and sometimes any ObjectClass Type.

What is nested attributes rails?

Rails provide a powerful mechanism for creating rich forms called 'nested attributes' easily. This enables more than one model to be combined in forms while maintaining the same basic code pattern with simple single model form. Nested attributes allow attributes to be saved through the parent on associated records.


2 Answers

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
like image 92
Andrei Erdoss Avatar answered Nov 15 '22 20:11

Andrei Erdoss


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

like image 25
David van Geest Avatar answered Nov 15 '22 21:11

David van Geest