/sortable-by

Primary LanguageRubyMIT LicenseMIT

Sortable By

Test 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 LOWER(posts.title) ASC
Post.sorted_by('-title')         # => ORDER BY LOWER(posts.title) DESC
Post.sorted_by('title,-id')      # => ORDER BY LOWER(posts.title) ASC, id DESC
Post.sorted_by(['title', '-id']) # => ORDER BY LOWER(posts.title) ASC, id DESC
Post.sorted_by('bad,title')      # => ORDER BY LOWER(posts.title) ASC
Post.sorted_by(nil)              # => ORDER BY LOWER(posts.title) ASC

Case-sensitive:

class Post < ActiveRecord::Base
  sortable_by do |x|
    x.field :title, case_sensitive: true
    x.field :id
  end
end

Post.sorted_by('title') # => ORDER BY 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 LOWER(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 (custom scope):

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