Различия между .build, .create и .create! и когда они должны быть использованы?

167

Так что я вижу людей , используя .build, .createи .create!в своих контроллерах все больше и больше в последнее время. В чем разница с использованием .newи передачей объекта param'd, а затем .save? Есть ли плюсы и минусы? Использование этих других методов дает преимущества?

Тим Найт
источник

Ответы:

234

Есть пара отличий, но они не большие:

  1. .createэквивалентно .newпоследующим .save. Это просто более кратко.
  2. .create!эквивалентно .newпоследующему .save!(выдает ошибку, если сохранение не удается). Это также просто немного короче
  3. Я думаю, что .buildэто в основном псевдоним для .new. В Rails 3 он работает одним способом, а в Rails <3.

Однако наиболее важной частью является то, что эти методы могут вызываться через ассоциацию ( has_manyи т. Д.) Для автоматической связи двух моделей.

zenazn
источник
1
Я выбрал этот как наиболее правильный ответ из-за упоминания о возможности связать связанные модели с ними - это интересная и важная разница, которую я думаю над использованием .new и .save. Что требует немного дополнительной работы. Спасибо.
Тим Найт
11
Небольшое разъяснение по 3 - build делает немного больше, чем просто новое - оно также устанавливает связь ассоциации.
Двух битный гангстер
116
Сборка отличается от новой. Но разница не в том, что он устанавливает связь ассоциации (New делает то же самое для нового экземпляра). Разница в том, что Build заполняет вызывающую сторону новым экземпляром, а New - нет. Так, например: Wall.posts.new дает вам новое сообщение, связанное с вашей стеной, но Wall.posts все еще пусто после этого вызова. Wall.posts.build дает вам новое сообщение, связанное с вашей стеной, и теперь у ваших Wall.posts есть одно сообщение.
Амин Ариана
3
Разве это не псевдоним сейчас, без специальной функциональности?
Габриэле Цирулли,
14
В Rails 4 я только что проверил в консоли. wall.posts.new и wall.posts.build оба заполняют объект стены одинаково. Значит после wall.posts.new, wall.posts не пусто, как утверждается в комментарии Амина.
Бот
35

Хотя это правильно, что createвызовы, newа затем saveесть большая разница между двумя альтернативами в их возвращаемых значениях.

Saveвозвращает либо trueили в falseзависимости от того, был ли объект успешно сохранен в базе данных или нет. Это может затем использоваться для управления потоком согласно первому примеру в вопросе выше.

Createвернет модель независимо от того, был ли объект сохранен или нет. Это имеет значение для приведенного выше кода в том, что верхняя ветвь ifоператора всегда будет выполняться, даже если объект не прошел валидацию и не был сохранен.

Если вы используете createлогику ветвления, вы рискуете молчаливых сбоев, что не так, если вы используете new+ save.

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

createАльтернатива может быть полезной в контроллерах , где respond_withиспользуются API (JSON / XML) ответы. В этом случае наличие ошибок в объекте приведет к тому, что ошибки будут возвращены в ответе со статусом unprocessable_entity, который является именно тем, что вы хотите от API.

Я бы всегда использовал опцию new+ saveдля html, особенно если вы полагаетесь на возвращаемое значение для управления потоком.

nmott
источник
6

# Создать более короткую версию новой и сохранить. #Создайте! создает исключение, если проверка не была положительной.

Rkj
источник
5

Я бы второй ответ выше. Кроме того create, нельзя falseприводить в качестве аргумента, что вы можете сделать с save. Передача falseв качестве аргумента пропустит все проверки рельсов

Винет Прадхан
источник