无法在 Rails 中创建新模型

发布于 09-30 09:44 字数 3045 浏览 7 评论 0原文

tl;dr:似乎params[:commit]不包含创建新Commit的实际相关信息,而是仅包含提交按钮的值对于名称也是“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

这是我的迁移的样子,由 railsgenerate 自动生成

def self.up
  create_table :commits do |t|
    t.text :description

    t.timestamps
  end
end

因此,如您所见,它将描述值视为 NULL即使我确实在文本区域中输入了一些内容。以下是 Rails 在 _form.html.erb 部分中生成的内容:

<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 表单的源代码,它会显示描述的文本区域的名称为 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"

tl;dr: It seems like params[:commit] does not contain the actual relevant information to create a new Commit, instead, it only contains the value of the submit button for the form whose name is also "commit". Any ideas as to why this is happening? I did not change anything.

I am running rails 3 with the webrick server since it displays relevant debugging information. I created a model with only one attribute, description:text, and everything seems to be working fine.

However, when I go to create a new one using the auto-generated scaffolding form, it does not seem to care about the description text-area value. In other words, after having been created, the created_at column is fine and all but the description does not show up at all. Here is the output from the server:

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

Here is what my migration looks like, auto-generated by rails generate

def self.up
  create_table :commits do |t|
    t.text :description

    t.timestamps
  end
end

So as you can see, it is seeing the description value as NULL even though I did type something into the text area. Here is what rails generated in the _form.html.erb partial:

<div class="field">
  <%= f.label :description %><br />
  <%= f.text_area :description %>
</div>

Anyone have any ideas as to why this is happening? I'm pretty sure it's some obvious thing too.

By the way, rails console works fine when I create one and save it manually, so I have a feeling there is a disconnect going on in the controller when it goes to save or something.

EDIT: I noticed something interesting. In the controller, the object is created as such:

@commit = Commit.new(params[:commit])

However, as noted in the webrick output above, the parameters the server receives are only:

Parameters: {"utf8"=>"✓", "authenticity_token"=>"F00A8Ttv7ceREegfZmP+T5kr+6u2YbRJrQzmfEOaT7o=", "commit"=>"Create Commit"}

So it doesn't seem like it gets the description parameter, which I imagine should have been wrapped in the commit parameter, but then if I look at the source for the new form, it shows that the description's text area is of name commit[description], but the submit button is of name commit. So somehow it's getting only the value of the submit button, which is indeed of value "Create Commit", and not the other information it requires.

I don't know that much about rails though so I don't really know if this is the case or what.

Someone please help me out haha.

EDIT: Here is the rest of the _form.html.erb partial generated by rails. Perhaps you can spot the glaring issue:

<%= 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 %>

Answer: It seems that Rails 3 now automatically gives every submit button a name of "commit", which conflicts with the name of my model. I feared as much. I'm wondering if there are any further implications on using this name. This problem was solved by explicitly changing the submit call to:

f.submit "Button Text", :name => "something_else"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

幻想少年梦2024-10-07 09:44:36

默认情况下,rails 脚手架将创建一个如下所示的表单:

<%= 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

By default, the rails scaffolding will create a form that will look something like the following:

<%= form_for @commit do |f| %>
  <%= f.label :description %>
  <%= f.text_area :description %>
  <%= submit_tag "Create" %>
<% end %>

Please note that I have collapsed the content of the partial into the form itself. The important thing to understand is what HTML is generated when this happens. It will look like this:

<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>

The gotcha you've run into is a name collision between the submit button's name and the object's name. Normally, when rails encounters a form name like "commit[description]" it will store the results in @params so the value looks like this:

@params[:commit] = { :description => 'value' }

In fact, that is what rails did. The problem was that the default name generated by the "submit_tag" form helper is also named "commit". So when rails encountered that form parameter it overwrote the results of the form like this:

@params[:commit] = "Create" # same name as the value of the submit button

To get around this name collision you have a couple options. The first option is to hand write your submit button in plain old HTML. Sure you lose some of the options, but at least you can change the name of the submit button to something else:

<input type="submit" name="who_cares" value="Create Commit" />

The other option is to use a variation of the 'form_for' helper. In this case the form's opening line would look like this:

<%= form_for :newcommit, @commit, :url => { :action => "create" } do |f| %>
  <%= f.label :description %>
  <%= f.text_area :description %>
  <%= submit_tag "Create" %>
<% end %>

That will change the resulting HTML to look like this:

<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>

That will bind your form data to the @params[:newcommit] parameter, and you can continue processing as per normal.

For your further reading enjoyment:

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

街角迷惘2024-10-07 09:44:36

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

所以请尝试 <%= f.submit "Your button text", :name =>; “something_else”%>

The form_for generates fields with name like commit[description].
However, the last subit button have the name of commit.
I think the last submit button overwrites the fore commit[]s.

So please try <%= f.submit "Your button text", :name => "something_else" %>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文