delete_all 대 destroy_all?


193

테이블에서 레코드를 삭제하는 가장 좋은 방법을 찾고 있습니다. 예를 들어, 사용자 ID가 많은 테이블에있는 사용자가 있습니다. 이 사용자와 모든 테이블에 ID가있는 모든 레코드를 삭제하고 싶습니다.

u = User.find_by_name('JohnBoy')
u.usage_indexes.destroy_all
u.sources.destroy_all
u.user_stats.destroy_all
u.delete

이것은 작동하고 모든 테이블에서 사용자의 모든 참조를 제거하지만 destroy_all프로세스가 너무 무거워서 시도했습니다 delete_all. 자신의 사용자 테이블에서 사용자를 제거하고 id다른 모든 테이블에서 사용자를 null로 만들지 만 레코드는 그대로 둡니다. 누군가 이와 같은 작업을 수행하기위한 올바른 프로세스를 공유 할 수 있습니까?

모든 관련 개체 destroy_all에서 destroy함수 를 호출하는 것을 보았지만 올바른 접근 방식을 확인하고 싶습니다.

답변:


244

네 말이 맞아 사용자 및 모든 관련 객체 destroy_all 를 삭제하려는 경우 -> 그러나 모든 관련 객체를 억제하지 않고 사용자를 삭제하려는 경우->delete_all

이 게시물에 따르면 : Rails : dependent => : destroy VS : dependent => : delete_all

  • destroy/ destroy_all: 연관된 객체는 destroy 메소드를 호출하여이 객체와 함께 파괴됩니다.
  • delete/ delete_all: 관련된 모든 객체는 : destroy 메소드를 호출하지 않고 즉시 파괴됩니다.

80
또한 1)을 사용할 때 콜백이 호출되지 않고 delete_all2) destroy_all모든 레코드를 인스턴스화하고 한 번에 하나씩 삭제하므로 매우 큰 데이터 세트의 경우 고통스럽게 느려질 수 있습니다.
Dylan Markow

모델에서 before_destroy 메소드를 실행한다고 가정하십시오-delete_all을 사용하면이 메소드가 실행되지 않습니까? 둘째로 모델에 before_delete 메소드를 사용하면 레일 콘솔에서 delete 또는 delete_all을 실행할 때 실행됩니까?
BKSpurgeon

23

delete_all은 단일 SQL DELETE 문이며 더 이상 없습니다. destroy_all은 일치하는 모든 : conditions 결과 (있는 경우)에서 NUM_OF_RESULTS 개 이상의 SQL 문일 수있는 destroy ()를 호출합니다.

큰 데이터 세트에서 destroy_all ()과 같은 과감한 작업을 수행 해야하는 경우 앱에서하지 않고 조심스럽게 수동으로 처리합니다. 데이터 세트가 충분히 작 으면 크게 아프지 않을 것입니다.


16

destroy_all모든 레코드 를 인스턴스화하고 한 번에 하나씩 삭제 한다는 사실을 피하기 위해 모델 클래스에서 직접 사용할 수 있습니다.

따라서 대신 :

u = User.find_by_name('JohnBoy')
u.usage_indexes.destroy_all

넌 할 수있어 :

u = User.find_by_name('JohnBoy')
UsageIndex.destroy_all "user_id = #{u.id}"

결과는 모든 관련 레코드를 삭제하기위한 하나의 쿼리입니다.


1
그것은이 관련 기록에 콜백을 파괴, 또는이다 호출 UsageIndex.destroy_all과 동등 UsageIntex.delete_all?
Magne

UsageIndex.destroy_all레일 3 이후로 더 이상 사용할 수 없습니다
fabriciofreitag

1

일부 상황에서 관련 레코드를 수동으로 삭제해야 할 필요성을 완화 할 수 있는 작은 보석 을 만들었습니다 .

이 gem은 ActiveRecord 연관을위한 새로운 옵션을 추가합니다 :

의존적 : : delete_recursively

레코드를 삭제하면이 옵션을 사용하여 연결된 모든 레코드는 인스턴스화하지 않고 재귀 적으로 (예 : 모델 전체) 삭제됩니다.

dependent : : delete 또는 dependent : : delete_all과 마찬가지로이 새로운 옵션은 종속 레코드의 around / before / after_destroy 콜백을 트리거하지 않습니다.

그러나, 종속적 인 : : delete_recursively와 연관된 모델 체인 내에서 어디서든 종속적 인 :: troy 연관을 가질 수 있습니다. : destroy 옵션은 회선의 위나 아래로 정상적으로 작동하여 모든 관련 레코드를 인스턴스화하고 삭제하여 콜백을 트리거합니다.


환상적이다! 왜 더 많은 사람들이 github에서 그것을 보거나 별표 표시하거나 포크하지 않았는지 궁금합니다. 여전히 잘 작동합니까?
Magne

@Magne 감사합니다! 작동해야합니다. 테스트는 Ruby 2.4.1 및 Rails 5.1.1에서 실행됩니다. 지금까지 나는 주요 프로덕션 앱이 아닌 개인적으로 만 사용했기 때문에 주요 버전 "0"은 없었지만 아무런 문제도 발견하지 못했습니다. 또한 매우 간단하므로 괜찮을 것입니다.
Janosch

멋있는. :) Ruby 2.3.1 및 'rails', '~> 4.1.14'에서 프로젝트를 실행 중이며 다른 보석으로 인해 activerecord (~> 4.1.0)에 의존해야합니다. delete_recursively가 0.9.0으로 해결되는 것을 알 수 있습니다. activerecord 4.1에서 작동하는 이전 버전이 있습니까? github의 릴리스 탭에서 찾을 수 없습니다.
Magne

1
@Magne 나는 실제로 4.1.14만큼 낮은 activerecord에서 작동 하며 편안한 종속성으로 gem 버전 1.0.0을 발표했습니다. 그러나 Rails 4.1 브랜치는 더 이상 보안 업데이트를받지 않습니다.
Janosch
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.