當我有一個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
辦法在這種情況下?