6

Rails アプリに埋め込みフォームを設定しています。

これは動作しません

<h1>PlayersToTeams#edit</h1>
<%= form_for @players_to_teams do |field| %>
  <%= field.fields_for @players_to_teams.player do |f| %>
    <%= f.label :IsActive %>
    <%= f.text_field :IsActive %>
  <% end %>
  <%= field.label :BT %>
  <%= field.text_field :BT %>
  <br/>
  <%= field.submit "Save", class: 'btn btn-primary' %>
<% end %> 

エラーが発生しますActiveRecord::AssociationTypeMismatch。に注目して@players_to_teams.playerくださいforms_for

これは機能します:

<h1>PlayersToTeams#edit</h1>
<%= form_for @players_to_teams do |field| %>
    <%= field.fields_for :player do |f| %>
        <%= f.label :IsActive %>
        <%= f.text_field :IsActive %>
    <% end %>
    <%= field.label :BT %>
    <%= field.text_field :BT %>
    <br/>
    <%= field.submit "Save", class: 'btn btn-primary' %>
<% end %>

ライン内の:player呼び出しに注意してください。fields_for

シンボルの使用とインスタンスの使用の違いは何ですか? この場合、インスタンスを使用したいと思いますが、そうではないと思いますか?

編集

モデル:

class Player < ActiveRecord::Base
  has_many :players_to_teams
  has_many :teams, through: :players_to_teams
end

class PlayersToTeam < ActiveRecord::Base
  belongs_to :player
  belongs_to :team

  accepts_nested_attributes_for :player
end

コントローラ:

class PlayersToTeamsController < ApplicationController
  def edit
    @players_to_teams=PlayersToTeam.find(params[:id])
  end

  def update
    @players_to_teams=PlayersToTeam.find(params[:id])
    respond_to do |format|
      if @players_to_teams.update_attributes(params[:players_to_team])
        format.html { redirect_to @players_to_teams, notice: 'Player_to_Team was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @players_to_teams.errors, status: :unprocessable_entity }
      end
    end
  end
end

サンプルプロジェクト

Github: https://github.com/workmaster2n/embedded-form-errors

4

1 に答える 1

5

インスタンス変数の関連付けがfields_for何であるかを理解できないようです。アソシエーションの名前 (つまり ) を明示的に指定することで、これをバイパスします。関連付けを双方向で定義していますか? すなわち:player@players_to_teams:player

class PlayersToTeam < ActiveRecord::Base
  has_one :player
end

class Player < ActiveRecord::Base
  belongs_to :players_to_team
end

さらに、のドキュメントをfields_for見ると、最初のパラメーターは と呼ばれrecord_nameているため、Rails は関連付け自体ではなく、関連付けの名前を想定しているようです。しかし、コードを詳しく調べずにそのメソッドが何をするのかを正確に伝えるのは難しく、実際にいくつかの例では関連付けを に直接渡していfields_forます。


サンプル プロジェクトのクローンを作成し、エラーを再現できました。何が起こっているのか理解していると思います。

を呼び出した後、accepts_nested_attributes_forモデルに という名前のインスタンス メソッドができましplayer_attributes=た。これはplayer=、関連付けに対して通常定義されるメソッドに追加されhas_oneます。メソッドは属性のplayer_attributes=ハッシュを受け入れますが、player=メソッドは実際のPlayerオブジェクトのみを受け入れます。

を呼び出したときに生成されるテキスト入力の例を次に示しますfields_for @players_to_teams.player

<input name="players_to_team[player][name]" ... />

を呼び出すときの同じ入力は次のfields_for :playerとおりです。

<input name="players_to_team[player_attributes][name]" ... />

コントローラーを呼び出すupdate_attributesと、最初の例では が呼び出されplayer=、2 番目の例では が呼び出されますplayer_attributes=。どちらの場合も、メソッドに渡される引数はハッシュです (params最終的には単なるハッシュのハッシュであるため)。

これが、 を取得していた理由ですAssociationTypeMismatch: にハッシュを渡すことはできません。オブジェクトplayer=のみです。Player

fields_forwithを使用する唯一の安全な方法accepts_nested_attributes_forは、関連付けそのものではなく、関連付けの名前を渡すことです。

したがって、元の質問に答えるには、違いは、一方が機能し、もう一方が機能しないことです:-)

于 2012-04-05T02:56:47.617 に答える