ruby-on-rails – Rails – 如何在不使用accepts_nested_attribu
我的问题是我遇到了accepts_nested_attributes_for的限制,所以我需要弄清楚如何自己复制该功能以获得更大的灵活性. (请参阅下文,了解究竟是什么让我失望.)所以我的问题是:如果我想模仿并增加accepts_nested_attributes_for,我的表单,控制器和模型应该是什么样的?真正的诀窍是我需要能够使用现有的关联/属性更新现有的AND新模型.
我正在构建一个使用嵌套表单的应用程序.我最初使用这个RailsCast作为蓝图(利用accepts_nested_attributes_for):Railscast 196: Nested Model Form. 我的应用程序是带有作业(任务)的清单,我让用户更新清单(名称,描述)并在单个表单中添加/删除关联的作业.这很好用,但是当我将其合并到我的应用程序的另一个方面时,我遇到了问题:历史记录通过版本控制. 我的应用程序的一个重要部分是我需要记录我的模型和关联的历史信息.我最终推出了自己的版本控制(here是我的问题,我描述了我的决策过程/注意事项),其中很大一部分是我需要创建旧版本的新版本的工作流程,对新版本进行更新,归档旧版本.这对于用户是不可见的,用户将该体验视为仅通过UI更新模型. 代码 – 模型 #checklist.rb class Checklist < ActiveRecord::Base has_many :jobs,:through => :checklists_jobs accepts_nested_attributes_for :jobs,:reject_if => lambda { |a| a[:name].blank? },:allow_destroy => true end #job.rb class Job < ActiveRecord::Base has_many :checklists,:through => :checklists_jobs end 代码 – 当前表单(注意:@jobs在检查清单控制器编辑操作中被定义为此清单的未归档作业;因此是@checklist) <%= simple_form_for @checklist,:html => { :class => 'form-inline' } do |f| %> <fieldset> <legend><%= controller.action_name.capitalize %> Checklist</legend><br> <%= f.input :name,:input_html => { :rows => 1 },:placeholder => 'Name the Checklist...',:class => 'autoresizer' %> <%= f.input :description,:input_html => { :rows => 3 },:placeholder => 'Optional description...',:class => 'autoresizer' %> <legend>Jobs on this Checklist - [Name] [Description]</legend> <%= f.fields_for :jobs,@jobs,:html => { :class => 'form-inline' } do |j| %> <%= render "job_fields_disabled",:j => j %> <% end %> </br> <p><%= link_to_add_fields "+",f,:jobs %></p> <div class="form-actions"> <%= f.submit nil,:class => 'btn btn-primary' %> <%= link_to 'Cancel',checklists_path,:class => 'btn' %> </div> </fieldset> <% end %> 代码 – 来自checklists_controller.rb的代码段#更新 def update @oldChecklist = Checklist.find(params[:id]) # Do some checks to determine if we need to do the new copy/archive stuff @newChecklist = @oldChecklist.dup @newChecklist.parent_id = (@oldChecklist.parent_id == 0) ? @oldChecklist.id : @oldChecklist.parent_id @newChecklist.predecessor_id = @oldChecklist.id @newChecklist.version = (@oldChecklist.version + 1) @newChecklist.save # Now I've got a new checklist that looks like the old one (with some updated versioning info). # For the jobs associated with the old checklist,do some similar archiving and creating new versions IN THE JOIN TABLE @oldChecklist.checklists_jobs.archived_state(:false).each do |u| x = u.dup x.checklist_id = @newChecklist.id x.save u.archive u.save end # Now the new checklist's join table entries look like the old checklist's entries did # BEFORE the form was submitted; but I want to update the NEW Checklist so it reflects # the updates made in the form that was submitted. # Part of the params[:checklist] has is "jobs_attributes",which is handled by # accepts_nested_attributes_for. The problem is I can't really manipulate that hash very # well,and I can't do a direct update with those attributes on my NEW model (as I'm # trying in the next line) due to a built-in limitation. @newChecklist.update_attributes(params[:checklist]) 而这就是我遇到accepts_nested_attributes_for限制的地方(它很好地记录了here.我得到了“找不到具有ID = X的模型2的模型1,具有ID = Y”的异常,这基本上是设计的. 那么,我如何创建多个嵌套模型并在父模型的表单上添加/删除它们,类似于accepts_nested_attributes_for,但我自己呢? 我见过的选项 – 这些是最好的选择之一吗?真正的诀窍是我需要能够使用现有的关联/属性更新现有的AND新模型.我无法链接它们,所以我只是命名它们. Redtape(在github上) 谢谢你的帮助! 解决方法
您可能想要删除复杂的accepts_nested内容并创建自定义类或模块以包含所需的所有步骤.
这篇文章中有一些有用的东西 http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/ 特别是第3点 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |