불필요한 쿼리를 트리거하지 않고 레일스의 has_many 연관에서 레코드를 제거하는 데 문제가 있습니다. 본질적으로, 나는 has_many 릴레이션이있는 모델을 가지고 있으며, 몇 가지 기준에 따라 여러 레코드를 제거하려고합니다. 나는 협회를 최신 상태로 유지하면서 동시에 데이터베이스에서 레코드를 제거 할 수 있기를 원하며 이렇게하기 위해 하나의 DELETE 쿼리 만 필요합니다. 나는 불필요한 UPDATE 쿼리를 생성하는 새로운 객체와의 관계를 할당하고 delete_all (하나의 쿼리를 만들지 만 연관을 업데이트하지 않음)을 호출하려고 시도했다.has_many에서 레코드 제거 단일 쿼리로 레일스 연결
1
A
답변
0
관계에서 레코드를 삭제하는 두 가지 방법이 있습니다. destroy
은 모든 관련 레코드를 한 번에 하나씩 삭제하고 삭제 된 각 레코드에서 콜백을 실행합니다. delete_all
은 하나의 쿼리에서 모든 레코드를 삭제하고 콜백을 실행하지 않습니다.
그래서, 모델에 당신은 할 수 : 당신이 고객에게
pry(main) foo = Customer.first
pry(main)> foo.destroy
(0.3ms) BEGIN
SQL (290.4ms) DELETE FROM `statements` WHERE `statements`.`customer_id` = 3
SQL (2.6ms) DELETE FROM `customers` WHERE `customers`.`id` = 3
모든 하나의 팽창의 foop에서 수행을 삭제할 때
class Customer < ApplicationRecord
has_many :statements, dependent: :delete_all
을하고, 아무런 콜백은 삭제합니다.
또는 - 각 의존 기록은 한 번에 하나씩 삭제 고객
pry(main) foo = Customer.first
pry(main)> foo.destroy
(0.4ms) BEGIN
Statement Load (25.0ms) SELECT `statements`.* FROM `statements` WHERE `statements`.`customer_id` = 4
SQL (0.5ms) DELETE FROM `statements` WHERE `statements`.`id` = 9023
SQL (0.3ms) DELETE FROM `statements` WHERE `statements`.`id` = 9024
SQL (0.3ms) DELETE FROM `statements` WHERE `statements`.`id` = 9025
. . . etc etc etc . . .
을 삭제할 때
class Customer < ApplicationRecord
has_many :statements, dependent: :destroy
은하고, 콜백이 삭제 각에서 실행됩니다.
및 delete_all
및 destroy
은 유사한 효과를 가진 결과 세트에서 실행할 수 있습니다. 그래서 당신은 관련 기록에 대한 몇 가지 필터가 원한다면 :
pry(main) foo = Customer.first
pry(main)> bar = foo.statements.where(some_param: 42)
pry(main)> bar.delete_all
SQL (4.2ms) DELETE FROM `statements` WHERE `statements`.`customer_id` = 7 AND `notices`.`some_param` = 42
=> 2
또는 - 레일은 각 당신이 콜백에게 (`before_`과`실행하기 위해 삭제할 개체를 찾을 필요가
pry(main) foo = Customer.first
pry(main)> bar = foo.statements.where(some_param: 42)
pry(main)> bar.destroy_all
(0.2ms) BEGIN
SQL (0.6ms) DELETE FROM `notices` WHERE `notices`.`id` = 4639
(0.5ms) COMMIT
(0.2ms) BEGIN
SQL (0.5ms) DELETE FROM `notices` WHERE `notices`.`id` = 4640
(0.4ms) COMMIT
(0.1ms) BEGIN
SQL (0.5ms) DELETE FROM `notices` WHERE `notices`.`id` = 4641
(0.5ms) COMMIT
. . . etc etc etc . . .
을 after_' 파괴). 미끄러운 슬로프 인 그 프로세스를 건너 뛰고 싶다면 "관련된 모든 객체 삭제"에 대한 모든 논리를 담고있는 서비스 객체를 생성하고 연관을 재설정하고 싶을 수도 있습니다. – MrYoshiji
연관을 재설정하는 것이 최적이 아니라고 생각합니다. 나중에 연결에 액세스하면 관계에 있어야하는 내용을 알 수 있더라도 개체를 다시 가져와야하기 때문입니다. – mp94
IMO를 사용하면 SQL 쿼리를 줄이고 Rails의 동작을 재정의해서는 안됩니다. 첫눈에 보이지는 않지만 여러 가지 문제로 이어질 수 있지만 나중에 전체 앱이 몇 달 동안 앱을 사용했을 때 ... – MrYoshiji