2012-05-07 5 views
1

私はRuby on Rails 3.2.2を使用していますが、@articleインスタンスの以前のインスタンスに基づいて、データベースに格納されているチェックを実行したいと考えています。つまり、に関連するデータベースに既に格納されているデータを使用する方法を実行する必要があります(データが{:id => 1, :title => "Sample title", :content => "Sample content", :status => "private"}およびでない場合は{:id => 1, :title => "Sample title changed!", :content => "Sample content", :status => "private"})。データベースに格納される前のインスタンスの以前のステータスに基づいてチェックを実行するにはどうすればよいですか?

元のインスタンスの属性値が変更された後で元のインスタンスを「取得する」/「再構築」を続けると考えました。それは次のとおりです。

# In the controller file 

# @article.attributes 
# => {:id => 1, :title => "Sample title", :content => "Sample content", :status => "private"} 
@article.update_attributes(params[:article]) 
# => {:id => 1, :title => "Sample title changed!", :content => "Sample content", :status => "private"} 


# In the model file 
before_save :retrieve_original 

def retrieve_original 
    # self.attributes 
    # => {:id => 1, :title => "Sample title changed!", :content => "Sample content", :status => "private"} 

    original = ... # ? 
    # original.id 
    # => nil 
    # original.attributes 
    # => {:title => "Sample title", :content => "Sample content", :status => "private"} 
    # self.attributes 
    # => {:id => 1, :title => "Sample title changed!", :content => "Sample content", :status => "private"} 
end 

ので、original@articleインスタンスのちょうど複製(idなしと変化していること@article属性なし)Articleオブジェクトでなければなりません。

いくつかのRuby on Railsメソッド(ActiveRecord::Base.dupまたはActiveModel::Dirty.changed_attributesなど)で試してみましたが、解決策が見つかりませんでした。さらに、には、自分のアプローチに比べて、私がしたいことを達成するためのより良い方法があると思います。もしそうなら、私は何をするでしょうか?私は、例えば、記事が公開されている場合ので、タイトルの値を変更することはできませんなければならないことをやりたい


。記事がプライベートであれば、タイトル値を変更することが可能でなければなりません。もちろん、私は編集した記事データを保存する前にそのチェックを行い、そのデータを更新しようとするすべての試み(このために私はbefore_saveコールバックを使用することにしました)を行う必要があります。しかし、ユーザーがタイトル値とプライベート値をpublicに変更しようとすると、すべてのチェックはパブリック "コンテキスト"で実行されますが、以前のステータスがプライベートであったため、これらのチェックはプライベート "コンテキスト" 。

答えて

3

changesハッシュを実行するように見えます。私。 dupまたはclone変更されたバージョンを使用してから、変更されたバージョンのchangesを実行し、属性を元のコピーに戻します。

+0

でそれを作ることが可能です:ここで

diff_hash = tmp_article - @article.attributes # diff will now contain any differences. It will be empty if they are identical. 

はRailsの中のdiff拡張へのリンクです:そして、あなたが保存する前には、組み込みのだレールにハッシュ.diffメソッドを使用することができます簡単/明確な方法(たとえば、ブロックを使用しない)? – user12882

+0

はい、ブロックは必要ありません。 'old_title、new_title = @ article.changes ['title']'はこのトリックを行うべきです。 –

+0

@マークトーマス - 私がこの問題で使用しようとしているアプローチが正しいと仮定すると、私は属性を適切に設定し、単純に属性値ではなくインスタンス変数を必要とします。 – user12882

0

だけ

@article = Article.find(params[:id])` 
@orginal = @article 
if @article.update_attributes(params[:article]) 
    @original.do_some_method_that_probably_should_be_a_before_update 
    #.... whatever is next ..... 
end 

を保存したり、あなたはあなたがする必要があると思う何をする必要がある理由考え直します。

+0

更新された質問に書いたように、私は '@ article'データを更新しようとするすべての試みをチェックしたいと思います(これについては私が選んだ'before_save'コールバックを使用する) – user12882

+0

実行チェックは正確に何を意味するのですか?私は推測することができますが、何を確認したいのですか?なぜですか? – pjammer

+0

質問の最後に書いてあります。 – user12882

0

これを行うにはいくつかの方法があります。基本的に、その後の変更を元に戻してチェックするのではなく、変更が行われる前にオブジェクトのコピーを作成するほうが簡単です。これを行うには

一つの方法は、このような現在のオブジェクトの「属性」から新しいオブジェクトを作成することです:あなたはモデルオブジェクトに変更を加える前に、

tmp_article = @article.attributes 

はこれを行います。

https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/hash/diff.rb

関連する問題