ruby-on-railsruby-on-rails-4dci

How to use concerns in Rails 4


The default Rails 4 project generator now creates the directory "concerns" under controllers and models. I have found some explanations about how to use routing concerns, but nothing about controllers or models.

I am pretty sure it has to do with the current "DCI trend" in the community and would like to give it a try.

The question is, how am I supposed to use this feature, is there a convention on how to define the naming / class hierarchy in order to make it work? How can I include a concern in a model or controller?


Solution

  • So I found it out by myself. It is actually a pretty simple but powerful concept. It has to do with code reuse as in the example below. Basically, the idea is to extract common and / or context specific chunks of code in order to clean up the models and avoid them getting too fat and messy.

    As an example, I'll put one well known pattern, the taggable pattern:

    # app/models/product.rb
    class Product
      include Taggable
    
      ...
    end
    
    # app/models/concerns/taggable.rb
    # notice that the file name has to match the module name 
    # (applying Rails conventions for autoloading)
    module Taggable
      extend ActiveSupport::Concern
    
      included do
        has_many :taggings, as: :taggable
        has_many :tags, through: :taggings
    
        class_attribute :tag_limit
      end
    
      def tags_string
        tags.map(&:name).join(', ')
      end
    
      def tags_string=(tag_string)
        tag_names = tag_string.to_s.split(', ')
    
        tag_names.each do |tag_name|
          tags.build(name: tag_name)
        end
      end
    
      # methods defined here are going to extend the class, not the instance of it
      module ClassMethods
    
        def tag_limit(value)
          self.tag_limit_value = value
        end
    
      end
    
    end
    

    So following the Product sample, you can add Taggable to any class you desire and share its functionality.

    This is pretty well explained by DHH:

    In Rails 4, we’re going to invite programmers to use concerns with the default app/models/concerns and app/controllers/concerns directories that are automatically part of the load path. Together with the ActiveSupport::Concern wrapper, it’s just enough support to make this light-weight factoring mechanism shine.