我正在尝试编写一个库,以编程方式将 around_update
/around_destroy
回调添加到 ActiveRecord 模型。
因此,常规模型看起来像这样并且按预期工作:
class User < ActiveRecord::Base
around_update :test_update
def test_update
Rails.logger.debug "test_update"
yield
Rails.logger.debug "Finished test_update"
end
end
u=User.last
u.name = 'something'
u.save
######### output (as expected):
# test_update
# Finished test_update
我的小图书馆(显然只是骨架)看起来像这样:
# A module for creating around callbacks in a model
module Piddle
module TimelineFor
def self.included(klass)
klass.send(:extend, ClassMethods)
end
module ClassMethods
def timeline_for(event, opts={})
method_name = :"timeline_for_#{event.to_s}"
define_method(method_name) do |&block|
Rails.logger.debug method_name.to_s
yield block
Rails.logger.debug "After yield in #{method_name.to_s}"
end
send(:around_update, method_name)
end
end
end
end
它定义了一个 timeline_for 方法,该方法应该添加 timeline_for_update 方法并使其成为 around_update 事件的回调。我想使用的用户模型是这样的:
# second version of the User model using Piddle to create the callback
require 'piddle/piddle'
class User < ActiveRecord::Base
include Piddle::TimelineFor
timeline_for :update
end
u=User.last
u.name = 'gfgfhfhfgh'
u.save
在我看到的输出中
timeline_for_update
LocalJumpError: no block given (yield)
from /vagrant/lib/piddle/piddle.rb:13:in `block in timeline_for'
第一行输出表示正在调用方法但未传入 block 。
任何想法或替代实现?
最佳答案
问题是,如果您从 define_method
调用 yield
,ruby 会将其解释为试图屈服于传递给 timeline_for 的(不存在的) block
,不是 block
rails 传递给 timeline_for_foo
您已将 block
传递给您,因此您可以直接调用它:
def timeline_for event
method_name = "timeline_for_#{event}"
define_method method_name do |&block|
ActiveRecord::Base.logger.debug "before #{method_name} yield"
block.call
ActiveRecord::Base.logger.debug "after #{method_name} yield"
end
send :around_update, method_name.to_sym #must use a symbol here
end
关于ruby-on-rails - 以编程方式定义 around_ 回调时为 "no block given",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12287708/