ruby-on-rails – 在rails app / scaffold中无限制嵌套添加/编辑
概述/型号
比方说,你有一个相当大的系统,有非常通用的模型(我们将在这个例子中使用三个) >地点(通用地址字段,类型,第1行,第2行,城镇城市等) 示例(rails_admin screenshot) 我发现在制作这样的系统时,我总是遇到同样的问题.我点击了公司的添加按钮(例如我现在已经加载了表格部分等),我通过添加公司的一部分,发现我需要的位置不在系统中.我想快速打开一个模态窗口,添加位置,然后通过jquery或其他东西更新选择.太棒了,没什么太难的,而且已经在像rails_admin这样的系统中完成了(见下面的截图): http://www.server1-breakfrom.com/nestedaddexample.jpg 当处理一个级别的嵌套时,这一切都很好,并且一般来说,当处理这个问题时,所有这些都很好(因为你可以在这个时候编写能力).但是,我正在建立一个系统,这个系统本身几乎需要一个框架,因为我需要超过50%的模型.我需要能够在模型/控制器中动态添加各种??选项,并让表单动态生成相关按钮. 其他问题 >模态内部/之上的模态 – 添加联系人时,单击添加他们的公司,在这些新公司添加表单中然后您想要添加一个位置:繁荣,模态在模态之上. 扩大问题 所以,除了问题:我是否过于复杂化并且有一个容易解决我的问题(我必须强调3个模型纯粹是例子,我有很多模型需要引用公司,例如,它不仅仅是一个联系人,所以’只需按需要编程’,将无法正常工作!). 或者,我应该拉开rails_admin并拉出我需要的位吗? (同样,他们还没有解决多重嵌套问题,所以我觉得从头开始可能会更好?). 解决方法
我遇到了类似的情况.我的解决方案可能在您的方案中存在性能问题,它不适合我,但它是一个低并发使用系统,只有300个用户.
我做的是使用一个MEGA AJAX视图/表格!并根据需要使用JavaScript显示/隐藏.此技术要求您不要使用表单标记助手(即text_field_tag而不是f.text_field),您必须控制元素名称. 因此,首先要创建一个包含您最终需要的所有表单的视图.您必须区分它们,因此将每个元素放在具有唯一ID的div元素中. <%= form_for @mega,:remote=>true do %> <div id='main_part'> <%= render :partial => "main_part",:object=>@mega %> </div <div id='subpart1'> <%= render :partial => "subpart1",:object=>@foobar,:locals=>{:id=>@foobar.id} %> </div <div id='subpart2'> <%= render :partial => "subpart2",:object=>@barfoo,:locals=>{:id=>@barfoo.id} %> </div <% end %> 表单部分的一个示例,注意区分提交按钮: <%= label_tag "main_part[name]","Name" %> <%= text_field_tag "main_part[name]",main_part.name %> <%= submit_tag "UPDATE",:name=>'main_part' %> <%= hidden_tag_field "subpart1_id",id %> <%= label_tag "subpart1[city]","City" %> <%= text_field_tag "subpart1[city]",subpart1.city%> <%= submit_tag "ADD",:name=>'subpart1' %> 所以现在你需要一个大型控制器,因为这个表单发布到一个控制器动作.该控制器看起来只是顶级型号的常规控制器,但它需要为所有型号进行管理. 该控制器动作必须弄清楚点击了哪个提交按钮,即 def update if params[:main_part] # since I controlled the parameter naming I know what's in params[:main_part] # which is main_part[:name] @mega = MainThing.find(params[:id]) @mega.attributes = params[:main_part] @mega.save # only for main_part is the id valid,in every other case you have to # manually extract the id elsif params[:subpart1] @subpart1_id = params[:subpart1_id] @foobar = FooBar.find(@subpart1_id) @foobar.attrubutes = params[:subpart1] @foobar.save else end end 由于mega表单是remote => true,因此您需要创建一个javascript文件来重新加载所有表单部分,因此在app / views / megas / update.js.erb中: $('#main_part').html('<%= escape_javascript(render :partial=> "main_part",:object=>@mega) %>'); $('#subpart1').html('<%= escape_javascript(render :partial=> "subpart1",:object=>@foobar :locals=>{:id=>@foobar.id) %>'); 现在这里是性能问题的来源.如果您注意到,如果我运行该javascript,它将期望定义所有这些实例变量,因此各种部分将呈现刷新任何由于更新而获得新值的选择标记.在我的情况下,我只是在一个前过滤器中加载它们,即 class MegaController < ApplicationController before_filter :load,:only=>[:edit] def load @mega = Mega.find(params[:id]) @foobar = @mega.foobar @barfoo = @foobar.barfoo end 但你也可以不这样做,而是创建单独的javascript文件并在控制器中专门呈现它们,即 def update if params[:main_part] # do whatever... render :action=>'update_set1',:handler=>[:erb],:formats=>[:js] elsif params[:subpart1] # do whatever render :action=>'update_set1',:formats=>[:js] elsif params[:subpart2] # do whatever render :action=>'update_set2',:formats=>[:js] end end 文件app / views / mega / update_set1.js.erb只会更新受@mega或@foobar更新影响的部分,update_set2.js.erb会更新受@barfoo更新影响的部分. 最后一点,你的表单是remote => true,你怎么退出?假设你有: <%= submit_tag 'Cancel',:name=>'cancel' %> 然后在控制器中你会做类似的事情: def update if params[:cancel] render :js=> "window.location = '/'" else # whatever.... end end 最后一步是添加javascript以根据需要显示/隐藏表单div,一个练习留给读者…. UPDATE class Mega < ActiveRecord::Base def self.get_param_name self.class.name end def self.get_id_name "#{self.class.name}_id" end end class MyModel < Mega end 然后在一个巨型控制器: def edit @mymodel = MyModel.find(params[MyModel.get_id_name]) end (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |