我在Rails中有一个三级多嵌套表单。设置如下:项目有许多里程碑,里程碑有很多笔记。目标是使用JavaScript在页面中编辑所有内容,我们可以在页面中的项目中添加多个新的里程碑,并将新的Notes添加到新的和现有的里程碑。
一切都按预期工作,除了当我向现有的里程碑添加新笔记时(新的里程碑在向他们添加笔记时工作正常),新笔记将不会保存,除非我编辑任何实际上属于里程碑的字段标记“脏”/编辑的形式。
有没有办法标记里程碑,以便添加的新Notes会保存?
编辑:抱歉,很难粘贴所有代码,因为有太多的部分,但是这里有:
模型
class Project < ActiveRecord::Base
has_many :notes, :dependent => :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 < ActiveRecord::Base
belongs_to :project
has_many :notes, :dependent => :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不会引起注意。
答案 0 :(得分:2)
答案 1 :(得分:0)
我认为你的模特是错的。注释与项目没有直接关系。他们是通过里程碑。
试试这些
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 %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<% f.fields_for :notes do |n| %>
<p>
<div>
<%= n.label :content, 'Project Notes:' %>
<%= n.text_area :content, :rows => 3 %>
</div>
</p>
<% end %>
<% f.fields_for :milestones do |m| %>
<p>
<div>
<%= m.label :name, 'Milestone:' %>
<%= m.text_field :name %>
</div>
</p>
<% m.fields_for :notes do |n| %>
<p>
<div>
<%= n.label :content, 'Milestone Notes:' %>
<%= n.text_area :content, :rows => 3 %>
</div>
</p>
<% end %>
<% end %>
<p>
<%= f.submit 'Update' %>
</p>
<% end %>