首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >REST将资源表示为主资源和子资源。

REST将资源表示为主资源和子资源。
EN

Stack Overflow用户
提问于 2015-12-10 15:13:15
回答 1查看 418关注 0票数 1

在我的Rails 4应用程序中,我有以下模型:

代码语言:javascript
复制
class Location < ActiveRecord::Base
  has_many :location_parking_locations
  has_many :parking_locations, through: :location_parking_locations
end

class LocationParkingLocation < ActiveRecord::Base
  belongs_to :location
  belongs_to :parking_location
end

class ParkingLocation < ActiveRecord::Base
  has_many :location_parking_locations
  has_many :locations, through: :location_parking_locations
end

对路由/locations/1/parking_locations的调用返回位置= 1的停车位置集合。响应中的一些属性来自连接模型( location_parking_location)。例如,响应中的一个parking_locations可能如下所示:

代码语言:javascript
复制
{
  id: 1
  name: 'Test Parking Location'
  description: 'Test description for the parking location'
  upvote_count: 10, <- this field comes from the join model
  downvote_count: 8, <- this field comes from the join model
}

如果用户想要更新一个直接来自停车场的属性,例如名称,我觉得他们应该能够通过一个端点来更新这个属性,该端点将停车场作为一个主要资源,而不是将其作为特定位置的子资源引用。例如,它们应该能够从端点parking_location (而不是特定于特定位置)编辑或检索端点/parking_locations/1

在这种情况下,不应该包括来自location_parking_location (如upvote_count )和downvote_count的字段。

是否有某种允许这种行为的设计模式?还是我应该换个角度考虑这个问题?例如,在检索端点locations/1/parking_locations时,我不应该返回parking_locations的集合,而是应该返回location_parking_locations的集合,该集合可以包括表示来自parking_location的属性的对象。在这种情况下,端点是否应该更改为locations/1/location_parking_locations?例如,响应中的一个对象可能如下所示:

代码语言:javascript
复制
{
  id: 9
  upvote_count: 10,
  downvote_count: 8,
  parking_location: {
    id: 1
    name: 'Test Parking Location'
    description: 'Test description for the parking location'
  }
}

在这种情况下,怎么会有人增加一个新的停车位?它是否会通过发布到/parking_locations端点来完成呢?或者他们是否应该同时创建它并将其添加到某个位置,也许可以通过将其发布到/locations/1/parking_locations

在这种情况下,如果有人想要将一个已经存在的停车位置添加到某个位置,该怎么办?在这种情况下,也许他们应该把/locations/1/parking_locations/{parking_location_id}

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-12-10 15:53:27

路线

您可以通过一些简单的路由和允许的控制器使您的ParkingLocation模型成为主资源和子资源。首先,路由-除了您已经将其作为Location的子资源的位置之外,您还需要在顶层声明它。

代码语言:javascript
复制
resources :locations do
  resources :parking_locations
end

resources :parking_locations

如果现在检查rake routes,您将看到两组连接到ParkingLocationsController的URL,一组位于/parking_locations,另一组嵌套在/locations/:location_id/parking_locations

ParkingLocationsController

您的控制器将始终接收包含params[:id] ID的ParkingLocation。如果您访问嵌套路由,它还将接收包含params[:location_id] ID的Location。任何表单提交等都将包含params[:parking_location],其中包含create/update/etc的其余属性。一个简单的控制器可能如下所示:

代码语言:javascript
复制
class ParkingLocationsController
  def index
    if params[:location_id]
      location = Location.find(params[:location_id])
      @parking_locations = location.parking_locations
    else
      @parking_locations = ParkingLocation.all
    end
  end

  def show
    @parking_location = ParkingLocation.find(params[:id])
  end

  # ...
end

index的工作原理是相同的,而不管location_id参数来自何处:

代码语言:javascript
复制
/locations/1/parking_locations
/parking_locations?location_id=1

添加位置

因为您的RESTful资源是一个ParkingLocation,所以您应该处理ParkingLocationsController#update中的Location添加。为了简单和一致,您的控制器不应该关心路由是PUT /locations/:location_id/parking_locations/:id还是PUT /parking_locations/:idhas_many关联提供ParkingLocation#location_ids=,您可以在任何您喜欢的表单中收集它并传递给控制器。您的update操作看起来与往常一样:

代码语言:javascript
复制
def update
  @parking_location = ParkingLocation.find(params[:id])
  if @parking_location.update(params[:parking_location])
    redirect_to @parking_location
  else
    render :edit
  end
end

这样的请求将设置Location12ParkingLocation 3上。

代码语言:javascript
复制
PUT https://your.server/parking_locations/3?parking_location[location_ids[]]=1&parking_location[location_ids[]]=2

如果您想要追加Location,您需要自己编写更多的代码来处理。如果您想在Location表单中创建ParkingLocation (反之亦然),您将需要查看Rails的嵌套形式特性。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34205418

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档