如何将查询参数传递给 Rails API 控制器?
How to pass query params to Rails API controller?
在我的 Ruby Rails 应用程序中,自行车租赁公司可以管理他们所有的自行车(预订、付款等)。
上下文
我想为一家自行车租赁公司 (shops
) 提供在他们自己的网站上实施预订表格的选项,这样他们就可以让客户预订 bike
.
- 此预订表格随后会显示
bike_categories
,其中 bikes
可用于给定的 arrival
和 departure
日期。
问题
为了管理这个,我想生成一个 API 控制器操作,显示 availability
某个 bike_category
显示 count
可用数量 bikes
属于这个bike_category
。
据此 post
Design RESTful query API with a long list of query parameters
我应该能够在我的 api 中处理查询,但是如何在我的 Rails 控制器中处理查询?
代码
型号
class Shop < ApplicationRecord
has_many :bike_categories, dependent: :destroy
has_many :bikes, through: :bike_categories
has_many :reservations, dependent: :destroy
end
class Reservation < ApplicationRecord
belongs_to :shop
belongs_to :bike
end
class Bike < ApplicationRecord
belongs_to :bike_category
has_many :reservations, dependent: :destroy
end
class BikeCategory < ApplicationRecord
belongs_to :shop
has_many :bikes, dependent: :destroy
end
路线
# api
namespace :api, defaults: { format: :json } do
namespace :v1 do
resources :shops, only: [ :show ]
resources :reservations, only: [ :show, :create ]
resources :bike_categories, only: [:index, :show, :availability]
end
end
controller/api/v1/bike_categories_controller.rb
class Api::V1::BikeCategoriesController < Api::V1::BaseController
acts_as_token_authentication_handler_for User, only: [:show, :index, availability]
def availability
# How to get the bike_category, arrival and departure?
end
end
Rails 在 params
散列中提供查询字符串参数,它实际上是以下内容的混搭:
- 请求主体(对于 POST、PATCH、PUT 等具有主体的方法)
- 查询字符串
- 路径中的命名段(例如
params[:id]
)。
所以真的没什么:
class Api::V1::BikeCategoriesController < Api::V1::BaseController
acts_as_token_authentication_handler_for User, only: [:show, :index, availability]
def availability
# How to get the bike_category, arrival and departure?
bike_category = params[:bike_categories]
arrival = params[:arrival]
departure = params[:departure]
end
end
但是您的路由配置不正确。您实际上没有 availiblity
的路线。 only
和 except
选项仅限制 resources
生成的默认 CRUD 路由的输出。因此,有效值为:
- 显示
- 指数
- 新
- 创建
- 编辑
- 更新
- 删除
任何其他值都没有任何效果。如果你想添加额外的 RESTful 路线,你可以这样做:
resources :bike_categories, only: [:index, :show] do
# GET .../bike_categories/:bike_category_id/availability
get :availability
# GET .../bike_categories/:id/availability
get :availability, on: :member
# GET .../bike_categories/availability
get :availability, on: :collection
end
您可以使用 has_scope gem.
在您的 Bike 模型中,您可以创建范围 not_reserved
(我假设您将到达和离开的列命名为 arrive_at
和 departure_at
:
class Bike < ApplicationRecord
# ...
scope :not_reserved, -> arrive, departure { left_outer_joins(:reservations).distinct.where("reservations.arrival_at < ? AND reservations.departure_at > ?", departure, arrive) }
# If you need to return the result for a specific bike category
scope :by_bike_category, -> bike_category_id { where(bike_category_id: bike_category_id) }
# ...
end
在您的 BikeCategoriesController 中:
class Api::V1::BikeCategoriesController < Api::V1::BaseController
has_scope :not_reserved, using: [:arrive, :departure], type: :hash
has_scope :by_bike_category
def availability
category_availability = apply_scopes(Bike).group(:bike_category_id).count
render json: category_availability
end
end
您的查询字符串如下:
?not_reserved[arrive]=20200110¬_reserved[departure]=20200125&by_bike_category=3
在我的 Ruby Rails 应用程序中,自行车租赁公司可以管理他们所有的自行车(预订、付款等)。
上下文
我想为一家自行车租赁公司 (shops
) 提供在他们自己的网站上实施预订表格的选项,这样他们就可以让客户预订 bike
.
- 此预订表格随后会显示
bike_categories
,其中bikes
可用于给定的arrival
和departure
日期。
问题
为了管理这个,我想生成一个 API 控制器操作,显示 availability
某个 bike_category
显示 count
可用数量 bikes
属于这个bike_category
。
据此 post
Design RESTful query API with a long list of query parameters
我应该能够在我的 api 中处理查询,但是如何在我的 Rails 控制器中处理查询?
代码
型号
class Shop < ApplicationRecord
has_many :bike_categories, dependent: :destroy
has_many :bikes, through: :bike_categories
has_many :reservations, dependent: :destroy
end
class Reservation < ApplicationRecord
belongs_to :shop
belongs_to :bike
end
class Bike < ApplicationRecord
belongs_to :bike_category
has_many :reservations, dependent: :destroy
end
class BikeCategory < ApplicationRecord
belongs_to :shop
has_many :bikes, dependent: :destroy
end
路线
# api
namespace :api, defaults: { format: :json } do
namespace :v1 do
resources :shops, only: [ :show ]
resources :reservations, only: [ :show, :create ]
resources :bike_categories, only: [:index, :show, :availability]
end
end
controller/api/v1/bike_categories_controller.rb
class Api::V1::BikeCategoriesController < Api::V1::BaseController
acts_as_token_authentication_handler_for User, only: [:show, :index, availability]
def availability
# How to get the bike_category, arrival and departure?
end
end
Rails 在 params
散列中提供查询字符串参数,它实际上是以下内容的混搭:
- 请求主体(对于 POST、PATCH、PUT 等具有主体的方法)
- 查询字符串
- 路径中的命名段(例如
params[:id]
)。
所以真的没什么:
class Api::V1::BikeCategoriesController < Api::V1::BaseController
acts_as_token_authentication_handler_for User, only: [:show, :index, availability]
def availability
# How to get the bike_category, arrival and departure?
bike_category = params[:bike_categories]
arrival = params[:arrival]
departure = params[:departure]
end
end
但是您的路由配置不正确。您实际上没有 availiblity
的路线。 only
和 except
选项仅限制 resources
生成的默认 CRUD 路由的输出。因此,有效值为:
- 显示
- 指数
- 新
- 创建
- 编辑
- 更新
- 删除
任何其他值都没有任何效果。如果你想添加额外的 RESTful 路线,你可以这样做:
resources :bike_categories, only: [:index, :show] do
# GET .../bike_categories/:bike_category_id/availability
get :availability
# GET .../bike_categories/:id/availability
get :availability, on: :member
# GET .../bike_categories/availability
get :availability, on: :collection
end
您可以使用 has_scope gem.
在您的 Bike 模型中,您可以创建范围 not_reserved
(我假设您将到达和离开的列命名为 arrive_at
和 departure_at
:
class Bike < ApplicationRecord
# ...
scope :not_reserved, -> arrive, departure { left_outer_joins(:reservations).distinct.where("reservations.arrival_at < ? AND reservations.departure_at > ?", departure, arrive) }
# If you need to return the result for a specific bike category
scope :by_bike_category, -> bike_category_id { where(bike_category_id: bike_category_id) }
# ...
end
在您的 BikeCategoriesController 中:
class Api::V1::BikeCategoriesController < Api::V1::BaseController
has_scope :not_reserved, using: [:arrive, :departure], type: :hash
has_scope :by_bike_category
def availability
category_availability = apply_scopes(Bike).group(:bike_category_id).count
render json: category_availability
end
end
您的查询字符串如下:
?not_reserved[arrive]=20200110¬_reserved[departure]=20200125&by_bike_category=3