[ruby-on-rails] ActiveRecord 콜백을 실행하지 않으려면 어떻게해야합니까?

after_save 콜백이있는 모델이 있습니다. 일반적으로 문제는 없지만 개발 데이터를 만들 때와 같은 일부 상황에서는 콜백을 실행하지 않고 모델을 저장하려고합니다. 그렇게하는 간단한 방법이 있습니까? 비슷한 것 …

Person#save( :run_callbacks => false )

또는

Person#save_without_callbacks

Rails 문서를 보았는데 아무것도 찾지 못했습니다. 그러나 내 경험상 Rails 문서가 항상 전체 이야기를 말하는 것은 아닙니다.

최신 정보

다음 과 같은 모델에서 콜백을 제거하는 방법을 설명하는 블로그 게시물 을 찾았 습니다 .

Foo.after_save.clear

그 방법이 문서화 된 곳을 찾을 수 없지만 작동하는 것 같습니다.



답변

이 솔루션은 Rails 2 전용입니다.

방금 조사한 결과 해결책이 있다고 생각합니다. 사용할 수있는 두 가지 ActiveRecord 개인용 메소드가 있습니다.

update_without_callbacks
create_without_callbacks

이러한 메소드를 호출하려면 send를 사용해야합니다. 예 :

p = Person.new(:name => 'foo')
p.send(:create_without_callbacks)

p = Person.find(1)
p.send(:update_without_callbacks)

이것은 확실히 콘솔에서만 또는 임의의 테스트를 수행하는 동안 사용하고 싶은 것입니다. 도움이 되었기를 바랍니다!


답변

사용 update_column(레일> = 3.1) 또는 update_columns(레일> = 4.0) 콜백 및 유효성 검사를 건너 뜁니다. 또한 이러한 방법으로, updated_at되어 있지 업데이트되었습니다.

#Rails >= v3.1 only
@person.update_column(:some_attribute, 'value')
#Rails >= v4.0 only
@person.update_columns(attributes)

http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_column

# 2 : 객체를 만드는 동안 작동하는 콜백 건너 뛰기

class Person < ActiveRecord::Base
  attr_accessor :skip_some_callbacks

  before_validation :do_something
  after_validation :do_something_else

  skip_callback :validation, :before, :do_something, if: :skip_some_callbacks
  skip_callback :validation, :after, :do_something_else, if: :skip_some_callbacks
end

person = Person.new(person_params)
person.skip_some_callbacks = true
person.save


답변


업데이트 :

@Vikrant Chaudhary의 솔루션이 더 좋아 보입니다.

#Rails >= v3.1 only
@person.update_column(:some_attribute, 'value')
#Rails >= v4.0 only
@person.update_columns(attributes)

내 원래 답변 :

이 링크 참조 : ActiveRecord 콜백을 건너 뛰는 방법?

Rails3에서

클래스 정의가 있다고 가정하십시오.

class User < ActiveRecord::Base
  after_save :generate_nick_name
end 

접근법 1 :

User.send(:create_without_callbacks)
User.send(:update_without_callbacks)

접근 방법 2 : rspec 파일이나 다른 파일에서 건너 뛰려면 다음을 시도하십시오.

User.skip_callback(:save, :after, :generate_nick_name)
User.create!()

참고 :이 작업이 완료되면 rspec 환경이 아닌 경우 콜백을 재설정해야합니다.

User.set_callback(:save, :after, :generate_nick_name)

레일 3.0.5에서 잘 작동합니다.


답변

레일 3 :

MyModel.send("_#{symbol}_callbacks") # list  
MyModel.reset_callbacks symbol # reset


답변

콜백이나 유효성 검사없이 단순히 레코드를 삽입하는 것이 목표이며 추가 gem에 의존하지 않고 조건부 검사를 추가하거나 RAW SQL을 사용하거나 종료 코드를 사용하여 어떤 식 으로든 퍼징하지 않고 수행하려는 경우 “그림자”사용을 고려하십시오. 기존 DB 테이블을 가리키는 개체 ” 이렇게 :

class ImportedPerson < ActiveRecord::Base
  self.table_name = 'people'
end

이것은 모든 Rails 버전에서 작동하며 스레드 안전하며 기존 코드를 수정하지 않고도 모든 유효성 검사 및 콜백을 완전히 제거합니다. 실제로 가져 오기 직전에 클래스 선언을 던질 수 있으며 잘 진행해야합니다. 다음과 같이 새 클래스를 사용하여 객체를 삽입하십시오.

ImportedPerson.new( person_attributes )


답변

Person 모델에서 다음과 같은 것을 시도해 볼 수 있습니다.

after_save :something_cool, :unless => :skip_callbacks

def skip_callbacks
  ENV[RAILS_ENV] == 'development' # or something more complicated
end

편집 : after_save는 기호가 아니지만 적어도 1,000 번 시도했습니다.


답변

당신은 사용할 수 있습니다 update_columns:

User.first.update_columns({:name => "sebastian", :age => 25})

save를 호출하지 않고 객체의 지정된 속성을 업데이트하므로 유효성 검사 및 콜백을 건너 뜁니다.