Last active
April 22, 2024 16:56
-
-
Save antillas21/11232600 to your computer and use it in GitHub Desktop.
Stubbing an ActiveRecord::Relation object
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# first we create an empty ActiveRecord::Relation object | |
relation = Model.where(attribute: value) | |
# then we make the relation stub the :[] method | |
# and return whatever values we need | |
relation.stub(:[]).and_return( Model.new({attrs: values})] ) | |
# of course, we can make this too | |
# instead of the step above | |
record = double("Model", :foo => 'bar', :bar => 'baz') | |
relation.stub(:[]).and_return([record]) | |
# last, we make our Model class stub the :where method | |
# and return the relation object we created | |
Model.stub(:where).and_return(relation) | |
# additionally we can have use case specific behavior | |
model_instance.stub(:method_or_scope_that_returns_collection) { relation } |
Furthermore you can mock a
has_many
relation (which was my use case) by doingallow(record).to receive(:related_records).and_wrap_original do |original, *args, &block| relation = original.call(*args, &block) relation.stub(:records).and_return(my_custom_array_of_related_records) relation end
I wonder why your code didn't work in my particular case. Could it be related to my call of relation = original.call(*args, &block)
always returning a nil
object?
relation.stub(:records)
raises unknown #stub method for #<ActiveRecord::Associations::CollectionProxy []>
But I found a way out of this, not sure if ideal, though:
allow(record).to receive(:related_records).and_wrap_original do |original, *args, &block|
relation = original.call(*args, &block)
relation << custom_records
allow(relation).to receive(:scope_of_related_class).and_return(scoped_custom_records)
relation
end
Mocking only the has_many
return was insufficient for my case because I also needed to mock the scope call.
record.related_records.scope_of_related_class
Thanks!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This simply doesn't work - accessing
relation[0]
will return an array of records, rather than a single record. Furthermore,.any?
,.first
,.last
, etc. are completely nonfunctional.The correct way to do this is
Furthermore you can mock a
has_many
relation (which was my use case) by doing