【问题标题】:ActiveRecord not saving complete nested dataActiveRecord 不保存完整的嵌套数据
【发布时间】:2026-02-23 00:25:01
【问题描述】:

我有以下型号:

class Innovator < ActiveRecord::Base
  has_many :innovators_medios, :dependent => :destroy, :autosave => true
  has_many :medios, :through => :innovators_medios
  accepts_nested_attributes_for :innovators_medios, :allow_destroy => true, :reject_if => lambda { |a| a['medio_id'].eql? 0 || a['medio_id'].blank? }

  attr_accessor :list_medios

  def self.nuevo
    @new = self.new

    @new.list_medios = Medio.all

    @new.list_medios.count.times { @nuevo.innovators_medios.build }

    @new
  end
end

class InnovatorsMedio < ActiveRecord::Base
  belongs_to :innovator
  belongs_to :medio

  set_primary_key :medio_id
end

控制器:

class InnovadorsController < ApplicationController
  ...

  def new
    @innovator  = Innovator.nuevo
  end

  ...
end

对于新的创新者有以下看法:

<% form_for @innovator do |f| %>
  <%= f.error_messages %>

  ...  

  <section id="paso-1">
    <div class="page-header">
      <h1>Datos del postulante</h1>
    </div>
    <div class="row">      
        ...                 
        <%= render :partial => 'datos_personales', :locals => { :dato => f } %>   
        ...   
    </div>      
  </section>
<% end %>

以及对应的部分:

  ...
  <div class="clearfix">
    <%= dato.label :innovadors_medios_id, '¿Cómo se enteró del programa de estímulo a la innovación e investigación?' %>
    <div class="input">
      <ul class="inputs-list">
      <% i = 0 %>
      <% dato.fields_for :innovadors_medios do |im| %>
        <%= render :partial => 'medios/new', :locals => { :medio => im, :nombre => @innovator.list_medios[i].nombre, :id => @innovator.list_medios[i].id } %>
        <% i += 1 %>
      <% end %>
      </ul>
    </div>
    ...

<li id="medio-<%= id %>">
  <label>
    <%= medio.check_box :medio_id, {}, id, 0 %>
    <span><%= nombre %></span>
  </label>
</li>

一切都按原样呈现。但是,当我保存记录时,AR 不会将嵌套属性保存在相应的模型中。它只保存主 ID。即:

   innovators_medios
-------------------------
 innovator_id | medio_id
-------------------------
       23     |
       23     |
       23     |
       23     |
-------------------------

日志控制台显示WARNING: Can't mass-assign these protected attributes: medio_id

可能出了什么问题?

【问题讨论】:

  • 应用在 Ruby 1.8.7 和 Rails 2.3.5 上

标签: ruby-on-rails ruby activerecord nested-attributes


【解决方案1】:

我认为您的问题是您使用了 InnovatorsMedio 类的受保护属性。 Rails 定义了某种可访问性来保护字段不被大量分配。

尝试将attr_accessible :medio_id 放在您的 InnovatorsMedio 课程中,并判断这是否能解决您的问题。

【讨论】:

  • 我已经做到了。但它阻止了其他属性。 An 甚至不保存该属性。 ://
【解决方案2】:

试试attr_accessible :medio_id, :innovator_id

来自 attr_accessible 文档:

指定可以通过以下方式设置的模型属性白名单 批量分配。

与 attr_protected 一样,如果没有角色,属性的角色是可选的 提供然后 :default 被使用。角色可以通过使用 : 作为选项。

这与 attr_protected 宏相反:批量赋值将 仅在此列表中设置属性,以分配给其余属性 您可以使用直接编写器方法。这是为了保护敏感 属性被恶意用户篡改覆盖 URL 或表单。如果你宁愿从一个全开放的默认开始,并且 根据需要限制属性,查看 attr_protected。

【讨论】:

    【解决方案3】:

    :through 文档建议忽略直通表的 :primary_key 选项:

    http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many

    这个较早的帖子(还有其他帖子)指出了在直通表中设置主键的可能性,直到 2.3.8(或更高版本)才起作用:

    http://railsforum.com/viewtopic.php?id=36186

    虽然您的错误消息似乎指向其他内容。

    【讨论】: