first_or_create vs find_or_create_by
@ndnenkov's answer is right on but I wanted to expand on why I think one might use find_or_create
:
Consider the case when Foo must have either attribute_subset_1
or attribute_subset_2
before it can be created. One could (pseudo)code this as:
if attribute_subset_1 then
Foo.where(attribute_subset_1).first_or_create(attributes)
elsif attribute_subset_2 then
Foo.where(attribute_subset_2).first_or_create(attributes)
else
Raise error " insufficient attributes"
end
This is a case where I think find_or_create_by
does not work...at least not easily. I would be curious to hear if anything sees this differently but for me I found this use of first_or_create
perfect for my needs.
Basically:
Foo.where(attributes).first_or_create
Is the same as:
Foo.find_or_create_by(attributes)
#first_or_create
is sometimes misunderstood as people expect it to search by the attributes given, but that is not the case. Aka
Foo.first_or_create(attributes)
Will not search for a foo
that satisfies the attributes
. It will take the first foo
if any are present. It's useful if the conditions for finding are a subset of those used for creation. Aka
Foo.where(something: value).first_or_create(attributes)
Will find the first foo
where something: value
. If none is present, it will use attributes
to create it.