Note: I know what I'm doing here is probably stupid but I'm not even necessarily going to use this code I'm just curious at this point.
I'm trying to dynamically add an empty Rails scope to a class in the event a specific method is missing on the class
This documentation in particular seems to suggest this should be possible: https://api.rubyonrails.org/classes/ActiveSupport/Concern.html
module Mod
extend ActiveSupport::Concern
class_methods do
def method_missing(m, *args, &block)
if m.match? /method/
klass = class << self; self; end
klass.class_eval { scope :method, -> {} }
end
end
end
end
klass is correctly set to the class here however trying to eval the creation of the scope fails with undefined method 'scope' for #<Class:0x0000560e35d2eb48>
however when I call klass.ancestors
I can confirm that klass is inheriting from ActiveRecord::Base
and should have scope.
Any ideas why I can't class_eval
scope
here
Assume that there's a class Person < ActiveRecord::Base
that will include your module Mod
.
In Ruby, inheritant hierarchy look like below (the horizontal superclass chain):
Class Class
| |
Person -superclass-> ActiveRecord::Base
So that Person.class
will not return ActiveRecord::Base
but Class:Person
(the vertical chain above), that mean your code kclass = class << self; self; end
actually return Person.class
which is Class:Person
- a Class object that has not anything relative to ActiveRecord::Base - so it'll not respond_to? :scope
module Mod
extend ActiveSupport::Concern
class_methods do
# override Person#method_missing
def method_missing(m, *args, &block)
# anytime call Person.a_method_that_not_be_defined
puts self # Person
kclass = class << self; self; end # <--- Class:Person
So in this case, you should use self.class_eval
instead of kclass.class_eval
.