Rails 5 - 创建1个模型的多个对象

时间:2017-10-04 01:53:04

标签: ruby-on-rails ruby

我认为我想要实现的目标非常简单。我希望有一个包含5个字段的表单,并且一个人可以从该表单创建任意数量的对象(即如果只填写1个字段,则创建1个对象,如果您填充2个字段,则创建2个对象等。 ..)

有趣的是,当我试图谷歌这个话题时,没有多少出现。我遇到的唯一“正当”例子是this。这导致我到达目前的位置(因为它不起作用)。

这是我的foo_controller.rb

def new
  @foo = []
  5.times do
    @foo << Foo.new
  end
end

def create
  if params.has_key?("foos")
    Foo.create(foo_params(params["foos"]))
  else
    params["foos"].each do |f|
      Foo.create(foo_params(f))
    end
  end
end

private
def foo_params(my_params)
  my_params.permit(:item_one, :item_two)
end

这是new.html.erb

<%= form_tag foos_path do %>
  <% @foo.each do |f| %>
    <% fields_for "foos[]", f do |ff| %>
      #all the form stuff, labels, buttons etc
    <% end %>
  <% end %>
<% end %>

在我提交之前,我已经“知道”有一个问题。我的表单字段都具有相同的ID,这意味着即使“if”我可以毫无问题地提交,只有最后一个条目最终会访问数据库。所以......

问题#1 - 我如何拥有唯一的表格ID?

我面临的下一个问题是当我点击提交时,我收到此错误Rack::QueryParser::ParameterTypeError (expected Array (got Rack::QueryParser::Params),所以基本上params没有收到正确的内容。那是我的下一个问题......

问题2 - 传递一系列参数的正确方法是什么?

但这都假设THIS指南的解决方案有效。我几乎每走一步都走了,但空洞了。所以我想我的重大问题是:

如何创建单个模型的一个或多个对象?

3 个答案:

答案 0 :(得分:2)

看起来你正朝着正确的方向前进。

问题1:ID

如果要创建新记录,则不需要ID。如果您希望能够使用相同的表单编辑记录,那么生成ID可能会更好,但这更多地取决于您希望如何处理创建与更新。

这样做的方式是Rails查看表单元素的名称。如果名称中有空括号,Rails会将参数渲染为数组:

<input type="text" name="foo[bar][][baz]" value="one" />
<input type="text" name="foo[bar][][baz]" value="two" />
<input type="text" name="foo[bar][][baz]" value="three" />

params => { foo: { bar: ["one", "two", "three"]}}

但是,如果你有ID,Rails会将params渲染成哈希:

<input type="text" name="foo[bar][1][baz]" value="one" />
<input type="text" name="foo[bar][2][baz]" value="two" />
<input type="text" name="foo[bar][3][baz]" value="three" />

params => { foo: { bar: {1: "one", 2: "two", 3: "three"}}}

问题3:创建模型

现在的诀窍是如何处理模型的创建。如果您想使用嵌套属性,可以通过设置#accepts_nested_attributes_for并将所有内容嵌套在bar_attributes下来实现。这将让你只需将params散列传递给模型,让它有一些魔力。

或者,您可能希望迭代params哈希,并在控制器中创建每个模型。

或创建一个表单对象以包含所有逻辑。由你决定。

我将从手动迭代过度方法开始,让事情有效。然后你可以重构和清理。

在控制器中可能看起来像这样:

array_of_bars = foo_params[:bar].map do |bar_params|
  Bar.new(baz: bar_params[:baz])
end

了解更多详情,请查看RailCast的Dynamic FormsNested Forms。在过去的几年里,我多次重复这些指南,并且每次都对结果代码感到满意。

答案 1 :(得分:0)

嵌套表单总是很棘手,但有些宝石可以帮到你。我最喜欢的一个是:https://github.com/nathanvda/cocoon

这是使用gem https://www.sitepoint.com/better-nested-attributes-in-rails-with-the-cocoon-gem/

的教程

答案 2 :(得分:0)

我一直在处理相同的错误Rack :: QueryParser :: ParameterTypeError(期望的数组(得到Rack :: QueryParser :: Params)。This answer helped me to fix it.

错误是由具有ID的记录呈现为散列的事实引起的。解决方案:您不需要fields_for。删除fields_for块并仅使用表单标记帮助程序应该可以工作,例如:

text_field_tag "foos[][name]", f["name"]

通过这种方法,将不会有与您的参数混乱的ID。如果你提交并检查参数,你会看到一系列漂亮的哈希。