Swamy g
Swamy g

Reputation: 2166

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.

Upvotes: 10

Views: 3344

Answers (4)

Andrei Erdoss
Andrei Erdoss

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

siefca
siefca

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

David van Geest
David van Geest

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

Tilo
Tilo

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

Related Questions