Sortable By

Build Status License

ActiveRecord plugin to parse the sort order from a query parameter, match against a white-list and generate a scope. Useful for JSON-API compatibility.

Installation

Add gem 'sortable-by' to your Gemfile.

Usage

Simple:

class Post < ActiveRecord::Base
  sortable_by :title, :id
end

Post.sorted_by('title')     # => ORDER BY posts.title ASC
Post.sorted_by('-title')    # => ORDER BY posts.title DESC
Post.sorted_by('bad,title') # => ORDER BY posts.title ASC
Post.sorted_by(nil)         # => ORDER BY posts.title ASC

Case-insensitive:

class Post < ActiveRecord::Base
  sortable_by do |x|
    x.field :title, as: arel_table[:title].lower
    x.field :id
  end
end

Post.sorted_by('title') # => ORDER BY LOWER(posts.title) ASC

With custom default:

class Post < ActiveRecord::Base
  sortable_by :id, :topic, :created_at, default: 'topic,-created_at'
end

Post.sorted_by(nil) # => ORDER BY posts.topic ASC, posts.created_at DESC

Composition:

class App < ActiveRecord::Base
  sortable_by :name, default: '-version' do |x|
    x.field :version, as: i[major minor patch]]
  end
end

App.sorted_by('version') # => ORDER BY apps.major ASC, apps.minor ASC, apps.patch ASC
App.sorted_by(nil)       # => ORDER BY apps.major DESC, apps.minor DESC, apps.patch DESC

Associations (eager load):

class Product < ActiveRecord::Base
  belongs_to :shop
  sortable_by do |x|
    x.field :name, as: arel_table[:name].lower
    x.field :shop, as: Shop.arel_table[:name].lower, eager_load: :shop
    x.default 'shop,name'
  end
end

Associations (custom scope):

class Product < ActiveRecord::Base
  belongs_to :shop
  sortable_by do |x|
    x.field :shop, as: Shop.arel_table[:name].lower, scope: -> { joins(:shop) }
  end
end