Trilhos: dependente =>: destroy VS: dependente =>: delete_all

192

Nos guias de trilhos, é descrito assim:

Além disso, os objetos serão destruídos se estiverem associados :dependent => :destroye excluídos se estiverem associados a:dependent => :delete_all

Certo, legal. Mas qual é a diferença entre ser destruído e excluído? Eu tentei os dois e parece fazer a mesma coisa.

Sergey
fonte

Respostas:

200

A diferença está no retorno de chamada.

O :delete_allé feito diretamente no seu aplicativo e excluído pelo SQL:

DELETE * FROM users where compagny_id = XXXX

Com o :destroy, há uma instanciação de todos os seus filhos. Portanto, se você não puder destruí-lo ou se cada um tiver o seu :dependent, seus retornos de chamada poderão ser chamados.

shingara
fonte
83
A instanciação e o chamado de destruição em cada um dos objetos filhos serão lentos se você tiver muitos filhos (e n ^ 2 se tiver netos e assim por diante). delete_all é o tipo de solução "nuke it from orbit", na qual você não se importa / não tem nenhum antes / depois de destruir retornos de chamada nos modelos.
Ryan Bigg
131

Na associação de modelo do Rails, você pode especificar a :dependentopção, que pode assumir uma das três formas a seguir:

  • :destroy/:destroy_allOs objetos associados são destruídos ao lado desse objeto chamando seu destroymétodo
  • :delete/:delete_allTodos os objetos associados são destruídos imediatamente sem chamar seu :destroymétodo
  • :nullifyAs chaves estrangeiras de todos os objetos associados são definidas como NULLsem chamar seus saveretornos de chamada
John Topley
fonte
2
Consulte api.rubyonrails.org/classes/ActiveRecord/Associations/… (procure por "anular") para obter os rdocs autoritativos.
mrm
21
Desde o Rails 3.0, também é possível especificar :restrict. Se definido como: restringir este objeto, não poderá ser excluído se houver algum objeto associado.
precisa saber é o seguinte
17
não há opções :deleteou :destroy_allpelo que parece? A opção: dependent espera que seja: destruir,: delete_all,: anular ou: restringir (: delete)
Mike Campbell
2
@ MikeCampbell, :deletee as :destroy_allopções não existem. No entanto, existem métodos de classe nos modelos chamados deletee, destroy_allportanto, esse pode ser o motivo da confusão.
precisa saber é o seguinte
@MikeCampbell Está faltando alguns mais opções, consulte a opção: dependent deve ser um dos [: destruir,: delete_all,: Nullify,: restrict_with_error,: restrict_with_exception]
Pravin Mishra
30

Consulte destroy exclui seus elementos associados, em que delete_all pode excluir vários dados da tabela própria comoDELETE * FROM table where field = 'xyz'

: Opções possíveis dependentes:

Controla o que acontece com os objetos associados quando o proprietário é destruído. Observe que eles são implementados como retornos de chamada, e o Rails executa retornos de chamada em ordem. Portanto, outros retornos de chamada semelhantes podem afetar o comportamento: dependente e o :dependentcomportamento pode afetar outros retornos de chamada.

:destroy faz com que todos os objetos associados também sejam destruídos.

:delete_all faz com que todos os objetos associados sejam excluídos diretamente do banco de dados (portanto, os retornos de chamada não serão executados).

:nullifyfaz com que as chaves estrangeiras sejam definidas como NULL. Os retornos de chamada não são executados.

:restrict_with_exception faz com que uma exceção seja gerada se houver algum registro associado.

:restrict_with_error faz com que um erro seja adicionado ao proprietário se houver algum objeto associado.

Se estiver usando com a :throughopção, a associação no modelo de junção deve ser perten_to e os registros que são excluídos são os registros de junção, e não os registros associados.

Manish Shrivastava
fonte
3

Na verdade, a principal diferença é que nenhum retorno de chamada será invocado quando :delete_allfoi usado. Mas quando usada, :destroya pilha de retornos de chamada ( :after_destroy, :after_commit...) será acionada.

Conseqüentemente, se você tiver touch:declarações em modelos sendo excluídas, é melhor usar dependent: :delete_all'dependente:: destroy'.

atlascoder
fonte