我在 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 不会注意。