在Rails中将多级嵌套表单标记为“脏”

我在Rails中有一个三级多嵌套表单。 设置如下:项目有许多里程碑,里程碑有很多笔记。 目标是使用JavaScript在页面中编辑所有内容,我们可以在页面中向项目添加多个新里程碑,并将新Notes添加到新的和现有的里程碑。

一切都按预期工作,除了当我向现有的里程碑添加新笔记(新的里程碑在向他们添加笔记时工作正常)时,新笔记将不会保存,除非我编辑任何实际属于里程碑的字段以标记forms“脏”/编辑。

有没有办法标记里程碑,以便添加的新Notes将保存?

编辑:对不起,很难粘贴所有代码,因为有很多部分,但是这里有:

楷模

class Project  :destroy has_many :milestones, :dependent => :destroy accepts_nested_attributes_for :milestones, :allow_destroy => true accepts_nested_attributes_for :notes, :allow_destroy => true, :reject_if => proc { |attributes| attributes['content'].blank? } end class Milestone  :destroy accepts_nested_attributes_for :notes, :allow_destroy => true, :allow_destroy => true, :reject_if => proc { |attributes| attributes['content'].blank? } end class Note < ActiveRecord::Base belongs_to :milestone belongs_to :project scope :newest, lambda { |*args| order('created_at DESC').limit(*args.first || 3) } end 

我正在使用基于jQuery的,不引人注目的Ryan Bates的组合助手/ JS代码来完成这项工作。

应用助手

 def add_fields_for_association(f, association, partial) new_object = f.object.class.reflect_on_association(association).klass.new fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder| render(partial, :f => builder) end end 

我在隐藏的div中呈现关联的表单,然后使用以下JavaScript找到它并根据需要添加它。

JavaScript的

 function addFields(link, association, content, func) { var newID = new Date().getTime(); var regexp = new RegExp("new_" + association, "g"); var form = content.replace(regexp, newID); var link = $(link).parent().next().before(form).prev(); if (func) { func.call(); } return link; } 

我猜测我能想到的唯一其他相关代码片段是NotesController中的create方法:

 def create respond_with(@note = @owner.notes.create(params[:note])) do |format| format.js { render :json => @owner.notes.newest(3).all.to_json } format.html { redirect_to((@milestone ? [@project, @milestone, @note] : [@project, @note]), :notice => 'Note was successfully created.') } end end 

@owner ivar在过滤之前创建如下:

 def load_milestone @milestone = @project.milestones.find(params[:milestone_id]) if params[:milestone_id] end def determine_owner @owner = load_milestone || @project end 

事实上,除非我在现有的里程碑中添加新笔记,否则这一切似乎都能正常工作。 必须“触摸”里程碑才能保存新笔记,否则Rails不会注意。

这是Rails 2.3.5中的#4242错误 ,它已在Rails 2.3.8中修复 。

我觉得你的模特错了。 这些笔记与项目没有直接关系。 他们是通过里程碑。

尝试这些

 class Project < ActiveRecord::Base has_many :milestones, :dependent => :destroy has_many :notes, :through => :milestones accepts_nested_attr ibutes_for :milestones, :allow_destroy => true end class Milestone < ActiveRecord::Base belongs_to :project has_many :notes, :dependent => :destroy accepts_nested_attributes_for :notes, :allow_destroy => true, :reject_if => proc { |attributes| attributes['content'].blank? } end class Note < ActiveRecord::Base belongs_to :milestone end 

更新:这是根据新信息为我工作的代码:

 ## project controller # PUT /projects/1 def update @project = Project.find(params[:id]) if @project.update_attributes(params[:project]) redirect_to(@project) else render :action => "edit" end end # GET /projects/1/edit def edit @project = Project.find(params[:id]) @project.milestones.build for m in @project.milestones m.notes.build end @project.notes.build end ## edit.html.erb <% form_for(@project) do |f| %> <%= f.error_messages %> 

<%= f.label :name %>
<%= f.text_field :name %>

<% f.fields_for :notes do |n| %>

<%= n.label :content, 'Project Notes:' %> <%= n.text_area :content, :rows => 3 %>

<% end %> <% f.fields_for :milestones do |m| %>

<%= m.label :name, 'Milestone:' %> <%= m.text_field :name %>

<% m.fields_for :notes do |n| %>

<%= n.label :content, 'Milestone Notes:' %> <%= n.text_area :content, :rows => 3 %>

<% end %> <% end %>

<%= f.submit 'Update' %>

<% end %>