我想在记录更新之前运行验证。我知道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
答案 0 :(得分:3)
ActiveRecord :: Callbacks不支持:on
选项...
在Rails代码库中,提到处理:on
选项的唯一位置是ActiveModel::Validations中的验证模块代码。
如果查看ActiveRecord::Callbacks代码,您会看到没有提到:on
,ActiveRecord :: Callbacks模块也不包含任何将处理的ActiveModel :: Validations模块那个选择。 ActiveModel :: Validations :: Callbacks包含一个include,但它只提供before_
和after_
验证方法的定义。但是,before_validation
和after_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-
的这篇最优秀的文章