无法在Rails中保存嵌套属性

时间:2010-12-14 00:03:25

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

Rails newb here。在我的应用程序中,我正在尝试创建一个游戏数据库,每个游戏都有多个MameControls作为嵌套属性。用于输入MameControls的字段显示在New视图中但不显示在Edit中,结果不显示在Show中,如果我validate_presence_of:mameControls它将不保存表单,说明“Mame控件不能为空”。在rails控制台中,Game.first(或最后一个或任何其他记录).mame_controls仅返回[]。所以据我所知,嵌套属性没有被保存,即使我很确定我已经设置了类似于Railscast#196中显示的内容。这是Game类:

class Game < ActiveRecord::Base
  has_many :mame_controls, :dependent => :destroy

  attr_accessible :name, :year, :company, :designer, :genre,
  :sb_info, :wiki_link, :arcade_history_link, :arcade_museum_link, 
  :caesar_link, :wildcard_link, :mame_controls

  accepts_nested_attributes_for :mame_controls, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true

  validates_presence_of :name, :year, :company, :genre, :sb_info, :mame_controls

end

mame_control.rb:

class MameControl < ActiveRecord::Base
  belongs_to :game

  attr_accessible :name, :game_action
end

输入或编辑MameControls的表单代码是这个。

_form.html.erb中的

  <% f.fields_for :mame_controls do |builder| %>
    <%= render "control_fields", :f => builder %>
<% end %>

_control_fields.html.erb:

<div class="field">
 <p>
     <%= f.label :name, "Mame Control Name" %><br />
  <%= f.text_field :name %><br />
  <%= f.label :game_action, "Game Action" %><br />
  <%= f.text_field :game_action %>
 </p>
</div>

在games_controller.rb中:

 def new
    @game = Game.new
    5.times do
       mame_control = @game.mame_controls.build
     end
  end

def create
    @game = Game.new(params[:game])
end

3 个答案:

答案 0 :(得分:1)

好吧,事实证明我在reject_if中使用accepts_nested_attributes_for时出现了一些问题。首先,我正在检查错误的变量名称(令人尴尬),并且我误解了该方法实际上在做什么,或者更确切地说没有做 - 如果先前填充的条目被拒绝为空(如在该lambda中),它就赢了“ t删除或清空数组中相应的索引值。它不会做任何事情。您必须将嵌套属性记录显式设置为_destroy以进行销毁。我从理论的角度阅读了accepts_nested_attributes_for,但我应该更好地理解它的选择。

答案 1 :(得分:0)

尝试将:mame_controls_attributes添加到attr_accessible,然后创建记录。然后,当您编辑记录时,编辑视图还应显示mame_controls的字段。

另外,为什么控件在show动作中可见? (show是为了显示数据,而不是编辑它)

答案 2 :(得分:0)

我遇到了类似的问题。我得到了正确显示的嵌套表单,但是当我提交表单时,它将父对象信息写入数据库,而不是子(嵌套)对象。

我的解决方案是将以下代码添加到我的游戏中(好像我正在使用你的例子)在games_controller.rb中创建方法

def create
  @game = Game.new(params[:game])
  if @game.save
    @game.mame_control = MameControl.new(params[:mame_control])
    ...

请注意我的父对象与孩子有一个has_one关系,而不是has_many。