web-dev-qa-db-ja.com

オブジェクトを保存するとき、after_saveはどのように機能しますか

私が次のことをした場合:

@user.name = "John"    
@user.url = "www.john.com"
@user.save

after_saveを使用する場合

@user.url = "www.johnseena.com"
@user.save

これを行うとどうなりますか?

'after_save'コールバックがあるため、値を保存する必要があると思います。

15
SSP

私の意見では、after_saveコールバックでsave関数を呼び出すと、最初にガードを配置しない限り、再帰にトラップされます。このような

class User < AR::Base
      after_save :change_url

      def change_url
          #Check some condition to skip saving
          url = "www.johnseena.com"
          save              #<======= this save will fire the after_save again
      end
end

ただし、ガードを配置する以外に、update_columnを使用することもできます

def change_url
    update_column(:url, "www.johnseena.com")
end

この場合、after_saveは起動しません。ただし、after_updateは起動します。したがって、そのコールバックで更新操作がある場合は、再び再帰的になります:)

34
Samiron

after_saveコールバックは、saveまたはそのオブジェクトのupdate

また、

update_columnは、コールバック(つまり、after_update)をトリガーせず、検証もスキップします。 http://apidock.com/Rails/ActiveRecord/Persistence/update_column を参照してください

Uは、操作とそのタイミングに応じて、具体的にafter_createまたはafter_updateを使用する必要があります。

after_create :send_mail
def send_x_mail
  #some mail that user has been created
end

after_update :send_y_mail
def send_y_mail
  #some data has been updated
end

after_save :update_some_date
def update_some_data
  ...
  action which doesnt update the current object else will trigger the call_back
end

ʻafter_create`とʻafter_save`の違いは何ですか?いつどちらを使用するか? およびコールバックについては http://ar.rubyonrails.org/classes/ActiveRecord/Callbacks .html#M000059

7
prasad.surase

after_saveで何かを変更しても、saveはすでに実行されているため、保存されません。介入する唯一のチャンスは、トランザクション全体をロールバックすることです。 after_saveに別のsaveを追加すると、無限ループになります。

4
Matzi

データベースに対して2つのクエリを実行して再帰を心配する代わりに、サーバーに送信する前にデータペイロードを変更することを検討することをお勧めします。

class User < AR::Base
      before_save :change_url

      def change_url
          url = "www.johnseena.com"
      end
end
1
ProLoser

ここで私を助けてくれたすべての人に感謝します。これが私の問題を解決した解決策です。注文モデルによって次のように変更しました。

class Order < ActiveRecord::Base

  has_and_belongs_to_many :users

  validates :item, presence: true

  def add_order(username, order)
    user = User.where(username: username).first
    if !user.nil?
      user.orders.create(item: order.item)
    end
  end

  def remove_order(order)
  end

end
0
CodeYogi