0

ActiveRecord 関連付けの保存に関して問題があり、あなたの助けが必要です :)

記事をマージする機能をレガシー コードに追加する必要があります。

次のように動作すると予想されます。

  1. 「ソース」記事のテキストを「ターゲット」記事にマージします。
  2. 「ソース」のコメントを確認し、もしあれば、それらを「ターゲット」に再度関連付けます。
  3. 「ソース」記事を破棄します。コメントは保存し、「ターゲット」に関連付ける必要があります。

これが私の Article モデルコードです (読みやすくするために縮小されています)。

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

これがコメントモデルです(これも縮小されています):

class Comment < Feedback
  belongs_to :article
end

問題は、before_destroyフックから戻ったときにデータベースに何も保存されていないことです。次の方法で確認します。

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
4

1 に答える 1

1

実際、Railsは記事のコールバックを呼び出す前にすべてのコメントを破棄しbefore_destroyます。それは悲しいことにレールがどのように機能するかです。この動作を変更すると、レガシーアプリが破損することになります。この問題の詳細については、https ://github.com/rails/rails/issues/670を参照してください。

私の意見では、最善の解決策は、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が述べたように、comment.save!代わりに電話する必要がありますarticle.save!

それが役に立てば幸い!

于 2013-03-13T23:10:59.420 に答える