Reputation: 242
I know include is used for access module methods as instance methods while extend is used to access module methods as class methods.
For ActiveSupport::Concern somewhere I see written as,
module Test
include ActiveSupport::Concern
end
while at some places written as,
module Test
extend ActiveSupport::Concern
end
Here my confusion is, ActiveSupport::Concern should be used with include or with extend?
Upvotes: 5
Views: 2842
Reputation: 101811
You need to extend the module with ActiveSupport::Concern
in order for the ActiveSupport::Concern#included
and #class_methods
methods to work properly.
These two methods are after all pretty much the only reason for its existance.
module A
extend ActiveSupport::Concern
# raises ArgumentError (wrong number of arguments (given 0, expected 1))
included do
puts "Hello World"
end
end
module B
extend ActiveSupport::Concern
included do
puts "Hello World"
end
end
class C
include B
end
# Outputs Hello World
Check out what happens if we inspect the included
method:
module AB
include ActiveSupport::Concern
puts method(:included).source_location # nil
end
module ABC
extend ActiveSupport::Concern
puts method(:included).source_location # .../ruby/gems/2.7.0/gems/activesupport-6.0.2.1/lib/active_support/concern.rb
end
When we extend the module with ActiveSupport::Concern
we are putting it on the ancestors chain of ABC
, thus the methods of ActiveSupport::Concern
are available as module methods of ABC
. This does not happen when you use include
and the included
method called is actually Module#included from the Ruby core.
Upvotes: 2
Reputation: 21110
You should use extend ActiveSupport::Concern
, like shown in the examples in the documentation.
By using
ActiveSupport::Concern
the above module could instead be written as:require 'active_support/concern' module M extend ActiveSupport::Concern included do scope :disabled, -> { where(disabled: true) } end class_methods do ... end end
The reason for using extend
is to make the methods defined in ActiveSupport::Concern
available in module context. This allows you to use the methods included
and class_methods
within the module.
When using include
those methods would not be available within the module and instead be available on instances of a class that includes M
.
If you want to know the difference between the two I suggest taking a look at What is the difference between include and extend in Ruby?
Upvotes: 3