当我有一个ActiveRecord
扩展名(略):重写setter方法包括InstanceMethods模块
module HasPublishDates
def self.included(base)
base.send :extend, ClassMethods
end
module ClassMethods
def has_publish_dates(*args)
attr_accessor :never_expire
include InstanceMethods
end
end
module InstanceMethods
def never_expire=(value)
@never_expire = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
end
def another_instance_method
'something to return'
end
end
end
ActiveSupport.on_load(:active_record) do
include HasPublishDates
end
可以称为像这样:
class MyModel < ActiveRecord::Base
has_publish_dates
...
end
的想法是,never_expire=
应重写setter由attr_accessor :never_expire
定义。然而,这似乎并不奏效:
m = MyModel.new
m.never_expire #=> nil
m.never_expire = '1' #=> '1'
m.never_expire #=> '1' should be true if never_expire= has been overridden
m.another_instance_method #=> 'something to return' works as expected
正如你所看到的,another_instance_method
被包括在内,按预期工作,但never_expire=
未覆盖二传手如我所料。
如果我改变HasPublishDates使用class_eval
然后它按预期工作:
module HasPublishDates
...
module ClassMethods
def has_publish_dates(*args)
...
class_eval do
def never_expire=(value)
@never_expire = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
end
def another_instance_method
'something to return'
end
end
end
end
end
...
m = MyModel.new
m.never_expire #=> nil
m.never_expire = '1' #=> true
m.never_expire #=> true
m.another_instance_method #=> 'something to return'
我想,这是因为之前attr_accessor :never_expire
被称为has_publish_dates
是InstanceMethods
定义。
尽管我认为class_eval
是做的事情我也喜欢有暴露我的实例方法的文档,所以没有“神奇”时,另一位开发人员正试图用我的代码的想法的一种优雅的方式。
反正我有可以使用include InstanceMethods
办法在这种情况下?