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.
Add gem 'sortable-by'
to your Gemfile.
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