【问题标题】:What is the difference between using ":" and "@" in fields_for在 fields_for 中使用“:”和“@”有什么区别
【发布时间】:2012-04-05 02:40:31
【问题描述】:

我正在我的 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 错误。注意forms_for 行中的@players_to_teams.player

这确实有效:

<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 %>

注意fields_for 行中的:player 调用。

使用符号和使用实例有什么区别?我想在这种情况下我会想使用一个实例,但我猜不是?

编辑

型号:

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

【问题讨论】:

    标签: ruby-on-rails forms


    【解决方案1】:

    似乎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
    

    另外,查看the documentation for fields_for,第一个参数称为record_name,所以看起来Rails 期待的是关联的名称,而不是关联本身。但是如果不进一步研究代码,很难确切地知道该方法的作用,并且他们的一些示例确实确实将关联直接传递到fields_for


    好的,我能够克隆您的示例项目并重现错误。我想我明白发生了什么。

    调用accepts_nested_attributes_for 后,您现在在模型上拥有了一个名为player_attributes= 的实例方法。这是通常为has_one 关联定义的player= 方法的补充。 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=,而第二个示例将调用player_attributes=。在这两种情况下,传递给方法的参数都是散列(因为params 最终只是散列的散列)。

    这就是你得到AssociationTypeMismatch 的原因:你不能将哈希传递给player=,只能传递Player 对象。

    看来,将fields_foraccepts_nested_attributes_for 一起使用的唯一安全方法是传递关联的名称,而不是关联本身。

    所以回答你原来的问题,区别在于一个有效,另一个无效:-)

    【讨论】:

    • 我已将我的模型添加到我的问题中。我在文档中唯一能看到的是,当他们为第一个参数使用实例变量时,它们并未绑定在另一个 form_for 块内。
    • 在他们的第一个“通用示例”中,他们实际上确实使用了fields_for,并在form_for 中进行了显式关联。我还能够创建一个具有相似模型和相似表单的简单应用程序,并且它没有产生该错误。查看 Rails 源代码,似乎您应该收到 AssociationTypeMismatch 异常的唯一时间是当您将对象分配作为关联并且对象的类与类不匹配时协会的。你在任何地方都在做这样的事情吗?
    • “将对象分配为关联”是什么意思?我不认为我在做任何不正常的事情,但也许我是。我添加了控制器源以防万一。
    • the docs on AssociationTypeMismatch(这次得到了正确的链接:-)。该示例将Comment 对象分配给为Patch 对象定义的关联。你在哪里看到异常?生成表单时(在视图中)或提交表单时(在控制器中)?
    • 我刚刚尝试了一个示例应用程序并得到了同样的错误。也许你可以看看我链接的 GitHub 项目,看看我的不同之处在哪里?
    猜你喜欢
    • 1970-01-01
    • 2017-12-23
    • 2016-08-23
    • 2014-07-25
    • 2010-11-26
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多