Ho un ActiveRecord
estensione (abbreviato):overriding metodo setter per attr_accessor quando comprese InstanceMethods modulo
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
che può essere definito così:
class MyModel < ActiveRecord::Base
has_publish_dates
...
end
L'idea è che never_expire=
dovrebbe ignorare la setter definito da attr_accessor :never_expire
. Tuttavia, non sembra funzionare:
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
Come si può vedere, another_instance_method
è stata inclusa e funziona come previsto, ma never_expire=
non è prevalente il setter come mi aspettavo.
Se cambio HasPublishDates usare class_eval
allora funziona come previsto:
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'
immagino che questo è perché InstanceMethods
è definito prima attr_accessor :never_expire
è chiamato da has_publish_dates
.
Anche se penso che class_eval
sia un modo elegante di fare le cose mi piace anche l'idea di avere i miei metodi di istanza esposti per la documentazione, quindi non c'è "magia" quando un altro sviluppatore sta cercando di usare il mio codice.
È possibile utilizzare l'approccio include InstanceMethods
in questo scenario?