是否可以向单个ActiveRecord实例添加回调?作为进一步的约束,这是继续使用库,因此我无法控制该类(除了对其进行修补)。
这或多或少是我想做的事情:
def do_something_creazy
message = Message.new
message.on_save_call :do_even_more_crazy_stuff
end
def do_even_more_crazy_stuff(message)
puts "Message #{message} has been saved! Hallelujah!"
end
答案 0 :(得分:5)
您可以通过在创建对象后立即向对象添加回调来执行此类操作,就像您所说的那样,修补默认的AR before_save
方法:
def do_something_ballsy
msg = Message.new
def msg.before_save(msg)
puts "Message #{msg} is saved."
# Calls before_save defined in the model
super
end
end
答案 1 :(得分:3)
对于类似这样的事情,你总是可以定义自己的疯狂处理程序:
class Something < ActiveRecord::Base
before_save :run_before_save_callbacks
def before_save(&block)
@before_save_callbacks ||= [ ]
@before_save_callbacks << block
end
protected
def run_before_save_callbacks
return unless @before_save_callbacks
@before_save_callbacks.each do |callback|
callback.call
end
end
end
这可以更通用,或者ActiveRecord :: Base扩展,适用于您的问题范围。使用它应该很容易:
something = Something.new
something.before_save do
Rails.logger.warn("I'm saving!")
end
答案 2 :(得分:1)
我想在我自己的项目中使用这种方法,以便能够在“保存”中注入其他操作。来自我的控制器层的模型的动作。我将Tadman的答案进一步提升,创建了一个可以注入活动模型类的模块:
module InstanceCallbacks
extend ActiveSupport::Concern
CALLBACKS = [:before_validation, :after_validation, :before_save, :before_create, :after_create, :after_save, :after_commit]
included do
CALLBACKS.each do |callback|
class_eval <<-RUBY, __FILE__, __LINE__
#{callback} :run_#{callback}_instance_callbacks
def run_#{callback}_instance_callbacks
return unless @instance_#{callback}_callbacks
@instance_#{callback}_callbacks.each do |callback|
callback.call
end
end
def #{callback}(&callback)
@instance_#{callback}_callbacks ||= []
@instance_#{callback}_callbacks << callback
end
RUBY
end
end
end
这允许您通过包含模块将完整的实例回调注入任何模型。在这种情况下:
class Message
include InstanceCallbacks
end
然后你可以做以下事情:
m = Message.new
m.after_save do
puts "In after_save callback"
end
m.save!
答案 3 :(得分:1)
要添加到bobthabuilda的答案 - 而不是在对象元类上定义方法,请使用模块扩展对象:
def do_something_ballsy
callback = Module.new do
def before_save(msg)
puts "Message #{msg} is saved."
# Calls before_save defined in the model
super
end
end
msg = Message.new
msg.extend(callback)
end
这样,您可以定义多个回调,它们将按照您添加它们的相反顺序执行。
答案 4 :(得分:1)
以下将允许您使用普通的before_save
构造,即在类上调用它,只有在这种情况下,您在实例的元类上调用它,以便没有{{{{{{ 1}}会受到影响。 (在Ruby 1.9,Rails 3.13中测试)
Message
测试它:
msg = Message.new
class << msg
before_save -> { puts "Message #{self} is saved" } # Here, `self` is the msg instance
end
Message.before_save # Calling this with no args will ensure that it gets added to the callbacks chain (but only for your instance)