为什么要执行此回调?

时间:2012-03-30 00:47:57

标签: ruby-on-rails ruby-on-rails-3 activerecord

我想在记录更新之前运行验证。我知道before_update但我几乎复制并粘贴了api文档中的第一个代码片段。

http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

我的精简模型看起来像

class User < ActiveRecord::Base
  attr_accessible :email
  validates :email, :presence => true

  before_save(:on => :update) do
    puts "******** before_save on => :update ********"
    # do something
  end
end

如果我进入控制台并创建 new 条目,则会在SQL插入调用上执行此回调。

irb(main):001:0> User.new(:email => "test@test.com").save
  (0.1ms)  begin transaction
******** before_save on => :update ********
SQL (29.1ms)  INSERT INTO "users" ("created_at", "email", "first_name", "last_name", "updated_at") VALUES (?, ?, ?, ?, ?)  [["created_at", Fri, 30 Mar 2012 00:26:33 UTC +00:00], ["email", "test@test.com"], ["first_name", nil], ["last_name", nil], ["updated_at", Fri, 30 Mar 2012 00:26:33 UTC +00:00]]
   (433.1ms)  commit transaction
=> true
irb(main):002:0> 

我原本希望只在更新电话上看到这一点。任何人都可以对此有所了解吗?

[编辑]

我刚刚将回调更改为函数调用,结果没有变化。回调仍然在create上执行。

class User < ActiveRecord::Base

attr_accessible :email
validates :email, :presence => true

before_save :my_before_update, :on => :update

private

def my_before_update
    puts "******** before_save on => :update ********"
    # do something
end

输出相同。

Loading development environment (Rails 3.2.2)
irb(main):001:0> User.new(:email => "test@test.com").save
   (0.1ms)  begin transaction
******** before_save on => :update ********
  SQL (28.2ms)  INSERT INTO "users" ("created_at", "email", "first_name", "last_name",         "updated_at") VALUES (?, ?, ?, ?, ?)  [["created_at", Fri, 30 Mar 2012 02:28:45 UTC +00:00],     ["email", "test@test.com"], ["first_name", nil], ["last_name", nil], ["updated_at", Fri, 30     Mar 2012 02:28:45 UTC +00:00]]
   (131.2ms)  commit transaction
=> true

3 个答案:

答案 0 :(得分:3)

ActiveRecord :: Callbacks不支持:on选项...

在Rails代码库中,提到处理:on选项的唯一位置是ActiveModel::Validations中的验证模块代码。

如果查看ActiveRecord::Callbacks代码,您会看到没有提到:on,ActiveRecord :: Callbacks模块也不包含任何将处理的ActiveModel :: Validations模块那个选择。 ActiveModel :: Validations :: Callbacks包含一个include,但它只提供before_after_验证方法的定义。但是,before_validationafter_validation回调将处理:on选项,如其定义中所见here

答案 1 :(得分:0)

我很确定这是Rails API在不同版本中发生变化的其中一个方面。我记得有一种方法可以将:on作为选项传递给before_save,就像我记得你必须定义一个after_initialize方法(它不能用作回调)一样

目前的方式更清晰,更明确。

如果您确实发现当前文档引用before_save(:on => :update),请查看新的docrails Github存储库,您可以在其中对文档进行分叉,更改和提交更改包括在内(不需要拉动请求或接受)。

答案 2 :(得分:0)

经过一番研究,看起来你是对的,看起来你可以将:on => :update传递给before_save

也许问题来自块表示法,尝试调用这样的函数:

before_save :run_this_before_update, :on => :update

def run_this_before_update
  puts "******** before_save on => :update ********"
  # do something
end

看起来使用这个的一个主要原因是Rails运行回调的顺序,请查看来自pivotallabs http://pivotallabs.com/users/danny/blog/articles/1767-activerecord-callbacks-autosave-before-this-and-that-etc-

的这篇最优秀的文章