如何使用 Jbuilder & Rails 生成自定义 json 响应

Posted

技术标签:

【中文标题】如何使用 Jbuilder & Rails 生成自定义 json 响应【英文标题】:How to generate a custom json response with Jbuilder & Rails 【发布时间】:2020-05-15 18:11:54 【问题描述】:

在我的 Ruby on Rails 应用中,自行车租赁公司可以管理他们所有的自行车(预订、付款等)。

上下文 我想为自行车租赁公司 (shops) 提供在他们自己的网站上实施预订表格的选项,这样他们就可以让客户预订bike

然后此预订表格将显示bike_categories,其中bikes 可用于给定的arrivaldeparture 日期。

问题 为了管理这个,我想生成一个 API 控制器操作,显示某个 bike_categoryavailability,显示属于这个 bike_category 的可用 bikes 数量的 count

根据这篇文章

Design RESTful query API with a long list of query parameters

我应该能够在我的 api 中处理查询,但是如何使用 Jbuilder 在视图中返回 count

代码

模型

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

路线

  namespace :api, defaults:  format: :json  do
    namespace :v1 do
      resources :shops, only: [ :show ]
      resources :reservations, only: [ :show, :create ]
      resources :reservation_contacts, only: [:show, :create]
      resources :reservation_options, only: [:show, :create]
      resources :bike_categories, only: [:index, :show] do
        get :availability, on: :member
      end
    end
  end

控制器/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
    @user = current_user
    bike_category = params[:bike_category]
    if @user.shop.bike_categories.include? bike_category
      arrival = params[:arrival]
      departure = params[:departure]
      shop = bike_category.shop
      reservations_overlap = shop.reservations.where("reservations.arrival >= ? AND ? >= reservations.arrival", arrival, departure)
      .or(shop.reservations.where("reservations.arrival <= ? AND ? <= reservations.departure", arrival, arrival)).distinct
      unavailable_bikes = []
      reservations_overlap.each do |res|
        if !unavailable_bikes.include? res.bike && res.bike.bike_category == bike_category
          unavailable_bikes << res.bike
        end
      end
      bikes = bike_category.bikes
      @count = (bikes - unavailable_bikes).length
    else
      error
    end
  end

end

views/api/v1/bike_categories.json.jbuilder

# How to return @count?

【问题讨论】:

使用默认的 json 适配器将 json 渲染到客户端不是更容易吗? 感谢您的评论罗曼。我对这个不是很熟悉。那将如何运作?只需在controllers/api/v1/bike_categories_controller.rb 中包含render json: count: @count 【参考方案1】:
your code here...
if @user.shop.bike_categories.include? bike_category
      arrival = params[:arrival]
      departure = params[:departure]
      shop = bike_category.shop
      reservations_overlap = shop.reservations.where("reservations.arrival >= ? AND ? >= reservations.arrival", arrival, departure)
      .or(shop.reservations.where("reservations.arrival <= ? AND ? <= reservations.departure", arrival, arrival)).distinct
      unavailable_bikes = []
      reservations_overlap.each do |res|
        if !unavailable_bikes.include? res.bike && res.bike.bike_category == bike_category
          unavailable_bikes << res.bike
        end
      end
      bikes = bike_category.bikes
      @count = (bikes - unavailable_bikes).length
      render json: @count, status: :ok, adapter: :json
    else
      error = ...some code here...
      render json: error, status: unprocessed_entity, adapter: :json
    end

我会做这样的事情

【讨论】:

以上是关于如何使用 Jbuilder & Rails 生成自定义 json 响应的主要内容,如果未能解决你的问题,请参考以下文章

使用 Jbuilder(或其他)的 Rails JSON API 布局

使Jbuilder与Rails 5 API模式一起工作

Rails jbuilder DateTime将小数添加到秒

为啥 Rails 找不到我的 jbuilder 模板或不渲染它?

在 Rails 4 中用于 JSON 处理的 jbuilder vs rails-api/active_model_serializers

ruby on rails 4 - 捆绑安装grape-jbuilder