我正在创建一个扩展ActiveRecord模型功能的模块。
这是我的初始设置。
我的课程:
class MyClass < ActiveRecord::Base
is_my_modiable
end
和模块:
module MyMod
def self.is_my_modiable
class_eval do
def new_method
self.mod = true
self.save!
end
end
end
end
ActiveRecord::Base(extend,MyMod)
我现在要做的是通过传入一个块来扩展new_method
的功能。像这样:
class MyClass < ActiveRecord::Base
is_my_modiable do
self.something_special
end
end
module MyMod
def self.is_my_modiable
class_eval do
def new_method
yield if block_given?
self.mod = true
self.save!
end
end
end
end
虽然这不起作用,但这是有道理的。在class_eval中,new_method没有被执行,只是被定义,因此在实际调用该方法之前,yield语句不会被执行。
我试图将块分配给class_eval中的类变量,然后在方法中调用该类变量,但是在所有is_my_modiable模型上调用该块,即使它们没有将块传递给方法。
我可能会覆盖该方法以获得相同的效果,但我希望有一种更优雅的方式。
答案 0 :(得分:2)
如果我理解正确,你可以通过将传递的块保存到类对象上的实例变量然后在实例方法中对其进行评估来解决这个问题。
bl.call
不会在这里执行,因为它将在原始上下文(类的)中执行,并且您需要在当前实例的范围内执行它。
module MyMod
def is_my_modiable(&block)
class_eval do
@stored_block = block # back up block
def new_method
bl = self.class.instance_variable_get(:@stored_block) # get from class and execute
instance_eval(&bl) if bl
self.mod = true
self.save!
end
end
end
end
class MyClass
extend MyMod
is_my_modiable do
puts "in my modiable block"
self.something_special
end
def something_special
puts "in something special"
end
attr_accessor :mod
def save!; end
end
MyClass.new.new_method
# >> in my modiable block
# >> in something special
答案 1 :(得分:1)
您可以通过将块指定为方法参数来执行此操作:
module MyMod
def self.is_my_modiable
class_eval do
def new_method(&block)
block.call if block
self.mod = true
self.save!
end
end
end
end