Rails 3.2 создание родительской модели из дочернего представления


Я имея трудное время понимание как это делать. У меня есть две модели, проект и курс.

#project.rb
belongs_to :course
attr_accessible :course_id, :course
accepts_nested_attributes_for :course, reject_if: lambda { |a| a[:course_id] == 0 }

#course.rb
has_many :projects

На странице Projects#new (дочерний объект) я хочу ввести имя нового course и заставить его создать родительский объект.

Вот моя попытка в представлении, но она, кажется, не работает правильно.

= form_for [@user, @project] do |f|

  # Other fields

  = fields_for :course do |builder|
    = builder.label :name, 'Course Name'
    = builder.text_field :name

  = f.submit

Позже я буду использовать этот родительский объект для создания новых проектов, но пока предположим, что он не существует.

Обновление 1 Я модифицировал мои fields_for, чтобы быть (в соответствии с запросом Райана):

= form_for [@user, @project] do |f|

  # Other fields

  = f.fields_for :course do |builder|
    = builder.label :name, 'Course Name'
    = builder.text_field :name

  = f.submit

Я использую haml, поэтому = должен отображаться, но поля for даже не отображаются на странице или в сгенерированном html. Есть какие-нибудь догадки, почему это так? (Кнопка Отправить действительно отображается)

Обновление 2 Я нашел потенциальное решение, но не уверен, что это правильный подход. В контроллере мне нужно построить курс для отображения fields_for.

# ProjectsController
def new
  @project  = @user.projects.new
  @project.build_course
end

# project.rb
attr_accessible :course_attributes
# So yes, I now see what you were talking about, regarding the course_attributes
2 2

2 ответа:

Вы должны использовать конструктор форм для построения Вашего объекта, а не просто fields_for сам по себе.

У вас есть это:

= fields_for :course do |builder|

Где вы должны иметь это:

= f.fields_for :course do |builder|

Разница заключается в том, что, вызывая его на начальном построителе форм, Rails проверит, есть ли метод course_attributes= на объекте из начального вызова form_for (в этом случае это будет @project), и если есть, то он определит поля внутри этой формы как course_attributes.

Вперед и проверьте форму до и после этого изменения, просто чтобы увидеть. Я подожду.

Это стало возможным благодаря вызову accepts_nested_attributes_for в вашей модели. Именно этот метод определяет метод course_attributes=, который позволяет вложенным атрибутам работать. После того, как вы создадите проект, он должен также создать курс.

Кроме того, нет необходимости делать course_id доступным атрибутом, поскольку ваша форма не будет устанавливать его.

Я использовал gem 'dynamic_form'. таблица faculty_list (id, faculty_name) содержит названия факультетов.

<%= f.select :faculty, options_from_collection_for_select(@faculty_list, 'id', 'faculty_name', @faculty.faculty.to_i) %>