我尝试在一个匹配和2个玩家之间建立连接,我们可以从注册的玩家列表中选择玩家:
<%= f.label :"Joueur 1" %>
<%= f.select :playerone, @players.collect {|a| [a.name, a.id]} , class: 'form-control' %>
<%= f.label :"Joueur 2" %>
<%= f.select :playertwo, @players.collect {|b| [b.name, b.id]} , class: 'form-control' %>
<%= f.label :Prolongations %>
<%= f.check_box :prolongations %><br />
<%= f.submit yield(:button_text), class: "btn btn-primary" %>
表的架构:使用连接表匹配玩家
create_table "matches", force: :cascade do |t|
t.boolean "prolongations"
end
create_table "matches_players", id: false, force: :cascade do |t|
t.integer "match_id", null: false
t.integer "player_id", null: false
t.index ["match_id", "player_id"], name: "index_matches_players_on_match_id_and_player_id"
t.index ["player_id", "match_id"], name: "index_matches_players_on_player_id_and_match_id"
end
create_table "players", force: :cascade do |t|
t.string "name"
t.integer "points"
end
在matches.controller中:
class MatchesController < ApplicationController
attr_accessor :player_id, :playerone, :playertwo
def new
@match= Match.new
@players = Player.all
end
def create
@match = Match.new(match_params)
@players = Player.all
if @match.save
flash[:success] = "Votre match a bien été enregistré !"
redirect_to @match
else
render 'new'
p "Une erreur existe, veuillez recommencer."
end
end
def show
@match = Match.find(params[:id])
end
private
def match_params
params.require(:match).permit(:prolongations, :playerone, :playertwo)
end
end
在比赛模型中:
class Match < ApplicationRecord
has_many :teams , class_name: "Team"
belongs_to :playerone, class_name: "Player" ,foreign_key: "player_id"
belongs_to :playertwo, class_name: "Player" ,foreign_key: "player_id"
end
我提交表单时的结果是:
播放器(#69852298534200)预期,得到“1”这是一个字符串的实例(#4817000)
{"utf8"=>"✓",
"authenticity_token"=>".............",
"match"=>{"playerone"=>"1", "playertwo"=>"3", "prolongations"=>"0"},
"commit"=>"Enregistrer le match"}
我该如何解决?
答案 0 :(得分:0)
最简单的解决方法是使用playerone_id
和playertwo_id
作为参数键(更改输入的名称)。如果使用playerone
,则setter期望参数是Player的实例 - 而不是包含id的字符串。
这将解决眼前的问题,但有更好的方法来解决它。
首先设置real many to many association:
class Match < ApplicationRecord
has_many :player_matches, dependent: :destroy
has_many :players, through: :player_matches
end
class Player < ApplicationRecord
has_many :player_matches, dependent: :destroy
has_many :matches, through: :player_matches
end
class PlayerMatches < ApplicationRecord
belongs_to :player
belongs_to :match
end
这可以让你避免一个非常棘手的问题,当你设置两个属于同一个表的关联时,关联的记录可以在任一列中:
Match.find_by("(playerone_id = :a OR playertwo_id = :a) AND (playerone_id = :b OR playertwo_id = :b)", a: a, b: b)
是的,这就是你如何查询玩家之间的匹配。加入可能会更加混乱。
通过该设置,您可以通过以下方式将玩家分配给匹配:
@match.player_ids = [1,2]
您正可以使用collection helpers:
执行此操作<%= form_for(@match) do |f| %>
<div class="field">
<%= f.label :player_ids, "Select the players" %>
<%= f.collection_select :player_ids, Player.all, :id, :name, multiple: true %>
</div>
<% end %>
您在控制器端所要做的就是白名单player_ids
:
class MatchesController < ApplicationController
# ...
def create
@match = Match.new(match_params)
# ...
end
def update
if @match.update(match_params)
# ...
else
# ...
end
end
# ...
private
def match_params
params.require(:match).permit(:foo, :bar, player_ids: [])
end
end