2012-03-14 2 views
2

모델 "하나"ActiveRecord 모델 이중 저장을 피하는 방법은 무엇입니까?

class One < ActiveRecord::Base 
    before_save :do_stuff 

    private 
    def do_stuff 
     two = Two.find(8) 
     two.field2 = 'Value' 
     two.save! 
    end 
end 

모델 "2"실행

class Two < ActiveRecord::Base 
    before_save :do_stuff 

    private 
    def do_stuff 
     one = One.find(7) 
     one.field2 = 'SomeValue' 
     one.save! 
    end 
end 

:

two = Two.find(1) 
two.somefield = 'NewVal' 
two.save! 

무한 루프가 시작됩니다. before_save 콜백에서 서로를 변경해야하는 두 가지 모델을 구현하려면 대부분의 루비 온 레일 (ruby-on-rails) 방법은 무엇입니까?

+0

여기 정확히 달성하려는 것은 무엇입니까? –

+2

확실히 디자인에 문제가 있습니다. 현재 질문을 해결할지라도 다음 문제로 이어질 것입니다. – megas

+0

+1 디자인에 부족한 것처럼 보일지라도이 종류의 _cycle에서 한 번 이상 내 자신을 발견했습니다. 콜백 참조 hell_. [adhoc 콜백을 피하십시오] 가능성을 가지는데 도움이 될 수 있습니다 (http://stackoverflow.com/questions/632742/how-can-i-avoid-running-activerecord-callbacks) – fguillen

답변

2

희소 한 경우에 이것을 수행해야하는 경우 attr_accessor을 사용하여 before_save 필터를 사용 중지하거나 반복하지 않으려면 after_save 블록으로 옮길 수 있습니다. 당신은 그들 중 적어도 하나에 트리거를 비활성화 할 것

class One < ActiveRecord::Base 
    attr_accessor :not_doing_stuff 
    before_save :do_stuff, 
    :unless => :not_doing_stuff 

private 
    def do_stuff 
    two = Two.find(8) 
    two.field2 = 'Value' 
    two.save! 
    end 
end 

:이 같은

class Two < ActiveRecord::Base 
    before_save :do_stuff 

private 
    def do_stuff 
    one = One.find(7) 
    one.not_doing_stuff = true 
    one.field2 = 'SomeValue' 
    one.save! 
    end 
end 

상황이 항상 매우 추한, 그래서 시도하고 당신이 할 수있는하지 않는 한 그것을 피할 예를 들어

다른 방법으로 생각하지 마라. 필요한 경우, 일부 가장자리 상황에서 끝없는 루프에 잠기지 않도록 충분한 단위 테스트를 작성했는지 확인하십시오.

+0

매우 똑똑합니다. 좋아합니다! :) – fguillen

1

before_save에서 save을 호출하지 마십시오. 무한 루프가 트리거됩니다. 대신 true 또는 false를 반환합니다. before_save에 넣은 내용이 모두 성공하면 true이고, 실패하면 false입니다. false를 반환하면 저장 및 모든 다른 콜백이 취소됩니다.

관련 문제