Rails 3.2 Обновление вложенных атрибутов
Вот моя проблема. Если я пойду к Projects#edit
Я не могу изменить курс, которому он назначен. Если я пытаюсь создать для него новый курс или выбрать один из существующих, я получаю следующую ошибку:
Couldn't find Course with ID=23 for Project with ID=62
app/controllers/projects_controller.rb:49:in `update'
{...
"project"=>{"title"=>"Sup",
"due_date"=>"2012-01-23",
"course_id"=>"27", # THIS IS THE ID OF THE NEW COURSE I WANT
"course_attributes"=>{"name"=>"Calc I", # THIS IS THE OLD ONE, I don't need this. Why is it passing this?
"number"=>"MATH102",
"user_id"=>"3",
"id"=>"23"},
"description"=>"bla bla bla"},
"commit"=>"Update Project",
"user_id"=>"3",
"id"=>"62"}
Итак, я вижу, что он пытается пройти в course_attributes
, но это на самом деле не установка нового course_id
, Я не понимаю почему course_attributes
передается, другая форма пуста, а course_attributes
Проходящие, являются атрибутами старого курса. Я хочу установить course_id как course_id
проходит (27 в этом случае).
ProjectsController
def new
@project = @user.projects.new
@courses = @user.courses # Used to populate the collection_select
@project.build_course # I was informed I need to use this to get the form_for to work
end
def edit
@project = Project.find(params[:id])
@courses = @user.courses # Used to populate the collection_select
end
def update
@project = Project.find(params[:id])
@courses = @user.courses
if @project.update_attributes(params[:project])
flash[:notice] = 'Project was successfully updated.'
redirect_to user_projects_path(@user)
else
render :edit
end
end
Строка 49 - это вызов update_attributes
,
Дополнительная информация
project.rb
belongs_to :user
belongs_to :course
attr_accessible :course_id, :course_attributes
accepts_nested_attributes_for :course
course.rb
belongs_to :user
has_many :projects
user.rb
has_many :projects
has_many :courses
Таким образом, у проекта есть course_id в базе данных. В настоящее время я создаю или выбираю существующий курс на лету на Projects#new page. Вот моя форма для этого. Я использую JavaScript-переключатель для переключения между collection_select и двумя text_fields.
Проекты /new.html.haml
= form_for [@user, @project] do |f|
# This is shown by default
= f.collection_select :course_id, @courses, :id, :name, { prompt: true }
.hidden # This is hidden by default and shown using a toggle
= f.fields_for :course do |builder|
= builder.text_field :name, class: 'large', placeholder: 'Ex: Calculus I'
= builder.label :number, 'Number'
= builder.text_field :number, class: 'new_project_course_number'
= builder.hidden_field :user_id, value: current_user.id
Теперь, если я нахожусь на странице нового проекта и прикрепляю его к курсу, выбирая существующий курс, он будет работать правильно. Проект будет создан, а course_id
будет установлен правильно.
Если я нахожусь на странице нового проекта и создаю курс с помощью переключателя JavaScript, затем заполняю Имя курса и Номер курса и нажимаю Создать, тогда он также будет работать. Курс будет создан, и Проект будет создан с правильным course_id
,
Извините за длинный пост, но я хотел предоставить всю информацию, которую мог. Спасибо!
ОБНОВЛЕНИЕ 1
routes.rb
resources :users do
resources :projects do
collection do
get 'completed'
match 'course/:course_number' => 'projects#course', as: 'course'
end
end
resources :courses
end
2 ответа
Предполагая, что ваш Projects#edit
форма похожа на вашу Projects#new
Это создает course_attributes
в парамах
.hidden # This is hidden by default and shown using a toggle
= f.fields_for :course do |builder|
= builder.text_field :name, class: 'large', placeholder: 'Ex: Calculus I'
= builder.label :number, 'Number'
= builder.text_field :number, class: 'new_project_course_number'
= builder.hidden_field :user_id, value: current_user.id
Это потому, что если user
имеет текущий курс, он будет создавать поля для каждого курса.
Если вы хотите быть в состоянии построить новый курс на лету в edit
а также new
измените эту строку на:
= f.fields_for :course, @project.build_course(:user => @user) do |builder|
Это создаст новый course
независимо от того, находитесь ли вы в редактировании или новый. (Также вы можете удалить @project.build_course
в вашем контроллере таким образом.)
Вы не перечисляете свои маршруты, но при условии, что они настроены правильно, тогда обновление ProjectsController должно быть в состоянии сделать что-то вроде:
@course = Course.find(params[:course_id])