Skip to content

Instantly share code, notes, and snippets.

@claritee
Last active December 6, 2017 10:56
Show Gist options
  • Save claritee/d2ec5247013af3e31b3944a504a9d90c to your computer and use it in GitHub Desktop.
Save claritee/d2ec5247013af3e31b3944a504a9d90c to your computer and use it in GitHub Desktop.

Rails Concerns

Extract common and / or context specific chunks of code. DRY code, keep models clean and avoid them getting too fat and messy.

More info: https://medium.com/@carlescliment/about-rails-concerns-a6b2f1776d7d

Cons

  • Circular dependencies
  • Implicitness can be hard to locate dependencies
  • Favour composition over concerns

Example

Source: https://stackoverflow.com/questions/14541823/how-to-use-concerns-in-rails-4

# 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment