
Tenho um relacionamento muitos-para-um, e gostaria que ao excluir o objeto pai todos os seus relacionamentos (filhos) fossem também apagados no banco de dados. Esta exclusão automática existe e se chama exclusão em cascata. No Rails é muito simples implementar:
[source:ruby]
class Pai < ActiveRecord::Base
has_many :filhos, :dependent => true
end
[/source]
Esta declaração informa que o Filho não pode existir sem um Pai. Desta maneira, se eu apagar uma instância de Pai, todos os seus filhos também serão apagados. Mas, atenção, cada filho será apagado individualmente, será executado um DELETE para cada linha no banco de dados.
Mas se seus objetos Filhos forem exclusivos de um objeto Pai – e somente de um – então você pode trocar esta declaração por esta:
[source:ruby]
class Pai < ActiveRecord::Base
has_many :filhos, :exclusively_dependent => true
end
[/source]
Agora o Rails fará o mesmo, mas de uma vez, com apenas um comando SQL.
Fiquem atentos aos recursos do Rails, os maiores problemas de desempenho que encontro é em detalhes como esse.
OI Carlos, tudo bom?
Na verdade:
:exclusively_dependent está em desuso, o melhor é usar:
:dependent => :delete_all
Cheers
É, isso ae que o Gustavo falou!
E outra dica para melhorar rendimento, é quando se tem relacionamentos, no find, tu usar o :include => {:model1, :model2, :model3 }
Com isso ele faz inner join ao inves de fazer varias consultas…
Mas tem que cuidar! :)
Opa, em um sistema que estou desenvolvendo eu tinha usado a primeira opção, acompanhando os logs vi que ele gerava 1 sql para cada filho e acabei apagando na mão mesmo… (em rails significa 1 linha de código a mais :D)
É bom saber dessa solução mais elegante, valeu pela dica!
Bem lembrado Gustavo.
Eu já tinha visto isto antes, mas acabei escrevendo da forma antiga no blog. Agora o correto é usar :dependent => :delete_all
Para confirmar o que o Gustavo comentou o link é: http://dev.rubyonrails.org/ticket/6024 e http://dev.rubyonrails.org/attachment/ticket/6024/deprecation_warning_exclusively_dependent.diff
Eles funcionariam em has_and_belongs_to_many também?
Como exemplo vou dar Foto e Tag, com relacionamento muitos para muitos.
Ao apagar todas as fotos de uma tag, essa tag deve ser apagada.
Mas ao apagar apenas um foto, e ainda ter mais para aquela tag, essa nao deve ser apagada. Caso não tenha mais fotos para a tag, a tag também apaga.
Seria melhor usar o :dependent => true?
XaXá,
O has_and_belong_to_many não tem a opção :dependent
Dá para sobrescrever o sql que deleta os registros,
para agir como vc pretende com a opção :delete_sql
Outra forma é fazer o overload do método destroy no model. Essa maneira me parece mais elegante.
Cheers
Ah sim, entendi.
Muito obrigado pela ajuda!
Ótimo post!!
Pouca gente se lembra do exclusively_dependent na hora de criar seus models (eu estou nesta lista)!! Valeu pelo lembrete, vou anotar essa!!
Felipe Giotto
Felipe, fique esperto que o :exclusively_dependent vai mudar. Nos comentários tem as dicas.
Abraço!