:credits属性を持つユーザーモデルがあります。 「add」と呼ばれるルートを通じて、ユーザーのクレジットに5を追加するシンプルなボタンが必要です。これにより、/ users/3/addがユーザーID = 3のクレジットに5を追加します。
def add
@user = User.find(params[:id])
@user.credits += 5
redirect_to root_path
end
それが私のコントローラーの重要な部分です。問題は、現在のUTC時間に基づいてユーザーのパスワードを再暗号化するbefore_saveコールバックがあるため、@ user.saveを呼び出したくないことです。単純に属性に5を追加して、コールバックを回避したいだけです。このような単純なことをこれほど難しいとは思っていませんでした。
編集:
コールバックを:before_createに変更しました。新しいコントローラーコードを次に示します(関連部分)。
def add
@user = User.find(params[:id])
@user.add_credits(5)
@user.save
flash[:success] = "Credits added!"
redirect_to root_path
end
そして、ここにモデル内の私のコードがあります:
def add_credits(num)
self.credits = num
end
編集2:
[編集]の変更が機能しなかったのは検証の問題でしたが、コールバックなしで更新するという元の質問に対する答えがまだ欲しいです!
Rails 3.1はupdate_column
を導入しました。これはupdate_attribute
と同じですが、検証またはコールバックをトリガーしません。
http://apidock.com/Rails/ActiveRecord/Persistence/update_column
コールバックなしで複数の属性を更新するには、モデルでupdate_allを次のように使用できます。
self.class.update_all({name: value, name: value}, self.class.primary_key => id)
本当に必要な場合は、update_columnsメソッドでも試して、これをアクティブなレコードの基本クラスにミックスインすることもできます。
1つの属性を更新するには、update_columnを使用できます。さらに、Railsガイド http://guides.rubyonrails.org/active_record_callbacks.html#skipping-callbacks にある特定のメソッドがあります。
一般的な答えとして、Rails 4では、これはコールバックをトリガーせずに属性を更新する簡単な方法です。
@user.update_column 'credits', 5
トリガーコールバックなしで複数の属性を更新する必要がある場合:
@user.update_columns credits: 5, bankrupt: false
他のオプションがあります ここでRails Guides にありますが、この方法が最も簡単であることがわかりました。
この場合、メソッド pdate_counters を使用する必要があると思います。コントローラーアクションで次のように使用します。
def add
User.update_counters params[:id], :credits => 5
redirect_to root_path
end
Rails4でこれを行う方法のいくつかのオプション http://edgeguides.rubyonrails.org/active_record_callbacks.html#skipping-callbacks
pdate_all を使用して、コールバックのトリガーを回避できる必要があります。
def add
@user = User.find(params[:id])
User.where(:id=>@user.id).update_all(:credits => @user.credits+5)
redirect_to root_path
end
このロジックをモデルに配置することを希望しますが、これはコントローラーで指定された元の問題を解決するために機能するはずです。
Mongoidの場合、 http://mongoid.org/en/mongoid/docs/persistence.html を使用することになりました。具体的には、次を使用できます。
person.set(name:"Robert Pulson")
コールバックは発行されません。とてもクール。
他のbefore_saveフックは、ユーザーのパスワードが実際に変更されたかどうかを再度暗号化する前にチェックする必要があるかもしれません。
使用するコールバックの変更など、多くのオプションがあります。例:after_create
。
コールバックをトリガーせずに列を更新できます。ARガイドの Skipping Callbacks を参照してください。例えば、 update_column
はコールバックをトリガーしません。前のリンクには、非トリガー関数がリストされています。
また、パスワードが変更されたときに 条件付きコールバック フォーム(またはオブザーバー)を使用することもできます。 ActiveModel :: Dirty (例:@user.password_changed?
。
これを行う列を更新できます
User.where(name: 'lily').update_all(age: '10')