【问题标题】:set dynamic nested form name and ID attributes设置动态嵌套表单名称和 ID 属性
【发布时间】:2013-12-19 18:57:13
【问题描述】:

我有一个具有两个模型的 Rails 应用程序:计划和任务。 Task belongs_to Schedule 和 Schedule has_many Tasks。我使用带有 javascript 的嵌套表单来允许用户在创建计划时输入任意数量的任务。这是我的表格:

<%= form_for [@project, @schedule] do |f| %>
    <%= f.fields_for :tasks do |builder| %>
        <%= render 'task_fields', :f => builder %>
    <% end %>
    <p><%= link_to_add_fields "Add task", f, :tasks %>
    <p><%= f.submit "Submit" %></p>
<% end %>

这是上面表格所指的部分:

<p class = "fieldo">

     <%= f.label :title %><br />
     <%= f.text_field :title %><br />

     <%= f.label :content %><br />
     <%= f.text_field :content %><br />

     <%= f.hidden_field :_destroy %>

    <%= link_to_function "remove", "remove_fields(this)"  %>
</p>

这是表单的调度控制器操作:

def new
    2.times {@schedule.tasks.build}
end

因此,正如您从控制器中看到的那样,表单会自动将 2 个任务表单打印到页面上。这 3 种形式给出以下 html:

<p class = "fieldo">
    <input id="schedule_tasks_attributes_0_title" name="schedule[tasks_attributes][0][title]" type="text" /><br />
    <input id="schedule_tasks_attributes_0_content" name="schedule[tasks_attributes][0][content]" type="text" /><br />
</p>
<p class = "fieldo">
    <input id="schedule_tasks_attributes_1_title" name="schedule[tasks_attributes][1][title]" type="text" /><br />
     <input id="schedule_tasks_attributes_1_content" name="schedule[tasks_attributes][1][content]" type="text" /><br />
</p>

如您所见,id 和 name 从 0 开始并以 1 递增。这很好,也是我期望它工作的方式。问题是,当我通过按下“添加任务”按钮动态添加任务时,id 和 name 变成这样的随机数:

<p class = "fieldo">
    <input id="schedule_tasks_attributes_1387479041550_title" name="schedule[tasks_attributes][1387479041550][title]" type="text">
    <input id="schedule_tasks_attributes_1387479041550_content" name="schedule[tasks_attributes][1387479041550][content]" type="text">
</p>
<p class = "fieldo">
    <input id="schedule_tasks_attributes_1387479043642_title" name="schedule[tasks_attributes][1387479043642][title]" type="text">
    <input id="schedule_tasks_attributes_1387479043642_content" name="schedule[tasks_attributes][1387479043642][content]" type="text">
</p>

我的问题是:

  1. 这些数字是什么?它们是如何产生的?
  2. 有没有什么方法可以在不破坏功能的情况下更改此设置以获得更整洁的数字?

如果有人看过 rails cast #197,那么这个表格就是基于此。这是我的 javascript 和我也在使用的 ruby​​ 助手。

javascript:

//Dynamic forms
 function remove_fields(link) {
         $(link).prev("input[type=hidden]").val("1");
         $(link).closest(".fieldo").hide();
 }

 function add_fields(link, association, content) {
         var new_id = new Date().getTime();
         var regexp = new RegExp("new_" + association, "g");
         $(link).parent().before(content.replace(regexp, new_id)); 

 }

应用助手:

def link_to_add_fields(name, f, association)
  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(association.to_s.singularize + "_fields", :f => builder)
  end
  link_to_function(name, raw("add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")"))
end

【问题讨论】:

    标签: javascript ruby-on-rails ruby nested-forms nested-attributes


    【解决方案1】:

    1):这个巨大的数字来自 Javascript 行 var new_id = new Date().getTime();,它使用时间戳设置新行的 HTML id,这使其“几乎”是 uniq。


    2):是的,您可以将其更改为使用“合理的人数”。

    function add_fields(link, association, content) {
             var new_id = Math.floor((Math.random()*10000)+3);
             var regexp = new RegExp("new_" + association, "g");
             $(link).parent().before(content.replace(regexp, new_id)); 
    }
    

    这将用 10003 和 3 之间的随机数替换这个巨大的数字。但我建议你让 Rails 处理这个巨大的数字:首先,它会阻止你应用程序的潜在邪恶用户,其次,它几乎 -确保一个唯一的 id。


    但是,嘿,永远记住 #1 开发者的规则:

    如果没有损坏,请不要修复它。

    【讨论】:

    • 不能像增加 1 一样简单地使它们成为唯一值吗?如果它适用于控制器中构建的任务,为什么这对站点上构建的任务不利?
    • 因为只使用 的时间戳比扫描输入、获取它们的 html id 作为字符串、扫描字符串以找到其中的索引、确定哪一个所需的时间/代码行更少是最大的,然后递增。此外,这意味着计算依赖于其他输入的存在,这增加了另一个约束。 -> 它变得不那么灵活了!
    【解决方案2】:

    如果没有看到更多代码,很难确定,但我认为这些是您在 rails 端 task.build 时创建的“临时” ID。使用debuggerpry 或一些puts @schedule.tasks.all.collect{|t| t.id} 进行检查。

    如果是这样的话,那么不,你不能“得到更整洁的数字”,但你不会想要 - 你只需要它们是唯一的,并且 Rails 可以很好地处理创建任务。因此,只需检查您的数据库在 create 操作后是否符合您的预期,然后将其称为完成。

    【讨论】:

      猜你喜欢
      • 2013-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-17
      • 2021-08-25
      • 2018-05-22
      相关资源
      最近更新 更多