tl; dr :似乎params[:commit]
不包含创建新提交的实际相关信息,而是仅包含表单的提交按钮的值name也是“commit”。关于为什么会发生这种情况的任何想法?我没有改变任何事情。
我正在使用webrick服务器运行rails 3,因为它显示相关的调试信息。我创建了一个只有一个属性description:text
的模型,一切似乎都运行正常。
然而,当我使用自动生成的脚手架形式创建一个新的时,它似乎并不关心描述文本区域值。换句话说,在创建完成后,created_at
列就可以了,除description
之外的所有列都没有显示。以下是服务器的输出:
Started POST "/commits" for 127.0.0.1 at 2010-11-03 17:24:20 -0700
Processing by CommitsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"F00A8Ttv7ceREegfZmP+T5kr+6u2YbRJrQzmfEOaT7o=", "commit"=>"Create Commit"}
SQL (0.5ms) INSERT INTO "commits" ("created_at", "description", "updated_at") VALUES ('2010-11-04 00:24:20.986571', NULL, '2010-11-04 00:24:20.986571')
Redirected to http://0.0.0.0:3000/commits/5
Completed 302 Found in 42ms
以下是我的迁移内容,由rails generate
def self.up
create_table :commits do |t|
t.text :description
t.timestamps
end
end
正如您所看到的,即使我在文本区域中键入了某些内容,它也会将描述值视为NULL
。以下是_form.html.erb
部分中生成的rails:
<div class="field">
<%= f.label :description %><br />
<%= f.text_area :description %>
</div>
任何人都有任何关于为什么会这样做的想法?我很确定这也很明显。
顺便说一下,rails console
在我创建一个并手动保存时工作正常,所以我觉得控制器在保存时会发生断开连接。
编辑:我注意到一些有趣的事情。在控制器中,对象是这样创建的:
@commit = Commit.new(params[:commit])
但是,如上面的webrick输出中所述,服务器接收的参数仅为:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"F00A8Ttv7ceREegfZmP+T5kr+6u2YbRJrQzmfEOaT7o=", "commit"=>"Create Commit"}
所以它似乎不会得到description
参数,我想这应该包含在commit
参数中,但是如果我查看new
的来源} form,它显示描述的文本区域名称为commit[description]
,但提交按钮的名称为commit
。所以不知何故,它只获得了提交按钮的值,这确实具有“创建提交”的价值,而不是它所需的其他信息。
我对rails不太了解,所以我真的不知道是不是这种情况或是什么。
有人请帮帮我哈哈。
编辑:以下是rails生成的_form.html.erb
部分的其余部分。也许你可以发现明显的问题:
<%= form_for(@commit) do |f| %>
<% 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 %>
<div class="field">
<%= f.label :description %><br />
<%= f.text_area :description %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
回答:看来Rails 3现在自动为每个提交按钮命名为“commit”,这与我的模型名称冲突。我担心的多了。我想知道使用这个名字是否有任何进一步的影响。通过明确地将提交调用更改为:
来解决此问题f.submit "Button Text", :name => "something_else"
答案 0 :(得分:4)
默认情况下,rails scaffolding将创建一个类似于以下内容的表单:
<%= form_for @commit do |f| %>
<%= f.label :description %>
<%= f.text_area :description %>
<%= submit_tag "Create" %>
<% end %>
请注意,我已将部分内容折叠到表单中。要理解的重要一点是,当发生这种情况时会生成HTML。它看起来像这样:
<form action="/commits/create" method="post">
<label for="commit_description">Description:</label>
<textarea id="commit_description" name="commit[description]"></textarea>
<input name="commit" type="submit" value="Create" />
</form>
您遇到的问题是提交按钮名称和对象名称之间的名称冲突。通常,当rails遇到类似“commit [description]”的表单名称时,它会将结果存储在@params中,因此值如下所示:
@params[:commit] = { :description => 'value' }
事实上,这就是rails所做的。问题是“submit_tag”表单助手生成的默认名称也称为“commit”。因此当rails遇到那个表单参数时,它会覆盖表单的结果,如下所示:
@params[:commit] = "Create" # same name as the value of the submit button
要解决此名称冲突,您有几个选择。第一个选项是用普通的旧HTML手写你的提交按钮。当然你丢失了一些选项,但至少你可以将提交按钮的名称更改为其他选项:
<input type="submit" name="who_cares" value="Create Commit" />
另一种选择是使用'form_for'助手的变体。在这种情况下,表单的开头行如下所示:
<%= form_for :newcommit, @commit, :url => { :action => "create" } do |f| %>
<%= f.label :description %>
<%= f.text_area :description %>
<%= submit_tag "Create" %>
<% end %>
这会将生成的HTML更改为:
<form action="/commits/create" method="post">
<label for="newcommit_description">Description:</label>
<textarea id="newcommit_description" name="newcommit[description]"></textarea>
<input name="commit" type="submit" value="Create" />
</form>
这会将您的表单数据绑定到@params [:newcommit]参数,您可以按照正常情况继续处理。
为了您的进一步阅读乐趣:
答案 1 :(得分:1)
form_for生成的字段名称为commit[description]
。
但是,最后一个提交按钮的名称为commit
。
我认为最后一个提交按钮会覆盖前commit[]
个。
请尝试<%= f.submit "Your button text", :name => "something_else" %>