2012-01-24 5 views
1

Вот моя проблема. Если я перейду к Projects#edit, я не могу изменить курс, которому он назначен. Если я пытаюсь создать новый курс для него, или выбрать из существующего, я получаю следующее сообщение об ошибке:Rails 3.2 Обновление вложенных атрибутов

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 в базе данных. В настоящее время я создаю или выбираю существующий курс «на лету» на новой странице «Проекты». Вот моя форма для этого. Я использую JavaScript, чтобы чередовать между collection_select и двумя текстовыми полями.

проекты/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

маршруты.Р.Б.

resources :users do 
    resources :projects do 
    collection do 
     get 'completed' 
     match 'course/:course_number' => 'projects#course', as: 'course' 
    end 
    end 

    resources :courses 
end 
+0

Просто подсказка: возможно, лучше переместить описание проблемы в голову сообщения, чтобы остальное было прочитано в контексте проблемы. –

+0

Неплохая идея, я просто писал и писал, ха-ха. Я немного переделал его. Спасибо @Sergio. – ardavis

ответ

3

Предполагая, что ваш Projects#edit формы похожа к вашему Projects#new

Это создает course_attributes в Params

.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 в своем контроллере таким образом.)

+0

Спасибо, сэр за ваш ответ. Это не позволит мне вознаградить вас своей щедростью до завтрашнего дня (через 22 часа). Я обязательно это сделаю :) Вместо ': user => @ user', я просто использовал': user_id => @ user.id'. Но более конкретно, это не сработало с пользовательским сеттером, я просто оставил его, и он работал по умолчанию. Мысли об этом? – ardavis

+0

Кроме того, в случае, если кто-то придумает другой способ сделать это, щедрость будет идти к тому, какой метод кажется лучшим. Но дайте мне знать, что вы думаете о том, почему я не мог использовать пользовательский сеттер. Когда я попытался, он не смог найти курс с курсом_ид из "". Параметр был пустым. – ardavis

+0

Да, это потому, что 'course_id' - это поле базы данных. Я думал взад-вперед, Извините, я это выдержу. Но я не знаю, почему этот парам был принят как «« это странно. – Azolo

0

Вы не перечисляете свои маршруты, но если предположить, что настроено правильно, то обновление ProjectsController должно быть в состоянии сделать что-то вроде:

@course = Course.find(params[:course_id]) 
+0

Так что, даже если я устанавливаю переменную экземпляра '@ course', как это помогает вызов' @ project.update_attributes'? – ardavis

+0

Обновление кода, который отражает мои маршруты. См. Обновление 1 – ardavis

 Смежные вопросы

  • Нет связанных вопросов^_^