【问题标题】:Rails routing for has_and_belongs_to_many relationshiphas_and_belongs_to_many 关系的 Rails 路由
【发布时间】:2015-10-27 09:50:05
【问题描述】:

我正在为一个有球员和球队的运动队开发 Rails 4 API,但我在 rails 路由和 has_many 关系方面遇到了一些困难。我的球员和球队之间的关系是这样的:

class Team < ActiveRecord::Base
  extend Searchable
  validates :title, presence: true
  has_and_belongs_to_many :players
end

class Player < ActiveRecord::Base
  extend Searchable
  validates :first_name, presence: true
  validates :last_name, presence: true
  has_and_belongs_to_many :teams
end

我希望能够将现有球员添加到球队,但我不确定如何更改我的 routes.rb 文件。目前,它看起来像:

Rails.application.routes.draw do
  devise_for :users
  namespace :api, defaults: { format: :json },
            constraints: { subdomain: 'api' }, path: '/'  do
    scope module: :v1 do
      resources :users, :only               => [:show, :create, :update, :destroy]
      resources :teams, :only               => [:show, :create, :update, :destroy, :index]
      resources :players, :only             => [:show, :create, :update, :destroy, :index]
      resources :sessions, :only            => [:create, :destroy]
    end
  end
end

允许对球员和球队模型进行 CRUD 操作。我在想,要将一名球员添加到现有球队,我的路线需要如下所示:

/teams/:team_id/add_player/

但我不确定如何在routes.rb 中声明该路由。所以,有几个问题:

  1. 从 REST-ful 的角度来看,这条路线对人们有意义吗?如果是这样,我将如何在routes.rb 中声明这条路线
  2. 应该是 PATCH 还是 POST 方法来将球员添加到球队?

感谢您提供的任何帮助,

肖恩

【问题讨论】:

  • 喜欢你如何格式化你的路线!

标签: ruby-on-rails ruby ruby-on-rails-4 has-and-belongs-to-many


【解决方案1】:

您需要使用nested resource

#config/routes.rb
resources :teams, only: [....] do
   resources :players, path: "", path_names: {new: "add_player", create: "add_player", destroy: "remove_player" }, only: [:create, :destroy] #-> /v1/teams/:team_id/add_player
end

这将路由到您的 players_controller,并传递 :team_id 参数:

#app/controllers/players_controller.rb
class PlayersController < ApplicationController
   def new
      @players = Player.all
   end

   def create
      if params[:team_id]
        @team = Team.find params[:team_id]
        @player = Player.find params[:id]
        @team.players << player
      else
        # normal "create" action
      end
   end

   def destroy
      if params[:team_id]
          @team = Team.find params[:id]
          @player = Player.find params[:id]
          @team.players.delete player
      end
   end
end

您可以将其与以下视图结合使用:

#app/views/players/new.html.erb
<%= form_tag team_players_path do %> #-> method should be "post"
   <%= collection_select :player, :id, @players, :id, :name %>
   <%= submit_tag %>
<% end %>

--

琐事:

使用HABTM,您可以获得&lt;&lt;collection.delete 方法——这两种方法都允许您非常简单地从集合中添加和删除对象。

-

从 REST-ful 的角度来看,这条路线对人们有意义吗?如果是这样,我将如何在routes.rb中声明这条路线@

是的。

将玩家添加到团队中应该是 PATCH 还是 POST 方法?

根据资源丰富的路由结构,我想说您可以通过POST 请求到create 操作来逃脱,但可以通过多种方式完成!


更新

这样做:

#config/routes.rb
resources :teams, only: [....] do
   match "players/:id", to: "players", via: [:put, :delete]
end

这将创建以下路线:

#put      url.com/teams/:team_id/players/:id
#destroy  url.com/teams/:team_id/players/:id

这将允许您在 teams 控制器中使用 players 方法:

#app/controllers/teams_controller.rb
class TeamsController < ApplicationController
   def players
      @team = Team.find params[:team_id]
      @player = Player.find params[:id]
      if request.put?
         @team.players << player
      elsif request.delete?
         @team.players.destroy player
      end
   end
end

【讨论】:

  • 感谢 Rich 的建议。我认为这感觉像是一种更新,而不是一种创造或毁灭。我用github.com/rgbycch/rgbycch-rest/commit/… 对它大加赞赏。有没有办法使用您的方法使用更新而不是创建和销毁来使其工作?
  • 我需要指定控制器以及操作,因为我收到了错误 Missing :action key on routes definition。所以我最终得到了match "players/:id", to: "teams#players", via: [:put, :delete]
【解决方案2】:

你可以这样声明这条路线:

resources :teams, only: [:show, :create, :update, :destroy, :index] do
  put 'add_player', on: :member
end

它会将路由映射到您的TeamsController 中的add_player 操作。

从 REST-ful 的角度来看,我建议您在 players#update 操作中执行此操作,因为您基本上是在更改玩家记录。

【讨论】:

  • 感谢 Yury。我使用github.com/rgbycch/rgbycch-rest/commit/… 对其进行了破解,但我的单元测试失败并出现stack level too deep 错误。 1) Api::V1::TeamsController PUT/PATCH #update 用户已登录,将玩家添加到团队失败/错误:put :add_player, { user_id: @user.id, id: @team.id, player_id: @ player.id } SystemStackError: stack level too deep # /Users/sean.oshea/.rvm/gems
  • 由于teamplayer中的序列化,您遇到了错误。有一个未解决的问题:github.com/rails-api/active_model_serializers/issues/211
  • 谢谢尤里。在解决了我的序列化程序之后,这对我很有效。希望他们能在下一版本的 rails 中解决这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-12
  • 1970-01-01
相关资源
最近更新 更多