Saturday, 15 January 2011

ruby on rails - Why isn't ActiveRecord's autosave working on my association? -



ruby on rails - Why isn't ActiveRecord's autosave working on my association? -

i have activerecord class looks this.

class foo belongs_to :bar, autosave: true before_save :modify_bar ... end

if logging, see bar beingness modified, changes not saved. what's wrong?

the problem here autosave: true sets normal before_save callback, , before_save callbacks run in order they're created.**

therefore, tries save bar, has no changes, then calls modify_bar.

the solution ensure modify_bar callback runs before autosave. using prepend alternative that.

class foo belongs_to :bar, autosave: true before_save :modify_bar, prepend: true ... end

alternative solutions reverse order of belongs_to , before_save statements, or explicitly save bar @ end of modify_bar method instead of using autosave option.

thanks danny burkes helpful blog post.

** also, they're run after after_validation callbacks , before before_create callbacks - see docs.

update

here's 1 way check order of such callbacks.

describe "sequence of callbacks" let(:sequence_checker) { sequencechecker.new } before :each foo.stub(:bar).and_return(sequence_checker) end "modifies bar before saving it" # run before_save callbacks , halt before saving foo.run_callbacks(:save) { false } # test 1 of next # # if these methods should have been called expect(sequence_checker.called_methods).to eq(%w[modify save]) # if there may other methods called in between expect(sequence_checker.received_in_order?('modify', 'save')).to be_true end end

using supporting class:

class sequencechecker attr_accessor :called_methods def initialize self.called_methods = [] end def method_missing(method_name, *args) called_methods << method_name.to_s end def received_in_order?(*expected_methods) expected_methods.map!(&:to_s) called_methods & expected_methods == expected_methods end end

ruby-on-rails ruby callback rails-activerecord

No comments:

Post a Comment