I'm trying to write a general purpose module to apply the method_missing pattern for dynamic method creation to some of my Rails models. These models have both class methods and instance methods. While I can write a module fairly straightforwardly for either the class case:
module ClassVersion
extend ActiveSupport::Concern
module ClassMethods
def method_missing(meth, *args, &block)
if meth.to_s =~ /^(.+)_async$/
Async::handle_async self, $1, *args, &block
else
super meth, *args, &block
end
end
# Logic for this method MUST match that of the detection in method_missing
def respond_to_missing?(method_name, include_private = false)
Async::async?(method_name) || super
end
end
end
or the instance case:
module InstanceVersion
extend ActiveSupport::Concern
def method_missing(meth, *args, &block)
if meth.to_s =~ /^(.+)_async$/
Async::handle_async self, $1, *args, &block
else
super meth, *args, &block
end
end
# Logic for this method MUST match that of the detection in method_missing
def respond_to_missing?(method_name, include_private = false)
Async::async?(method_name) || super
end
end
... I can't seem to support both cases in the same class. Is there a better way to override method_missing such that both cases are supported? I'm on Rails 3.2....
What you are trying to achieve is pretty straightforward, and unusual at the same time. ActiveSupport::Concern
is giving you possibility of defining nested ClassMethods
module that is extending base class on included
module hook. Usually this is handy, because you don't want to augment both class and its instances with the same methods.
What you need to do is stop using ActiveSupport::Concern
and write included
hook to meet your particular needs:
module AsyncModule
def method_missing(meth, *args, &block)
if meth.to_s =~ /^(.+)_async$/
Async::handle_async self, $1, *args, &block
else
super meth, *args, &block
end
end
# Logic for this method MUST match that of the detection in method_missing
def respond_to_missing?(method_name, include_private = false)
Async::async?(method_name) || super
end
private
def self.included(base)
base.extend self
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With