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.

Rails concerns are defined by extending ActiveSupport::Concern module. By extending this the module can define two blocks:

  • included: Any code written inside this block is evaluated in the context of the including class. That means if we define a method in this block then that’ll be available to the class in which the concern is included.
  • class_methods: The methods added inside this block become the class methods on the including class.

Here’s is an example where we’re creating a Visible module as a concern and using it in Post class:

# visible.rb

module Visible
  extend ActiveSupport::Concern

  # The code inside the included block is evaluated
  # in the context of the class that includes the Visible concern.
  # You can write class macros here, and
  # any methods become instance methods of the including class.
  included do
    attr_accessor :visible_to

    def is_visible?
      visible_to.present?
    end
  end

  # The methods added inside the class_methods block (or, ClassMethods module)
  # become the class methods on the including class.
  class_methods do
    def count_all_visible
      all.select { |item| item.is_visible? }
    end
  end

and then we use it in Post class:

class Post
  include Visible

end

Post class will have visible_to as an attribute and is_visible? as an instance method while it’ll have a class method count_all_visible:

post = Post.new
post.visiblt_to = 'reader'
post.is_visible?
# true

Post.count_all_visible
# []

Concerns are used to abstract away common functionality. It helps in reusing it in different classes and DRYing out your code.