【问题标题】:Use accepts_nested_attributes_for to create new records or update existing使用 accept_nested_attributes_for 创建新记录或更新现有记录
【发布时间】:2010-09-15 01:12:29
【问题描述】:

阅读重大更新以获取最新信息。

大家好,

我在一个涉及三个表的 Rails 应用程序中有一个多对多关系:一个用户表、一个兴趣表和一个连接 user_interests 表,该表也有一个评分值,因此用户可以对他们的每个表进行评分兴趣范围为 1-10。

我基本上是在寻找一种方法,让新用户在注册时创建他们的评分,并在未来的日期同时编辑他们的任何个人资料信息。

我尝试关注这个问题Rails nested form with has_many :through, how to edit attributes of join model?,但我遇到的问题是尝试将选择列表合并到组合中并为用户评分多个兴趣。

型号代码:

user.rb
has_many :user_interests, :dependent => :destroy
has_many :interests, :through => :user_interests, :foreign_key => :user_id  
accepts_nested_attributes_for :user_interests

interest.rb
has_many :user_interests, :dependent => :destroy
has_many :users, :through => :user_interests, :foreign_key => :interest_id, :dependent => :destroy

user_interest.rb
belongs_to :user
belongs_to :interest

查看代码:

app/views/user/_form.html.erb
<%= form_for(@user) do |form| %>
  ... user fields
  <%= form.fields_for :user_interests do |ui_form| %>
    ... loop through ALL interests
    <% Interest.all.each do |interest| %>
      <%= ui_form.select :rating, options_for_select(1..10) %>
      <%= ui_form.hidden_field :interest_id, :value => interest.id %>
    <% end %>
  <% end %>
<% end %>

我还在控制器 @user.interests.build.build_interest 的新/编辑操作中包含以下内容

我遇到的问题是,当我想要多个时,params 哈希中只传递了一个利率等级。我也得到了 rails 抛出的异常

Interest(#2172840620) expected, got Array(#2148226700)

我遗漏了哪些小细节或弄错了导致问题的原因?

编辑:

我找到了一种强制它工作的方法,但它需要在 chrome 开发人员工具中手动编辑 HTML,我的表单元素的 :name 属性正在生成为 user[user_interests_attributes][rating] 但如果我将其更改为 user[user_interests_attributes][][rating] 它会当我更新记录时工作。但是,我无法手动指定绑定到表单对象的表单元素的 :name。那么,我能做些什么来证明正在通过多个兴趣评级,而不是 Rails 认为的一个?

重大更新:

我得到了一个半功能版本,有一些细微的变化:

查看代码:

<% form.fields_for :user_interests do |ui_form| %>
<p>
    <%= ui_form.select :rating, options_for_select(1..5), :selected => :rating %>
    <%= ui_form.label :interest_title %>
    <%= ui_form.hidden_field :interest_id %>
</p>
<% end %>

控制器代码:

def new
  @user = User.new
  Interest.all.each { |int| @user.user_interests.build({ :interest_id => int.id }) }
end

def edit
  @user = @current_user
  Interest.unrated_by_user_id(@user.id).each { |int| @user.user_interests.build({ :interest_id => int.id }) }
end

现在,如果不存在评级,我可以编辑和更新或创建我的 user_interests,但是当我尝试创建新用户时,我收到一个错误,即用户为空。此外,我无法访问表单中的任何兴趣属性来显示用户实际评分的兴趣。任何人都可以帮助解决这些警告吗?

【问题讨论】:

    标签: ruby-on-rails nested-forms


    【解决方案1】:

    您只需要@user.interests.build,因为它是一个 has_many 关系。 build_interest 用于当存在 has_one/belongs_to 关系时。

    使用fields_for :user_interests 时,您是在告诉用户模型,当创建/更新用户时,一个或多个 user_interest 对象的实例将在参数散列中。该表单不会创建或更新任何 user_interests,但它会发送回一个 user_interest_attributes 哈希数组,这些哈希代表表单引用的用户的 user_interests。这是一个 user_interests 评分值数组,当您在表单中引用它们时不存在 user_interests,这就是您收到错误的原因。

    由于您将范围传递给select 表单助手,您实际上并没有为表单提供任何兴趣以供选择。该选择将为 user_interests 表中的 rating 列设置一个值,其值介于 1 和 10 之间。即使 user_interests 表具有 rating 列,也不存在用于设置 rating 的 user_interest。

    在选择标签的选项哈希中传递:multiple =&gt; true 将创建一个多选列表,但我认为这不是你想要的。我认为您希望在用户可以对其进行兴趣评级的页面上有很多项目。

    如果您确实希望用户能够选择许多兴趣,这是如何在 has_many :through 关系上使用 fields_for 和 accept_nested_attributes_for:

    <%= form_for(@user) do |f| %>
      <% f.fields_for :interest_ids  do |interest| %>
        <ul>
          <% Interest.all.each do |choice,i| %>
          <li class="selection">
            <%= interest.check_box [], { :checked => f.object.user_interest_ids.include?(choice.id) }, choice.id, ''  %>
            <%= interest.label [], choice.name %>
          </li>
        <% end %>
        </ul>
      <% end %>
    <% end %>
    

    【讨论】:

    • 我现在正在处理这个问题,看起来我在上面的代码示例中遗漏了我视图中所有兴趣的循环,我将对其进行修改以反映我最初可能会摆脱的东西更多的光
    • 是的,我不想为每个兴趣设置复选标记,而是为每个兴趣设置一个带有评分值的下拉列表
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-25
    • 2023-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-25
    • 2021-03-30
    相关资源
    最近更新 更多