使用rails中的fields_for的动态复选框

时间:2010-03-29 20:06:46

标签: ruby-on-rails dynamic checkbox multiple-models fields-for

我与链接框有多对多的关系,我想将这些模型合并为一个表单,以便我可以从同一页面进行更新。我真的很难让check_box甚至显示我阵列的所有元素 - 我已经在网上搜索并且整天都在努力工作,而且我发现很难将我正在阅读的信息应用到我的问题。我也是RoR的新手,我一直在关注一些过时的视频教程(2.0之前的版本),所以对我的代码道歉。到目前为止,我已经让它只输出数组中的一个键对(最后一个) - 虽然在表单之外,本教程中使用的代码完全按照它应该如何工作。虽然这很少用!主机是主要表单所针对的模型,而Billing是我尝试添加到表单的外部模型。

这是在教程的表单之外工作的代码:

<% for billing in @billings -%>
<%= check_box_tag('billing_title[]', billing.id, @host.billings.collect
{|obj| obj.id}.include?(billing.id))%> <%= billing.title %><br />
<% end -%>

我只需要知道如何在表单内部工作。这是前面提到的代码,它只在循环遍历后检索最后一个数组密钥对:

<% f.fields_for :billings do |obj| %><br />
<%= check_box_tag('billing_title[]', billing.id, @billings.collect
{|obj| obj.id}.include?(billing.id))%> <%= billing.title %><br />
<% end %>

调试(@billings):

--- 
- !ruby/object:Billing 
attributes: 
title: Every Month
id: "1"
attributes_cache: {}

- !ruby/object:Billing 
attributes: 
title: 12 Months
id: "2"
attributes_cache: {}

- !ruby/object:Billing 
attributes: 
title: 6 Months
id: "5"
attributes_cache: {}

任何帮助都非常感激。

3 个答案:

答案 0 :(得分:2)

Craig,听起来你正在寻找的是accepts_nested_attributes_for,这是处理表单中嵌套模型的更好方法。

我不会直接窃取所有Ryan的作品并将其转发给我,我只会给你一个他的截屏视频链接:

http://railscasts.com/episodes/196-nested-model-form-part-1

这是基于他的复杂形式系列。

你应该能够将这个教程发展到你想要做的事情,但如果没有,我会很乐意提供帮助。

修改

好的,看了你的代码后,有一些事情会导致你的问题。 :)

首先,通过关联,您无需为账单提取额外的收款,即:

@host = Host.find(params[:id])
@voips = Voip.find(:all)
@custsupps = Custsupp.find(:all)
@payments = Payment.find(:all)
@billings = Billing.find(:all) # <-- This is not needed and causing your problems

模型中的关联设置会为您完成所有操作。这是铁路魔术的一部分。 :d

现在,需要注意的是,在使用关联时,您需要确保对象实际关联。换句话说,如果数据库中有3个Billings对象,并且它们与Host对象没有关联,则它们不会显示在表单中。

如果您尝试使用复选框将结算与主机相关联,则您需要采用不同的方法,因为您的表单只显示Billings 已与您的主机关联。

如果您只是想编辑或修改与主机关联的现有Billings,例如复选框表示'付费'属性(布尔值),那么这种方法很好,您的表单代码看起来像这样:

<% f.fields_for :billings do |b| %><br />
  <%= b.check_box :paid %> <%= b.title %>
<% end %>

因此,或许从功能的角度阐明您想要实现的目标,我们可以找到更好的解决方案。

答案 1 :(得分:0)

我不确定我的答案,但我会尝试......

<% f.fields_for :billings, @billings do |obj| %>
   # ...
<% end %>

答案 2 :(得分:0)

让我觉得这是for循环的问题......

在您的示例代码中,您循环遍历@billings(从控制器传递的一组计费对象),并调用当前的billing

在表单代码中,您循环遍历:billings(引用计费ActiveRecords的符号)并调用当前的obj。然后,令人困惑的是,您的代码在@ billings.collect函数中再次重用变量名obj ...但是这应该具有本地私有范围而不会影响您的主循环,但很难在视觉上解释

无论如何,由于表单循环中的内容没有引用obj,它正在使用变量billing - 当你循环时它不会改变,但保留它的最后一个值:上一循环中的最后一项!这解释了为什么您只看到最后一个标记。 (另外,debug(@billings)函数自己循环遍历各种记录 - 它不在fields_for do循环中。)

我首先要更改表单代码的第一行,然后再次使用变量名billing,如下所示:

<% f.fields_for :billings do |billing| %><br />

Ruby's block syntax一开始可能会让人感到困惑 - 或者,哎呀,无论何时你正在阅读你自己没有写过的代码 - 但是当你把它全部分解为基本组件时,它通常只是循环通过一组项目并在每个项目上执行一些功能。还要注意类似名字之间的混淆:@billing,@ billings,:账单和账单都是Ruby和Rails的不同之处。祝好运!