嘿伙计们,我在理解Rails构造时遇到了麻烦。我正在使用Rails 3,但我怀疑这是否适用于此版本。
我有一个Goal
模型,has_many :commits
自然是一个Commit
模型belongs_to :goal
。我创建了正确的迁移,以便commits_table.references :goal
。
我实际上正在阅读Rails Getting Started指南,除了那篇文章他们分别使用Post
和Comment
。
现在我已经描述过这种情况,我可以表达我的困惑。在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
?
感谢。我只是试图了解这些新概念。
答案 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方法提供提交和目标对象。