has_and_belongs_to_many关系

时间:2015-10-27 09:50:05

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

我正在为一个运动队工作一个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. 中声明此路线
  3. 将球员添加到球队应该是PATCH还是POST方法?
  4. 感谢您提供的任何帮助,

    肖恩

2 个答案:

答案 0 :(得分:2)

您需要使用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,您可以获得<<&amp; 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

这样您就可以在players控制器中使用teams方法:

#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

答案 1 :(得分:1)

您可以这样声明此路线:

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

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

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