【问题标题】:Rails form : AssociationTypeMismatch in form with selectRails 形式:AssociationTypeMismatch 与选择形式
【发布时间】:2018-03-04 17:23:09
【问题描述】:

我尝试以一种可以从已注册玩家列表中选择玩家的形式在比赛和 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

在 Match 模型中:

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

我提交表单时的结果是:

Player(#69852298534200) 预期,得到“1”,它是 String(#4817000) 的一个实例

{"utf8"=>"✓",
 "authenticity_token"=>".............",
 "match"=>{"playerone"=>"1", "playertwo"=>"3", "prolongations"=>"0"},
 "commit"=>"Enregistrer le match"}

我该如何解决?

【问题讨论】:

    标签: ruby-on-rails forms select


    【解决方案1】:

    最简单的解决方法是使用playerone_idplayertwo_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
    

    【讨论】:

    • 如果您想将一场比赛限制为两名玩家,请创建一个custom validation
    猜你喜欢
    • 2014-08-18
    • 1970-01-01
    • 2016-04-20
    • 2014-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-01
    相关资源
    最近更新 更多