我正在使用ActiveAttr,它为您提供了通过块选项进行很好的初始化:
person = Person.new() do |p|
p.first_name = 'test'
p.last_name = 'man'
end
但是,在包含 ActiveAttr::Model 的特定类中,我想绕过此功能,因为我想将该块用于其他用途。所以我们来了:
class Imperator::Command
include ActiveAttr::Model
end
class MyCommand < Imperator::Command
def initialize(*args, &block)
@my_block = block
super(*args)
end
end
这很糟糕,因为块仍然被传递到链上,最终在 ActiveAttr 内部,运行以下代码:
def initialize(*)
super
yield self if block_given?
end
因此,如果我的电话如下所示:
MyCommand.new() { |date| date.advance(month: 1) }
它失败如下:
NoMethodError: undefined method `advance' for #<MyCommand:0x007fe432c4fb80>
由于MyCommand没有方法:提前它,对MyCommand的调用显然失败了。
所以我的问题是,有没有办法在我再次调用super
之前从方法签名中删除块,以便块不会比我覆盖的初始值设定项更远?
尝试
super(*args,&nil)
&使 ruby 使用 nil 作为块,而 ruby 似乎足够聪明,意识到这意味着没有块。
这当然是一个巧妙的技巧,但更好的方法是不要直接使用 ActiveAttr::Model 模块,而只包含您需要的模块。
而不是
class Imperator::Command
include ActiveAttr::Model
end
做
class Imperator::Command
include BasicModel
# include BlockInitialization
include Logger
include MassAssignmentSecurity
include AttributeDefaults
include QueryAttributes
include TypecastedAttributes
def initialize(*args, &block)
@my_block = block
super(*args)
end
end
一旦你看到ActiveAttr::Model正在做的分解视图,可能还有其他你真的不想要的东西。 在这种情况下,只需省略包含即可。 目的是为模型构建提供一种点菜式的方法。