Не могу создать новую модель в Rails - PullRequest
0 голосов
/ 04 ноября 2010

tl; dr : Похоже, что params[:commit] не содержит актуальную релевантную информацию для создания нового коммита, вместо этого он содержит только значение кнопки отправки для формы, имя которой также «совершить». Есть идеи, почему это происходит? Я ничего не менял.

Я запускаю rails 3 с сервером webrick, поскольку он отображает соответствующую информацию об отладке. Я создал модель только с одним атрибутом, 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 партиале:

<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. Так что каким-то образом он получает только значение кнопки отправки, которая действительно имеет значение «Создать коммит», а не другую информацию, которая ему требуется.

Я не так много знаю о рельсах, поэтому не знаю, так ли это на самом деле.

Кто-нибудь, пожалуйста, помогите мне, ха-ха.

РЕДАКТИРОВАТЬ : Здесь находится остальная часть _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 ]

4 голосов
/ 04 ноября 2010

По умолчанию леса рельсов создадут форму, которая будет выглядеть примерно так:

<%= 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 голос
/ 04 ноября 2010

Form_for генерирует поля с именем вроде commit[description].Тем не менее, последняя кнопка subit имеет имя commit.Я думаю, что последняя кнопка отправки перезаписывает передний план commit[] с.

Поэтому, пожалуйста, попробуйте <%= f.submit "Your button text", :name => "something_else" %>

...