First_or_create vs find_or_create_by

first_or_create кажется гораздо менее документированным, поэтому я задавался вопросом, было ли это только потому, что эти два метода являются синонимами.

Ответ 1

В принципе:

Foo.where(attributes).first_or_create

То же, что и:

Foo.find_or_create_by(attributes)

#first_or_create иногда неправильно понимается, поскольку люди ожидают его поиска по заданным атрибутам, но это не так. Ака

Foo.first_or_create(attributes)

Не будет искать foo, удовлетворяющий attributes. Он примет первый foo, если таковые имеются. Это полезно, если условия для поиска являются подмножеством тех, которые используются для создания. Ака

Foo.where(something: value).first_or_create(attributes)

Найти первый foo, где something: value. Если ни один не присутствует, он будет использовать attributes для его создания.

Ответ 2

Ответ @ndnenkov правильный, но я хотел бы find_or_create на том, почему я думаю, что можно использовать find_or_create:

Рассмотрим случай, когда Foo должен иметь attribute_subset_1 или attribute_subset_2 прежде чем его можно будет создать. Можно (псевдо) кодировать это как:

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

Это тот случай, когда я думаю, что find_or_create_by не работает... по крайней мере, не легко. Мне было бы любопытно услышать, если что-то видит это по-другому, но я нашел, что использование first_or_create идеально подходит для моих нужд.