-
-
Save msuzoagu/8c2d9ebe73a31178684c98b8b34d0abc to your computer and use it in GitHub Desktop.
Rails API Filtering and Sorting
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/models/experience.rb | |
# | |
# == Schema Information | |
# | |
# Table name: experiences | |
# | |
# id :integer not null, primary key | |
# title :string | |
# description :text | |
# created_at :datetime not null | |
# updated_at :datetime not null | |
# city_id :integer | |
# price :integer default(0) | |
# distance :integer | |
# duration :integer | |
# | |
class Experience < ActiveRecord::Base | |
belongs_to :city | |
has_many :categorizations | |
has_many :categories, through: :categorizations | |
scope :by_city, -> (city_ids) { where(city_id: city_ids) } | |
scope :by_price, -> (from, to) { where("price >= ? AND price <= ?", from, to) } | |
scope :by_duration, -> (from, to) { where("duration >= ? AND duration <= ?", from, to) } | |
scope :by_distance, -> (from, to) { where("distance >= ? AND distance <= ?", from, to) } | |
scope :by_category, -> (category_ids) { joins(:categories).where(categories: { id: category_ids }) } | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/serializers/experience_serializer.rb | |
class ExperienceSerializer < ActiveModel::Serializer | |
attribute :id | |
attribute :title | |
attribute :description | |
attribute :price | |
attribute :distance | |
attribute :duration | |
belongs_to :city | |
has_many :categories | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/controllers/api/v1/experiences_controller.rb | |
class Api::V1::ExperiencesController < Api::V1::BaseController | |
include Orderable | |
before_filter :authenticate_user! | |
# Filters: | |
# /api/v1/experiences?by_price[from]=100&by_price[to]=999 | |
# /api/v1/experiences?by_category=1,2,3 | |
# /api/v1/experiences?by_city=1,2,3 | |
# /api/v1/experiences?by_duration[from]=10&by_duration[to]=60 | |
# | |
has_scope :by_category, only: :index | |
has_scope :by_city, only: :index | |
has_scope :by_price, using: [:from, :to], only: :index | |
has_scope :by_duration, using: [:from, :to], only: :index | |
has_scope :by_distance, using: [:from, :to], only: :index | |
# GET /api/v1/experiences | |
def index | |
@experiences = apply_scopes(Experience). | |
order(ordering_params(params)). | |
# fix N+1 query problem | |
includes(:city, :user, :categories). | |
all | |
render json: @experiences | |
end | |
end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/controllers/concerns/orderable.rb | |
module Orderable | |
extend ActiveSupport::Concern | |
module ClassMethods | |
end | |
# A list of the param names that can be used for ordering the model list | |
def ordering_params(params) | |
# For example it retrieves a list of experiences in descending order of price. | |
# Within a specific price, older experiences are ordered first | |
# | |
# GET /api/v1/experiences?sort=-price,created_at | |
# ordering_params(params) # => { price: :desc, created_at: :asc } | |
# Experience.order(price: :desc, created_at: :asc) | |
# | |
ordering = {} | |
if params[:sort] | |
sort_order = { '+' => :asc, '-' => :desc } | |
sorted_params = params[:sort].split(',') | |
sorted_params.each do |attr| | |
sort_sign = (attr =~ /\A[+-]/) ? attr.slice!(0) : '+' | |
model = controller_name.classify.constantize | |
if model.attribute_names.include?(attr) | |
ordering[attr] = sort_order[sort_sign] | |
end | |
end | |
end | |
return ordering | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment