Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails4: How to trigger the callback for attr_accessor while using accepts_nested_attributes_for

Please check the pseudocode:

class Team
  has_many :users
  accepts_nested_attributes_for :users, allow_destroy: true
end

class User
  belongs_to :team
  has_many :addresses
  accepts_nested_attributes_for :addresses
  attr_accessor :dummy

  before_validation :generate_addresses_attributes
  def generate_addresses_attributes
    # Use the dummy value to set the addresses_attributes
  end
end

Now when execute team.update(users_attributes: [{"0" => { dummy: "changed!" }}])(the other fields will not change except the dummy attribute), it will not trigger the #generate_addresses_attributes callback since it think there is nothing changes, no save, no callback...

So my question is how to trigger the callback for the virtual attributes, or maybe force save for accepts_nested_attributes_for.

Thank you!

like image 827
Zernel Avatar asked Mar 16 '15 09:03

Zernel


2 Answers

Finally, I found two solution:

  1. add callback in Team model to trigger the callback functional manually

  2. use the attribute_will_change! to override the setter method:

    class User
      belongs_to :team
      has_many :addresses
      accepts_nested_attributes_for :addresses
      attr_accessor :dummy
    
      def dummy=(value)
        attribute_will_change!("dummy") if @dummy != value
        @dummy = value
      end
    
      ...
    end
    
like image 149
Zernel Avatar answered Oct 09 '22 11:10

Zernel


I found that for Rails 5.1+ attribute works better than attr_accessor for this use case.

attribute dirties up the object, thus triggering callbacks when saving it.

class User
  belongs_to :team
  has_many :addresses
  accepts_nested_attributes_for :addresses
  attribute :dummy, :string

  before_validation :generate_addresses_attributes
  def generate_addresses_attributes
    # Use the dummy value to set the addresses_attributes
  end
end
like image 27
Andrei Erdoss Avatar answered Oct 09 '22 12:10

Andrei Erdoss