I am reading some codes which use the concerns in Rails 4.
I read some articles to say, if we would like to include class methods
using module ClassMethods
, but the code I read using something like:
class_methods do
def ****
end
end
Concerns allow us to include modules with methods (both instance and class) and constants into a class so that the including class can use them. The code inside the included block is evaluated in the context of the including class.
ActiveSupport's Concern module allows us to mix in callbacks, class and instance methods, and create associations on target objects. This module has an included method, which takes a block, as well as an append_features method and class_methods block, which you can read about in the source code.
Concern can appear somewhere as model, controller and at here you can write module for yourself. And with general module is write in lib folder. Both can be used by way include or extend into a class.
In simple words, the difference between include and extend is that 'include' is for adding methods only to an instance of a class and 'extend' is for adding methods to the class but not to its instance.
ActiveSupport::Concern
provides syntactic sugar for common Ruby patterns for module mixins.
When you are using modules as mixins you can't just use self
to declare class methods like you would from a class:
module Foo
def self.bar
"Hello World"
end
def instance_method
"Hello World"
end
end
class Baz
include Foo
end
irb(main):010:0> Baz.bar
NoMethodError: undefined method `bar' for Baz:Class
from (irb):10
irb(main):011:0> Foo.bar
=> "Hello World"
irb(main):012:0>
As you can see from the example that actually creates a module method - thats because self
is the module. You can use extend instead:
module Foo
def a_class_method
"Hello World"
end
end
class Bar
extend Foo
end
irb(main):049:0> Bar.a_class_method
=> "Hello World"
But that does not let you declare instance methods in the module. Which is not really that useful.
So the solution is to create an inner module which is commonly named ClassMethods
and extend the class when the module is included:
module Foo
# this is a method thats called when you include the module in a class.
def self.included(base)
base.extend ClassMethods
end
def an_instance_method
end
# the name ClassMethods is just convention.
module ClassMethods
def a_class_method
"Hello World"
end
end
end
class Bar
include Foo
end
irb(main):071:0> Bar.a_class_method
=> "Hello World"
This boilerplate code is found in almost every ruby gem/library.
By extending your module with ActiveSupport::Concern
you can shorten this to just:
module Foo
extend ActiveSupport::Concern
class_methods do
def a_class_method
"Hello World"
end
end
end
Under the hood ActiveSupport::Concern
creates a ClassMethods
module and evaluates the block in the context of the module. Dig into the source if you curious about how it actually does this.
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