KatPadi's Point

My First RubyGem Is Called Sorty Sorter

In the Ruby world, mixins are very popular. In fact, I’ve created a number of basic mixins (or concerns) in Rails projects and so it came to a point where I wanted to try converting it to a gem. Why? Because why not? Well, just for the experience.

Anyway, my first RubyGem is called Sorty Sorter. It sorts AR collection when given a set of parameters that will be validated against the whitelisted attributes in the model.

RubyGem: https://rubygems.org/gems/sorty_sorter

GitHub: https://github.com/katpadi/sorty_sorter

GemGoalz

Given an ActiveRecord::Relation collection and some arguments, the gem should:

  1. define the model attributes (and their defaults) for sorting
  2. whitelist the only sortable columns
  3. alias the column name so it won’t be exposed to the outside world
  4. extend ActiveRecord::Relation and add a convenience method to sort according to arguments passed

Howz

I already have the mixin and other classes that will do the goals I mentioned above.

To convert it to a gem, I browsed the http://guides.rubygems.org/make-your-own-gem. Of course. And then I came up with the hows.

2 Things

I want to be able to define something in the model on the class level. This hypothetical (at that point when I was thinking) method will take a hash argument so I can configure options. Anyway, I need to extend ActiveSupport::Concern and define class method and then mix in that method.

ActiveRecord::Base.send(:include, SortySorter::Declaration)

Module#include is private so one way to “hack” it is the code above. It mixes in the sort_with method in the model.

module SortySorter
  module Declaration
    extend ActiveSupport::Concern

    module ClassMethods
      attr_reader :sort_columns
      def sort_with(columns)
        @sort_columns = columns
      end

      def sorty?
        true
      end
    end
  end
end

ActiveRecord::Base.send(:include, SortySorter::Declaration)

And then, I would add to ActiveRecord::Relation exstensions so I can use method sorty_sort within a collection.

module Extensions
  # ActiveRecord extensions
  module ActiveRecord
    # Extensions for ActiveRecord::Relation
    module Relation
      extend ActiveSupport::Concern

      # Introduce a new AR Relation method 🙂
      def sorty_sort(column = nil, direction = nil)
        ::SortySorter::Sort.apply(self, column, direction)
      end

      def sorty_sort!(column = nil, direction = nil)
        ::SortySorter::Sort.apply!(self, column, direction)
      end
    end
  end
end

ActiveSupport.on_load(:active_record) do
  ActiveRecord::Relation.send(:include, Extensions::ActiveRecord::Relation)
end

After doing these things, user can define sort_with in the model and AR collections will have a sorty_sort method.

Leave a Reply

Your email address will not be published. Required fields are marked *