做接口的时候,遇到了筛选的问题,不知如何去处理,Google了下,发现了个很简单的解法,实测有效,附上。
问题描述
现有model product,category, schema中信息如下:
Table name products
id :integer
title :string
description :string
price :float
category_id :integer
Table name categories
id :integer
title :string
app/models/product.rb
中:
class Product < ActiveRecord::Base
belongs_to :category
......
end
app/models/category.rb
中:
class Category < ActiveRecord::Base
has_many :products
......
end
app/controllers/api/v1/products_controller.rb
中:
class Api::V1::ExperiencesController < Api::V1::BaseController
# GET /api/v1/products
def index
@products = Product.all
render json: @products
end
end
现在需要得到指定category的products,类似这样:/api/v1/products?category=1
,得到category是1的所有products。以及给定价格区间的products,类似这样:/api/v1/products?price[from]=100&price[to]=999
如何实现?
解答
三步走
安装has_scope gem
gemfile中添加:
gem 'has_scope'
终端bundle,服务器重启。
在model中添加scope
修改
app/models/product.rb
:class Product < ActiveRecord::Base belongs_to :category + scope :category, -> (category_id) { where(category_id: category_id) } + scope :price, -> (from, to) { where("price >= ? AND price <= ?", from, to) } ...... end
在controller中添加has_scope
修改
app/controllers/api/v1/products_controller.rb
:class Api::V1::ExperiencesController < Api::V1::BaseController + has_scope :category, only: :index + has_scope :price, using: [:from, :to], only: :index # GET /api/v1/products def index - @products = Product.all + @products = apply_scopes(Product).includes(:category).all # using includes(:category), fix N+1 query problem render json: @products end end
好,大功告成,用postman测试下,确认正常,cool!