Mastering extend and when you want class methods and instance methods for your class

Mastering extend and when you want class methods and instance methods for your class

I just realized something cool, which is the underlying of including same module for a class and share instance and class methods with that class.

So here is the trick

You have this simple module:

module TestModule
  def test_name
    'test_name'
  end
end

And this class

class Test
  def name
    'Test'
  end
end
Test.extend(TestModule)
irb(main):033> Test.test_name
=> "test_name"
irb(main):034> Test.new.name
=> "Test"

So that is why if you want to include both instance and class methods, with something like this

class Test
  include TestModule
end

How would you include some as class methods, and the answer is by defining those methods in a module or subgroup within the module, and it would look like this

module TestModule
  def instance_method
    'instance method'
  end

  module TheClassMethods
    def class_hello
      'class_hello'
    end
  end

  def self.included(base)
    base.extend(TheClassMethods)
  end
end

class Test
  include TestModule
end

So now you can access both of them

Test.new.instance_method # instance method
Test.class_hello # class_hello

NOTE: remember that it is included in the past

def self.included(base)
  base.extend(YouClassMethodsToShare)
end

And active_support/concern comparison

module M
  def self.included(klass)
    klass.extend ClassMethods
    klass.class_eval do
      scope :disabled, -> { where(disabled: true) }
    end
  end

  def instance_method
    'instance method'
  end

  module ClassMethods do
     def class_method_one
       'class method'
     end
  end
end

Vs

require 'active_support/concern'

module M
  extend ActiveSupport::Concern

  included do
    scope :disabled, -> { where(disabled: true) }

    def self.direct_class_method_here
      ..
    end
  end

class_methods do
    def class_method_one
      'class method one'
    end
  end
end

class YourClass
  include M
end