How to stub save but run the callbacks in the ActiveRecord
TLDR; you can use ActiveSupport::Callbacks#run_callbacks method to run the callbacks manually.
Recently I moved some logic to the ActiveRecord's before_save
callback because the logic was tightly coupled to how the model is stored in database and it should be run before each saving to the database to retains models's integrity.
class Activity < ActiveRecord::Base
has_one :trackable
has_one :topic
before_save :set_topic_from_trackable
# ...
end
However moving this logic to the callback broke my spec for Activity.track
method.
describe Activity do
let(:topic) { Topic.new }
let(:trackable) { Comment.new(topic: topic))
before do
activity = Activity.new
allow( activity ).to receive(:save!)
allow( Activity ).to receive(:new) { activity }
end
describe '.track' do
subject{ Activity.track(comment) }
it "sets topic from trackable automatically"
expect( subject ).to have_received(:save!)
expect( subject.trackable ).to eql trackable
expect( subject.topic ).to eql trackable.topic
end
end
end
How we can fix that? Well there is a run_callbacks method at ActiveRecord
, which I've found during solving this issue and it can be used like this: some_model.run_callbacks(:save, :before)
. So I've just add this to the activity.save
stub and the spec is green again!
allow( activity ).to receive(:save!) { activity.run_callbacks(:save) }
Written by Vojtěch Kusý
Related protips
Have a fresh tip? Share with Coderwall community!
Post
Post a tip
Best
#Activerecord
Authors
Sponsored by #native_company# — Learn More
#native_title#
#native_desc#