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.
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