I'm writing specs for some software and getting a weird behavior: In the method I'm testing, I'm calling:
MyModel.where(special_identifier: opts[:ident]).first || MyModelBuilder.new(m).build
(note I don't want first_or_create or first_or_new since I'm using explicit builders here). When I query MyModel.where(...)
I should be getting back an ActiveRecord::Relation
object, which is how it behaves in prod, dev, console, etc. However, when running the specs, where
returns a MyModel
object. Is this a bug, am I missing something?
As @DVG said in the comments, MyModel.where(...)
returns a relation, but calling .first
or .last
on it should return an instance, not a relation. Similarly, if the where returns more than one record, then .limit(...)
, .to_a
, or .all
on the relation would return the set of records.
If you are doing MyModel.where(...)
and it is definitely not returning a relation, then you need to figure out where that is happening:
if !MyModel.where('').is_a? ActiveRecord::Relation
raise "where was defined in #{MyModel.method(:where).source_location}"
end
That raise could be a fail
instead, if in a spec.
If that doesn't work, see this answer for more ways to get the source of the method.
Now if .first
returns nil, then your code:
MyModel.where(special_identifier: opts[:ident]).first || MyModelBuilder.new(m).build
is going to return whatever MyModelBuilder.new(m).build
returns (or it might raise something).