如何通过关联编辑has_many

时间:2012-05-14 08:17:43

标签: ruby-on-rails-3 has-many-through

我几天以来一直在努力解决这个问题,最后我决定问一下,即使我认为它不应该那么难实现。

我正在使用rails 3.1,我希望能够以单一形式编辑has_many的连接表的几个记录:通过关联

我看了Ryan Bates' railscasts ,但这不是我正在寻找的,

然后我尝试实现看起来非常接近我需要的this solution,但它没有编辑连接表。

这是场景: 我有很多技能的玩家(用户的子类)。每个玩家的技能等级都以整数(1到10)存储在player_skill模型中。

我能够创建并显示玩家的技能,我可以设置值并将其存储在数据库中,但我无法从数据库中检索现有值并在下拉菜单中将其显示为选定值。这些是我的模特:

class Player < User

  has_many :player_skills, :dependent => :destroy
  has_many :skills, :through => :player_skills
  accepts_nested_attributes_for :skills

  attr_accessible :player_skills

end

class Skill < ActiveRecord::Base
  has_many :player_skills
  has_many :players, :through => :player_skills
end


# This stores the skill level as integer 1..10

class PlayerSkill < ActiveRecord::Base 
  belongs_to :player
  belongs_to :skill
end

我希望能够通过每种技能的下拉菜单以单一形式编辑给定玩家的所有技能等级。现在我可以设置并将它们保存到数据库中,但是当我重新加载编辑表单时,我无法检索这些值。

这是我用来创建编辑表单的代码。我知道我的错误是在select的用户中,我没有加载现有值,但我不知道该怎么做。

<h3><%= @user.first_name %> <%= @user.last_name %></h3>
<% @skills = Skill.all %>
<%= form_for @user, :url => updateplayerskills_path(@user) do |f| %>


  <div class="field">
  <table border="1">
    <tr>
      <td>Skill Name</td>
      <td>Level</td>

    </tr>
    <% @skills.each do |skill| %>
      <%= f.fields_for :player_skills do |builder|  %>
        <tr>
      <td><%=h skill.name %></td>
      <td>

        #Here how can I load and display the existing level's value??
        #Shall I maybe use a different select method?

        <%= f.select skill.id, 1..10 %>     
      </td> 
      </tr>
      <% end %>
    <% end %>
  </table>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

任何帮助/提示非常感谢! 谢谢!

1 个答案:

答案 0 :(得分:2)

我认为你需要为'player_skills'而不是'技能'声明 - accepts_nested_attributes_for。

所以,         class Player&lt;用户

        has_many :player_skills, :dependent => :destroy
        has_many :skills, :through => :player_skills
        accepts_nested_attributes_for :player_skills

此外,您当前的表单代码如下:

<% @skills.each do |skill| %>
  <%= f.fields_for :player_skills do |builder|  %>
    <tr>
        <td><%=h skill.name %></td>
        <td>
            <%= f.select skill.id, 1..10 %>     
        </td> 
    </tr>
  <% end %>
<% end %>

我认为它应该是这样的,而不是:

<%= f.fields_for :player_skills do |builder|  %>
    <tr>
        <td>
            <%= builder.label :skill_id, "Skill" %>
            <%= builder.select(:skill_id, options_for_select(Hash[(1..10).collect { |n| [n.to_s, n] }])) %>     
        </td> 
    </tr>
<% end %>

编辑:

如果要从常量 - 10生成选项列表,可以在application_helper.rb中定义常量

module ApplicationHelper
  MAX_SKILL_ID = 10
end

然后在你看来:

<%= f.fields_for :player_skills do |builder|  %>
    <tr>
        <td>
            <%= builder.label :skill_id, "Skill" %>
            <%= builder.select(:skill_id, options_for_select(Hash[(1..ApplicationHelper::MAX_SKILL_ID).collect { |n| [n.to_s, n] }]), player_skill.level) %>     
        </td> 
    </tr>
<% end %>