Creating a Rails Concern which accepts arguments

I wanted to create a Rails Concern which can accept arguments from the parent and/or it’s inherited sub-classes.

Most examples I came across online were simple Concerns which didn’t take any parameters or arguments. So here’s how I went about creating one. Let’s call it Arguable for the sake of this blog post.

Implementation:

module Arguable
  extend ActiveSupport::Concern

  module ClassMethods
    attr_reader :arguable_opts

    private

    def arguable(opts={})
      @arguable_opts = opts
    end
  end

  def do_something
    opts = get_arguable_opts
    excluded_attrs = opts[:except] || []
    included_attrs = opts[:only] || []
    custom_attrs = opts[:custom] || {}
    #Do something with the attrs here

    puts opts
  end

  def get_arguable_opts
    if self.class.arguable_opts.blank? && self.class.superclass.arguable_opts.present?
      opts = self.class.superclass.arguable_opts
    elsif self.class.arguable_opts.present? && self.class.superclass.arguable_opts.present?
      opts = self.class.superclass.arguable_opts.merge(self.class.arguable_opts)
    else
      opts = self.class.arguable_opts
    end
    opts || {}
  end
end

Usage:

class Shape > ActiveRecord::Base
  include Arguable
  arguable exclude: [:id]
end

class Circle > Shape
  include Arguable
  arguable include: [:order], custom: {foo: 'bar'}
end

Circle’s options would then have exclude available from it’s parent class and all the other include and custom options available from the subclass.

> c = Circle.find(1)
> c.do_something # => {exclude: [:id], include: [:order], custom: {foo: 'bar'}}
If you have any questions or comments, please post them below. If you liked this post, you can share it with your followers or follow me on Twitter!