Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override class_method in rails model concern

How does one override a class method defined in a model concern?

This is a bit tricky since you’re not really overriding a class method right? Because it’s using the concern api of definining class methods in the class_methods block.

so say I have a concern that looks like this:

module MyConcern
  extend ActiveSupport::Concern

  class_methods do
    def do_something
       #some code
    end
  end

end

In model.. how would I override that method so that I could call it like we do with super when using inheritance? So in my model I’d like to go:

def self.do_something
  #call module do_something
end

?

like image 524
andy Avatar asked Sep 11 '25 04:09

andy


1 Answers

If you've included MyConcern in the model that defines self.do_something, you should just be able to use super:

module MyConcern
  extend ActiveSupport::Concern

  class_methods do
    def do_something
      puts "I'm do_something in the concern"
    end
  end
end

class UsesMyConcern < ActiveRecord::Base
  include MyConcern

  def self.do_something
    super
  end
end

UsesMyConcern.do_something
# => "I'm do_something in the concern"

If you haven't or don't want to include MyConcern in the model and you want to invoke do_something on the module without creating any intermediary objects, you can change your model to:

class UsesMyConcern < ActiveRecord::Base
  def self.do_something                
    MyConcern::ClassMethods.instance_method(:do_something).bind(self).call
  end
end

UsesMyConcern.do_something
# => "I'm do_something in the concern"

ActiveSupport::Concern.class_methods defines a ClassMethods module in the concern if there isn't one already, and that's where we can find the do_something method.

like image 166
Paul Fioravanti Avatar answered Sep 12 '25 18:09

Paul Fioravanti