4

モデルの属性がいつ変更されたかを確認したい。値をチェックしようとしました != 保存を行う前にフォームの値を確認しようとしましたが、そのコードは非常に見苦しく、時々うまく機能しません。モデルクラスで検証を行わない update_column を使用する場合と同じです。他に何もせずに update_attributes を使用すると、フィールドがいつ更新されたかを理解できなくなります。スタック オーバーフローや他のサイトに関する私の Web 調査から、ActiveModel Dirty を使用することが最善の方法であるように思われます。

私はこれを見てきました: http://api.rubyonrails.org/classes/ActiveModel/Dirty.html

これを使用して、update_attributes を使用した後にモデルでブール値のフラグが変更されたかどうかを確認したいと考えています。含まれているリンクで説明されているように、最小限の実装を試みました。ActiveRecord クラスに以下を追加しました。

include ActiveModel::Dirty

define_attribute_methods [:admin]

追跡したい3つの属性を追加してみました。機能するかどうかを確認するために、1 つの属性から始めました。rspec テストを実行すると、次のエラーが発生しました。引数を削除すると、エラーはなくなりました。

Exception encountered: #<ArgumentError: wrong number of arguments (1 for 0)>

引数を削除した後、名前の代わりに admin を使用して、モデルに同様のメソッドを含めることにしました。他の Rspec テストは save メソッドで壊れました。ただし、ActiveModel Dirty の実装方法に問題があると感じています。

他のスタック オーバーフローの投稿を読んだことがありますが、コメンターはこれが 3.2.8 に含まれていると述べていたので、3.2.6 から 3.2.8 にアップグレードしました。私はそれが何を意味するのか理解できなかったので、エラーが発生した後、include ActiveModel::Dirty ステートメントをそのままにして、admin_changed を使用することにしましたか? もちろん、うまくいきませんでした。

ここに含めたリンク以外に、これを最初に設定する方法について何も見つけることができませんでした。私が見つけた他のすべての調査では、初期設定が正しく、Rails の現在の安定版に更新することで問題が解決されると想定しています。

これを実装する方法についての助けをいただければ幸いです。リンクに記載されている最小限の実装を行っても機能しません。多分私が見逃している何かが他にあります。

4

2 に答える 2

8

問題は、ActiveRecord がdefine_attribute_methods0 の引数を受け入れるようにメソッドを再定義しているようです (ActiveRecord はデータベース テーブルのすべての列に対して属性メソッドを自動的に作成するため): https://github.com/rails/rails/blob/master/activerecord/lib/ active_record/attribute_methods.rb#L23

define_attribute_methodsこれは、ActiveModel によって提供されるメソッドをオーバーライドします: https://github.com/rails/rails/blob/master/activemodel/lib/active_model/attribute_methods.rb#L240

解決:

私は自分に合った解決策を見つけました...

このファイルを次の名前で保存しますlib/active_record/nonpersisted_attribute_methods.rb: https://gist.github.com/4600209

次に、次のようなことができます。

require 'active_record/nonpersisted_attribute_methods'
class Foo < ActiveRecord::Base
  include ActiveRecord::NonPersistedAttributeMethods
  define_nonpersisted_attribute_methods [:bar]
end

foo = Foo.new
foo.bar = 3
foo.bar_changed? # => true
foo.bar_was # => nil
foo.bar_change # => [nil, 3]
foo.changes[:bar] # => [nil, 3]

ただし、次のようにすると警告が表示されるようです。

DEPRECATION WARNING: You're trying to create an attribute `bar'. Writing arbitrary attributes on a model is deprecated. Please just use `attr_writer` etc.

したがって、このアプローチが Rails 4 で壊れるか、難しくなるかどうかはわかりません...

以下も参照してください。

于 2013-01-22T21:00:47.287 に答える
-3

次のように = を追加してみてください。

define_attribute_methods = [:admin]

その変更は私にとってはうまくいきました。これと関係があるかどうかわかりませんか?

于 2012-11-15T23:52:22.883 に答える