Neeraj
Neeraj Ruby on Rails Expert, Architect & Evangelist | Full Stack Web Developer | Programmer | Open Source Contributor | RubyConf Speaker

Is ActiveSupport::Concern really Another Concern?

Is ActiveSupport::Concern really Another Concern?

In Ruby world, Rails is a well known web-framework and ActiveSupport is an integrated component. ActiveSupport is a ruby gem which comes with rails by default. But, we can also use this library or gem separately. ActiveSupport is very easy to understand upto the extend that if you are planning to read the source code of rails, then start with ActiveSupport. So, today I am going to throw some light on ActiveSupport::Concern which is also one of the component of ActiveSupport. Is ActiveSupport::Concern really Another Concern?

This post is for those who are new to ActiveSupport. Who constantly do utility work like encoding, or decoding JSON, generating random number, number to currency conversion etc. But never got the chance to find out the reason behind this. Have you ever looked into the source code of any rubygem where you found the statement like extend ActiveSupport::Concern. If yes, are you familiar with this statement? Why do we use this? Trust me ActiveSupport::Concern is not a concern, but to make your life easy.

ActiveSupport::Concern is useful in mixin or modules. It is more useful whenever you are building your own rubygem.

Without ActiveSupport::Concern


We can definitely achieve our goals without ActiveSupport::Concern. But it will insist you to write more code and introduce more complexity in your code base.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# my Foo mixin or module
module Foo
  module ClassMethods
    def class_method
      puts "I am inside bar method"
    end
  end

  module InstanceMethods
    def instance_method
      puts "I am inside foo method"
    end
  end

  def self.included(base)
    base.send :include, InstanceMethods
    base.send :extend, ClassMethods
    puts "FooBar included"
  end
end
1
2
3
4
5
6
7
# my Bar class
class Bar
  include Foo
end

Bar.class_method
Bar.new.instance_method

Here I created a Foo module and included this module into my Bar class. Whenever include Foo will execute, it will trigger my overridden method self.included(base) method in Foo module. base is the reference of the class in which I have included my module. And then Inside self.included(base), I am manually including and extending my ClassMethods and InstanceMethonds.

But I could say that this is not a good code. Why? Because first, I am over-ridding included method which is not good. Second, it is decreasing the readability of code. People have to struggle with code in order to understand the whole process.

With ActiveSupport::Concern

Now the same code could be written with the help of ActiveSupport::Concern. Trust me it will reduce the complexity and increase the readability.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# my Foo mixin or module
require 'active_support/concern.rb'

module Foo
  extend ActiveSupport::Concern

  module ClassMethods
    def class_method
      puts "I am inside bar method"
    end
  end

  def instance_method
    puts "I am inside foo method"
  end

  included do
    puts "FooBar included"
  end
end
1
2
3
4
5
6
7
# my Bar class
class Bar
  include Foo
end

Bar.class_method
Bar.new.instance_method

module InstanceMethods is also removed because methods inside Foo module will come under InstanceMethods module by default. You can also notice that self.included(base) is also changed to included only. Now You can override included method for your other useful purpose.

Rating:

comments powered by Disqus