Rails模型 - 关联表格问题

时间:2010-11-06 00:16:07

标签: ruby-on-rails ruby

嘿伙计们,我在理解Rails构造时遇到了麻烦。我正在使用Rails 3,但我怀疑这是否适用于此版本。

我有一个Goal模型,has_many :commits自然是一个Commit模型belongs_to :goal。我创建了正确的迁移,以便commits_table.references :goal

我实际上正在阅读Rails Getting Started指南,除了那篇文章他们分别使用PostComment

现在我已经描述过这种情况,我可以表达我的困惑。在Goal显示视图中,我嵌入了一个表单来创建一个新的提交,该提交已“附加”到当前查看的目标。这很好用。但是,我无法理解为什么要这样做

<%= form_for([@goal, @goal.commits.build]) do |f| %>

不应该是form_for(@commit)吗?我理解为什么我们希望@goal提供一些上下文,因为提交是嵌套资源。但是,在实际生成的源中,表单适当地命名为commit,即字段名为commit_blah。 Rails是怎么知道的?我知道有这个“信任和魔法”的整个系统,但我的意思是至少在高层次上,从这段代码中暗示我想要提交的Rails?

我查看了documentation for form_for,看起来其中一个参数可能是对表单采取的操作。我想在这种情况下,这是@goal.commits.build参数的用途?指定要采取的行动?这是Rails如何推断我想要提交?这也解释了为什么这个表单由Commit控制器处理,即使此代码在目标视图中?

另外,为什么这些参数作为数组([])传递?在Ruby中,该方法是否仍然将它作为两个单独的参数,或者是否有这样的原因通过这种方式?

最后,rails generate自动向我显示了一些错误,显示我的其他_form.html.erb部分代码:

<% if @commit.errors.any? %>
  <div id="error_explanation">
    <h2><%= pluralize(@commit.errors.count, "error") %> prohibited this commit from being saved:</h2>

    <ul>
    <% @commit.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
    </ul>
  </div>
<% end %>

如果我想将此添加到此嵌入表单中,我该怎么做?我想我的问题是,我会用什么代替@commit

感谢。我只是试图了解这些新概念。

2 个答案:

答案 0 :(得分:1)

如果您返回文档并点击“显示来源”,您会看到

def form_for(record_or_name_or_array, *args, &proc)
  ...
  case record_or_name_or_array
  when String, Symbol
    ...
  when Array
    object = record_or_name_or_array.last
    object_name = options[:as] || ActiveModel::Naming.singular(object)
    apply_form_for_options!(record_or_name_or_array, options)
    args.unshift object
  else
    ...
  end
  ...
  output << fields_for(object_name, *(args << options), &proc)
  ...

对于form_for,第一个参数可以是记录,名称或数组。在您的情况下,您传递一个数组。然后代码将'object'确定为该数组的最后一个成员,即@ goal.commits.build对象。对象名称由ActiveModel::Naming.singular方法确定。

console > ActiveModel::Naming.singular(@goal.commits.build)
=> "commit"

然后使用fields_for和'commit'生成相应的表单字段。

答案 1 :(得分:0)

看起来您正在使用嵌套资源。检查你的routes.rb文件,看看你是否有类似的东西:

map.resources:commits,:has_many =&gt; :目标

或者也许:

map.resources:提交do | commit |   commit.resources:目标 端

如果是这种情况,那么您需要向form_for方法提供提交和目标对象。