将多级嵌套表单标记为“脏”表单在 Rails 中
我在 Rails 中有一个三级多重嵌套表单。设置是这样的:项目有很多里程碑,里程碑有很多注释。目标是使用 JavaScript 使页面内的所有内容都可编辑,我们可以在页面内向项目添加多个新的里程碑,并向新的和现有的里程碑添加新的注释。
一切都按预期工作,除了当我向现有里程碑添加新注释时(向其中添加注释时新里程碑工作正常),新注释将不会保存,除非我编辑任何字段实际上属于里程碑来标记表单“脏”/已编辑。
有没有办法标记里程碑,以便保存已添加的新注释?
编辑:抱歉,很难粘贴所有代码,因为有太多部分,但这里是:
模型
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
我正在使用 Ryan Bates 的组合助手/JS 的基于 jQuery 的、不显眼的版本代码来完成这项工作。
应用程序助手
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 不会注意到。
I have a three-level multi-nested form in Rails. The setup is like this: Projects have many Milestones, and Milestones have many Notes. The goal is to have everything editable within the page with JavaScript, where we can add multiple new Milestones to a Project within the page, and add new Notes to new and existing Milestones.
Everything works as expected, except that when I add new notes to an existing Milestone (new Milestones work fine when adding notes to them), the new notes won't save unless I edit any of the fields that actually belong to the Milestone to mark the form "dirty"/edited.
Is there a way to flag the Milestone so that the new Notes that have been added will save?
Edit: sorry, it's hard to paste in all of the code because there's so many parts, but here goes:
Models
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
I'm using an jQuery-based, unobtrusive version of Ryan Bates' combo helper/JS code to get this done.
Application Helper
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
I render the form for the association in a hidden div, and then use the following JavaScript to find it and add it as needed.
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;
}
I'm guessing the only other relevant piece of code that I can think of would be the create method in the NotesController:
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
The @owner ivar is created in the following before filter:
def load_milestone
@milestone = @project.milestones.find(params[:milestone_id]) if params[:milestone_id]
end
def determine_owner
@owner = load_milestone || @project
end
Thing is, all this seems to work fine, except when I'm adding new notes to existing milestones. The milestone has to be "touched" in order for new notes to save, or else Rails won't pay attention.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是错误#4242< /a> 在 Rails 2.3.5 中,它已在 Rails 2.3.8 中修复 。
This is bug #4242 in Rails 2.3.5 and it has been fixed in Rails 2.3.8.
我认为你的模型是错误的。这些注释与项目没有直接关系。他们正在经历里程碑。
尝试这些
更新:这是基于新信息对我有用的代码:
i think your models are wrong. the notes have no direct relationship to project. they are through milestones.
try these
Update: here is the code that worked for me based on the new info: