As diferenças entre .build, .create e .create! e quando eles devem ser usados?


167

Então, eu tenho visto pessoas usando .build, .create e .create! nos controladores cada vez mais ultimamente. Qual é a diferença de apenas usar .new e passig o objeto param'd e depois .save? Existem prós e contras? O uso desses outros métodos oferece benefícios?

Respostas:


234

Existem algumas diferenças, mas elas não são grandes:

  1. .createé equivalente a .newseguido por .save. É apenas mais sucinto.
  2. .create!é equivalente a .newseguido por.save! (gera um erro se o salvamento falhar). Também é um pouquinho mais curto
  3. Eu acho que .buildé principalmente um apelido para .new. Ele funciona de uma maneira no Rails 3 e uma outra maneira em Rails <3.x

A parte mais importante, no entanto, é que esses métodos podem ser chamados por meio de uma associação ( has_many, etc.) para vincular automaticamente os dois modelos.


1
Eu escolhi essa como a resposta mais correta por causa da menção de poder vincular os modelos associados a eles - essa é uma diferença interessante e importante que penso em usar .new e .save. O que exige um pouco de trabalho extra. Obrigado.
— Tim Knight

11
Pequenos esclarecimentos sobre o 3 - build fazem um pouco mais do que apenas novos - ele também define o link da associação.
— Dois Bits Gangster

116
O Build é diferente de New. Mas a diferença não é que ele define o link de associação (o New também faz isso para a nova instância). A diferença é que o Build preenche o chamador com a nova instância, mas New não. Por exemplo: Wall.posts.new fornece uma nova postagem associada ao seu Wall, mas o Wall.posts ainda está vazio após esta chamada. O Wall.posts.build fornece uma nova postagem associada ao seu Wall, e agora o seu Wall.posts tem uma postagem.
— Amin Ariana

3
Não é apenas um alias agora, sem funcionalidade especial?
— Gabriele Cirulli 8/08/13

14
No Rails 4, acabei de fazer o check-in no console. wall.posts.new e wall.posts.build estão preenchendo o objeto wall da mesma maneira. Significa que após wall.posts.new, wall.posts não está vazio conforme reivindicado no comentário de Amin.
— Bot

35

Embora seja correto que createchama newe, em seguida, savehá uma grande diferença entre as duas alternativas em seus valores de retorno.

Saveretorna um trueou falsedependendo se o objeto foi salvo com sucesso no banco de dados ou não. Isso pode ser usado para controle de fluxo, conforme o primeiro exemplo da pergunta acima.

Createretornará o modelo independentemente de o objeto ter sido salvo ou não. Isso tem implicações para o código acima, pois a ramificação superior da ifinstrução sempre será executada mesmo se o objeto falhar nas validações e não for salvo.

Se você usa createa lógica de ramificação, corre o risco de falhas silenciosas, o que não é o caso se você usar new+ save.

create! não sofre do mesmo problema que gera e exceção se o registro for inválido.

A createalternativa pode ser útil em controladores onde respond_withé usado para respostas de API (JSON / XML). Nesse caso, a existência de erros no objeto fará com que os erros sejam retornados na resposta com um status de unprocessable_entity, que é exatamente o que você deseja de uma API.

Eu sempre usaria a opção new+ savepara html, especialmente se você estiver contando com o valor de retorno para controle de fluxo.


6

#create é uma versão mais curta do novo e salva. #crio! está lançando uma exceção se a validação não for positiva.


5

Eu segundo as respostas acima. Além disso create, não se pode passar falsecomo argumento com o qual você pode fazer save. Passar falsecomo argumento ignorará todas as validações de trilhos

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.