无法在Rails中创建新模型

时间:2010-11-04 00:47:05

标签: ruby-on-rails webrick

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"

2 个答案:

答案 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]参数,您可以按照正常情况继续处理。

为了您的进一步阅读乐趣:

http://guides.rubyonrails.org/form_helpers.html

答案 1 :(得分:1)

form_for生成的字段名称为commit[description]。 但是,最后一个提交按钮的名称为commit。 我认为最后一个提交按钮会覆盖前commit[]个。

请尝试<%= f.submit "Your button text", :name => "something_else" %>