0

를 저장하는 액티브 협회는 액티브 협회를 저장에 관한 문제를 가지고 여러분의 도움 :) 내가 레거시 코드에 기능을 병합 기사를 추가 할 필요가레일 : 문제

이 필요합니다. 은 "대상"기사

  1. 병합 "소스"기사 텍스트 :

    는 다음과 같은 방식으로 작동 할 것으로 예상합니다.

  2. "source"의 의견을 확인하고, 해당되는 경우 "target"에 다시 연결하십시오.
  3. "원본"기사를 삭제하십시오. 주석은 보존되어야하며 "목표"와 연관되어야합니다.

다음은 내 기사 모델 코드입니다 (가독성을 위해 줄였습니다). 내가 후크 아무것도 데이터베이스에 저장되어 있지 않은 before_destroy에서 돌아 왔을 때

class Comment < Feedback 
    belongs_to :article 
end 

문제는 다음과 같습니다

class Article < Content 

    before_destroy :reload_associated_comments 

    has_many :comments, :dependent => :destroy, :order => "created_at ASC" do 

    def reload_associated_comments 
    unless self.comments.empty? 
     article = Article.find(@merge_with) 
     self.comments.each do |comment| 
     comment.article = article 
     article.save! 
     end 
    end 
    end 

    def merge_with(id) 
    @merge_with = id 
    article = Article.find(@merge_with) 
    if !article.nil? 
     text = article.body + body 
     article.body = text 
     article.save! 
     self.destroy 
     return article 
    end 
    nil 
    end 
end 

여기 (또한 감소) 코멘트 모델입니다. 다음을 통해 확인합니다.

eval Article.find(target_article_id).comments 

저장시 예외가 발생하지 않습니다. 여기서 내가 놓친 게 뭐야?

미리 감사드립니다.

def merge_with(id) 
    @merge_with = id 
    article = Article.find(@merge_with) 
    unless article.nil? 
     text = article.body + body 
     article.body = text 
     article.save! 
     reload_associated_comments 
     self.reload 
     self.destroy 
     return article 
    end 
    nil 
    end 
+0

해당 메소드 reload_associated_comments에서 comment.save가되어야합니다! article.save 대신! 내 생각 : – Zippie

+0

또한 잘 모르겠지만 당신이 self.destroy 자체에서 호출되는 메서드 안에 호출 할 수 없습니다 생각합니다. 기사를 반환 한 다음 외부에서 파괴하십시오 (여기서'merge_with' 메소드를 호출합니다) – Zippie

+0

'reload_associated_comments' 메소드는'before_destroy' 콜백으로 사용됩니다. article.save!를 호출하면 주석이 자동 저장된다는 것을 의미하지 않습니까? 그렇지 않은 경우 올바른 저장 순서는 무엇입니까? 댓글을 달고 기사를 쓰거나 그 반대의 경우? – niebelung

답변

1

가 실제로 기사의 before_destroy 콜백을 호출하기 전에 모든 코멘트를 파괴 레일 날 위해 일했습니다. 슬프게도 레일 작동 방식입니다. 이 동작을 변경하면 기존 앱이 손상 될 수 있습니다. ,

class Article < Content 

    def destroy 
    reload_associated_comments 
    super 
    end 

    has_many :comments, :dependent => :destroy, :order => "created_at ASC" do 

    def reload_associated_comments 
    unless self.comments.empty? 
     article = Article.find(@merge_with) 
     self.comments.each do |comment| 
     comment.article = article 
     comment.save! 
     end 
    end 
    end 

    def merge_with(id) 
    @merge_with = id 
    article = Article.find(@merge_with) 
    if !article.nil? 
     text = article.body + body 
     article.body = text 
     article.save! 
     self.destroy 
     return article 
    end 
    nil 
    end 
end 

또한 @Zippie가 언급 한 바와 같이, 당신이해야합니다 https://github.com/rails/rails/issues/670 내 의견으로는

가장 좋은 방법은 destroy 메서드를 재정의하고 콜백을 제거입니다 : 현재이 문제에 대한 자세한 정보를 찾을 수 있습니다 article.save! 대신 comment.save!으로 전화하십시오.

희망이 있습니다.

+1

와우, 무슨 대답! alfonso,'reload_associated_comments' 메쏘드에서'article.save!'가 올바르지 않다고 말하지 않겠습니까? 'comment.save'하지 않아야합니다! 그리고 그것이 옳다면, 어떻게 맞습니까? 객체에'.save! '를 넣으면 모든 자식에게 영향을 미칩니 까? – Zippie

+0

@Zippie 좋은 캐치! 네가 맞아. 내 대답 편집 중 ... – alf

+0

정말 기쁩니다. 그렇지 않다면 ActiveRecord가 나를 놀라게 할 것입니다! :) – Zippie