首页 > 解决方案 > 如何处理来自网站的 API 调用,从而显示属于该网站的信息?

问题描述

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

目标

我想为自行车租赁公司提供在他们自己的网站上实施预订表格的选项,这样他们就可以让客户为特定的自行车创建预订。

然后,此预订表格会将可用自行车从我的 Rails 应用程序带到他们的网站,然后将新的预订数据发送回 Rails 应用程序。

问题

如何将商店的网站链接到Shop我的应用程序中的特定网站。因此,确保特定网站确实应该能够获取属于Shop.

代码

楷模

class Shop < ApplicationRecord
  has_many :bike_categories, dependent: :destroy
  has_many :bikes, through: :bike_categories
  has_many :user_shops, dependent: :destroy
  has_many :users, through: :user_shops
  has_many :reservations, dependent: :destroy
  accepts_nested_attributes_for :users, allow_destroy: true, reject_if: ->(attrs) { attrs['email'].blank? || attrs['role'].blank?}
end

class User < ApplicationRecord
  has_many :user_shops, dependent: :destroy
  has_many :shops, through: :user_shops
  accepts_nested_attributes_for :user_shops
  enum role: [:owner, :admin, :employee, :accountant, :demo, :app_owner]
end

class Reservation < ApplicationRecord
  belongs_to :shop
  belongs_to :bike
end

控制器/api/v1/reservations_controller

  def create
    # How to know/specify which shop?
    @shop = Shop.new(shop_params)
    authorize @shop
    if @shop.save
      render :show, status: :created
    else
      render_error
    end
  end

标签: ruby-on-railsjsonapi-design

解决方案


这是嵌套资源的教科书示例。在 REST 中,嵌套资源嵌套在另一个资源的路径中:

/authors/1/books
/countries/uk/cities
/blogs/1/posts/2

这里的天才在于路径本身描述了资源之间的关系。

您可以通过将块传递给来使路由嵌套resources

namespace :api do
  namespace :v1 do
    resources :shops do 
      resources :reservations, shallow: true
    end
  end
end

shallow选项仅使集合路由嵌套(新建、创建、索引),这通常是一件好事,因为无论如何记录都有一个唯一的 id,它们可以通过它来获取。

/blogs/1/posts/2是深度嵌套路由的一个例子。如果 id 是唯一的,我们应该能够获得完全相同的资源,通过/posts/2它大大简化代码,因为它不需要知道blog.

module API
  module V1
    class ReservationsController < ApiController
      before_action :set_shop, only: [:create, :index]

      # GET /api/v1/shops/1/resevations
      def index
        @reservations = @shop.reservations
      end 

      # POST/api/v1/shops/1/resevations
      def create
        @reservation = @shop.reservations.new(reservation_params)
        # ...
      end

      # ...
      private

      def set_shop
         @shop = Shop.includes(:reservations).find(params[:shop_id])
      end

      # ...
    end
  end
end

推荐阅读