我是Rails的新手。我有三个牌桌球员,名单和阵容。我有模型条目来创建玩家所属的关系 - 名单和阵容,名单上有很多玩家,阵容有很多玩家。
我遇到的问题是当我创建名单时,我有一个roster_name属性,我可以添加一个单独的玩家。我想在同一个阵容中添加更多玩家,但我正在努力解决如何将新玩家添加到名单中的问题。默认的新视图调用_form partial,它希望我创建一个全新的名单,这将允许我再次添加一个用户。
将新玩家添加到现有名单的轨道方式是什么?请帮我理解我需要的组件。我是否需要一个可以调用的新部分来添加新玩家?我是否必须创建新方法或控制器?我假设是我需要一种方法来引用现有的名单,同时能够添加新的player_id。任何帮助都会很棒。
这是我的模型/控制器和视图
My model roster.rb
class Roster < ActiveRecord::Base
has_many :players
accepts_nested_attributes_for :players, :allow_destroy => true
end
My model player.rb
class Player < ActiveRecord::Base
belongs_to :roster
end
My controller rosters_controller.rb
def new
@roster = Roster.new
@players = Player.all
End
My roster view
<%= form_for(@roster) do |f| %>
<% if @roster.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@roster.errors.count, "error") %> prohibited this roster from being saved:</h2>
<ul>
<% @roster.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :player_id %><br />
<%= f.text_field :player_id %>
<%= collection_select("roster", "player_id", @players, "id", "gname") %>
</div>
<div class="field">
<%= f.label :player_id %><br />
<%= f.text_field :player_id %>
<%= collection_select("roster", "player_id", @players, "id", "gname") %>
</div>
<div class="actions">
<%= f.submit %>
</div>
答案 0 :(得分:0)
由于它是多对多关联,has_many :through
关联通常用于与另一个模型建立多对多连接。该关联表明通过继续第三模型,声明模型可以与另一模型的零个或多个实例匹配。现在关联声明可能如下所示:
class Roster < ActiveRecord::Base
has_many :roster_players
has_many :players, :through => :roster_players
end
class RosterPlayer < ActiveRecord::Base
belongs_to :roster
belongs_to :player
end
class Player < ActiveRecord::Base
has_many :roster_players
has_many :roster, :through => :roster_players
end
第1步: 生成关联模型。
$> rails g model roster_player roster:references player:references
$> rake db:migrate
第2步: 您需要的是接受嵌套属性的方法。完成此rails cast并阅读nested_attributes。 rails cast的代码形式已被Ryan Bates提取为宝石,非常有用。
更新你的gemfile以要求这个宝石
gem 'nested_form'
$> bundle install
接下来运行生成器以创建JavaScript文件。这将自动检测您是否使用jQuery或Prototype。
rails g nested_form:install
运行生成器将添加一个文件nested_form.js
,该文件应该包含在jQuery或Prototype框架之后。
<%= javascript_include_tag :defaults, "nested_form" %>
让我们将嵌套属性提取到名为_roster_player_fields.html.erb
<div class="field">
<%= f.label :player_id, "Player" %>
<%= f.select :player_id, Player.all.collect { |p| [ p.name, p.id ] }, { :include_blank => true } %>
</div>
我们在这里要做的是为表单中的每个名册palyers添加字段。我们可以使用fields_for方法来管理表单中的关联字段,将其传递给关联模型的名称,然后遍历所有关联的播放器记录,并为每个记录创建表单构建器。构建器将为每个玩家渲染部分内容。
<%= form_for(@roster) do |f| %>
<% if @roster.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@roster.errors.count, "error") %> prohibited this roster from being saved:</h2>
<ul>
<% @roster.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<% f.fields_for :roster_players do |builder| %>
<%= render 'roster_player_fields', :f => builder %>
<% end %>
<%= link_to_add_fields "[+] Add Player", f, :roster_players %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
当渲染此表单时,它将看起来像以前一样。这是因为新名单中没有任何与之相关的玩家,因此不会显示任何玩家字段。最终我们希望在表单上有一个“添加播放器”链接,但我们可以在RosterController的新操作中创建一个roster_player,并显示其字段。
def new
@roster = Roster.new
@roster.roster_players.build
End
默认情况下,嵌套属性更新已关闭,您可以使用#accepts_nested_attributes_for
类方法启用它。启用嵌套属性时,将在模型上定义属性编写器。这应该有效并希望它有所帮助。