Respostas:
Basicamente, destroy
executa quaisquer retornos de chamada no modelo enquanto delete
não.
ActiveRecord::Persistence.delete
Exclui o registro no banco de dados e congela esta instância para refletir que nenhuma alteração deve ser feita (pois não pode ser persistida). Retorna a instância congelada.
A linha é simplesmente removida com uma instrução SQL DELETE na chave primária do registro e nenhum retorno de chamada é executado.
Para impor os retornos de chamada before_destroy e after_destroy do objeto ou qualquer outra opção de associação dependente, use #destroy.
ActiveRecord::Persistence.destroy
Exclui o registro no banco de dados e congela esta instância para refletir que nenhuma alteração deve ser feita (pois não pode ser persistida).
Há uma série de retornos de chamada associados à destruição. Se o retorno de chamada before_destroy retornar false, a ação será cancelada e destroy retornará false. Consulte ActiveRecord :: Callbacks para obter mais detalhes.
model#before_destroy
que pode ser usado para interromper a destroy()
chamada final sob certas condições.
delete
excluirá apenas o registro de objeto atual do db, mas não os registros filhos associados do db.
destroy
excluirá o registro de objeto atual do db e também o registro filho associado do db.
Seu uso realmente importa:
Se seus vários objetos pai compartilharem objetos filhos comuns, a chamada destroy
de um objeto pai específico excluirá objetos filhos que são compartilhados entre outros pais múltiplos.
destroy
é descendente , não filhos : de acordo com a documentação, destroy "cria um novo objeto a partir dos atributos e depois chama destrua nele". rubydoc.info/docs/rails/4.1.7/ActiveRecord%2FRelation:destroy
Quando você invoca destroy
ou destroy_all
em um ActiveRecord
objeto, o ActiveRecord
processo de 'destruição' é iniciado, ele analisa a classe que você está excluindo, determina o que deve fazer por dependências, executa validações etc.
Quando você invoca delete
ou delete_all
em um objeto, ActiveRecord
apenas tenta executar a DELETE FROM tablename WHERE conditions
consulta no banco de dados, não executando outras ActiveRecord
tarefas de nível superior.
Sim, existe uma grande diferença entre os dois métodos. Use delete_all se desejar que os registros sejam excluídos rapidamente, sem que os retornos de chamada do modelo sejam chamados.
Se você se preocupa com os retornos de chamada dos seus modelos, use destroy_all
Dos documentos oficiais
http://apidock.com/rails/ActiveRecord/Base/destroy_all/class
destroy_all (conditions = nil) public
Destrói as condições de correspondência dos registros instanciando cada registro e chamando seu método de destruição. Os retornos de chamada de cada objeto são executados (incluindo: opções de associação dependentes e métodos de observação before_destroy / after_destroy Observer). Retorna a coleção de objetos que foram destruídos; cada um será congelado, para refletir que nenhuma alteração deve ser feita (pois não pode ser persistida).
Nota: A instanciação, execução de retorno de chamada e exclusão de cada registro podem ser demoradas quando você está removendo muitos registros de uma só vez. Ele gera pelo menos uma consulta SQL DELETE por registro (ou possivelmente mais, para impor seus retornos de chamada). Se você deseja excluir muitas linhas rapidamente, sem se preocupar com suas associações ou retornos de chamada, use delete_all.
Basicamente, "excluir" envia uma consulta diretamente ao banco de dados para excluir o registro. Nesse caso, o Rails não sabe quais atributos estão no registro e está excluindo nem se há retornos de chamada (como before_destroy
).
O método "destroy" pega o ID passado, busca o modelo no banco de dados usando o método "find" e, em seguida, chama destroy nele. Isso significa que os retornos de chamada são acionados.
Você deseja usar "excluir" se não desejar que os retornos de chamada sejam acionados ou se desejar um melhor desempenho. Caso contrário (e na maioria das vezes), você desejará usar "destroy".
Muitas respostas já; queria pular um pouco mais.
docs :
Para has_many, destroy e destroy_all sempre chamará o método de destruição dos registros removidos, para que os retornos de chamada sejam executados. No entanto, delete e delete_all farão a exclusão de acordo com a estratégia especificada pela opção: dependente ou, se nenhuma opção for dependente for fornecida, seguirá a estratégia padrão. A estratégia padrão é não fazer nada (deixe as chaves estrangeiras com os IDs principais configurados), exceto has_many: through, em que a estratégia padrão é delete_all (exclua os registros de junção, sem executar seus retornos de chamada).
O delete
verbage funciona de maneira diferente para ActiveRecord::Association.has_many
e ActiveRecord::Base
. No último, a exclusão executará SQL DELETE
e ignorará todas as validações / retornos de chamada. O primeiro será executado com base na :dependent
opção passada para a associação. No entanto, durante o teste, encontrei o seguinte efeito colateral no qual os retornos de chamada eram executados apenas delete
e nãodelete_all
dependent: :destroy
Exemplo:
class Parent < ApplicationRecord
has_many :children,
before_remove: -> (_) { puts "before_remove callback" },
dependent: :destroy
end
class Child < ApplicationRecord
belongs_to :parent
before_destroy -> { puts "before_destroy callback" }
end
> child.delete # Ran without callbacks
Child Destroy (99.6ms) DELETE FROM "children" WHERE "children"."id" = $1 [["id", 21]]
> parent.children.delete(other_child) # Ran with callbacks
before_remove callback
before_destroy callback
Child Destroy (0.4ms) DELETE FROM "children" WHERE "children"."id" = $1 [["id", 22]]
> parent.children.delete_all # Ran without callbacks
Child Destroy (1.0ms) DELETE FROM "children" WHERE "children"."parent_id" = $1 [["parent_id", 1]]