Вопрос о форме ассоциации Rails Вопрос - PullRequest
1 голос
/ 06 ноября 2010

Эй, ребята, у меня проблемы с пониманием конструкции Rails.Я использую Rails 3, но сомневаюсь, что это специфично для этой версии.

У меня есть модель, Goal, которая has_many :commits и, естественно, модель Commit, которая belongs_to :goal.Я создал правильную миграцию таким образом, чтобы commits_table.references :goal.

Я на самом деле проходил руководство Rails Getting Started , за исключением того, что в этой статье они используют Post и Comment соответственно.

Теперь, когда я описал ситуацию, я могу выразить свое замешательство.В представлении Goal show я встроил форму для создания нового коммита, который «привязан» к просматриваемой цели.Это отлично работает и все.Однако мне трудно понять, почему мы делаем это

<%= form_for([@goal, @goal.commits.build]) do |f| %>

Разве это не должно быть form_for(@commit)?Я понимаю, почему мы хотим, чтобы @goal предоставлял некоторый контекст, поскольку коммит является вложенным ресурсом.Однако в фактическом сгенерированном источнике форма соответствующим образом называется коммитом, то есть поля имеют имя commit_blah.Как Rails узнал об этом?Я понимаю, что существует вся эта система "доверия и магии" и все такое, но я имею в виду, по крайней мере, на высоком уровне, что из этого кода подсказало Rails, что я хочу сделать коммит?

Я посмотрел на документация для form_for, и кажется, что одним из параметров может быть действие для формы.Я полагаю, что в этом случае для этого нужен параметр @goal.commits.build?Для обозначения действия предпринять?Это то, как Rails выводит, что я хочу коммит?Это также объясняет, почему эта форма обрабатывается контроллером Commit, хотя этот код находится в представлении цели?

Кроме того, почему эти параметры передаются в виде массива ([])?В Ruby будет ли метод по-прежнему воспринимать его как два отдельных параметра, или есть причина, по которой это было передано таким образом?

Наконец, rails generate автоматически дал мне ошибку при отображении кода в моем другом _form.html.erb partials:

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

Спасибо.Я просто пытаюсь разобраться с этими новыми понятиями.

Ответы [ 2 ]

1 голос
/ 06 ноября 2010

Если вы вернетесь к документации и нажмете «показать источник», вы увидите

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 первым параметром может быть запись, имя или массив. В вашем случае вы передаете ему массив. Затем код определяет «объект» как последний элемент этого массива, который является вашим объектом @ goal.commits.build. Имя объекта определяется с помощью метода ActiveModel :: Naming.singular .

console > ActiveModel::Naming.singular(@goal.commits.build)
=> "commit"

Затем он сгенерировал соответствующие поля формы, используя fields_for и 'commit'.

0 голосов
/ 06 ноября 2010

Похоже, вы используете вложенные ресурсы. Проверьте ваш файл rout.Rb, чтобы увидеть, есть ли у вас что-то вроде:

map.resources: commitits,: has_many =>: цели

или, возможно:

map.resources: commits do | commit | commit.resources: цели конец

Если это так, то вам необходимо предоставить оба объекта commit и target для метода form_for.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...