Topic: problem with created nested models

So I am very new to rails and slightly novice to programming, as a background. I understand a lot of the aspects of Active Record association, such as the basic belongs_to, etc. I do not understand how to create new objects (rows) for nested models. Let me show you my example. 

So for my basic app, you have a course model and a task model. 

Class Course
  has_many :tasks
end   

Class Task
   belongs_to :courses
end

 

I also understand the resources aspect, so I have

resources :courses do
   resources :tasks
end
 

when I do

 rake routes 
I can clearly see the new_course_task routes and other related routes. The problem I get is when I try and create a new object of task for a certain course. Do I have to create a new method in the course controller (like create_task)? Then, how can I incorporate this into my views? To me it seems like I need to make a new controller for Course.tasks or something so I have the necessary screens, but I do not think that's right.

Another thing I tried was adding this to my Course show screen

<% form_for([@task, @course.tasks.build]) do |f| %>
    <div class="field">
      <%= f.label :title %><br />
      <%= f.text_field :title %>
    </div>
    <div class="field">
      <%= f.label :note %><br />
      <%= f.text_area :note %>
    </div>
    <div class="field">
      <%= f.label :due_date %><br />
      <%= f.date_select :due_date, :order => [:month, :day, :year] %>
    </div>
    <div class="actions">
      <%- f.sumbit %>
    </div>
<% end %>

Here, I get an error message saying, 'undefined method 'submit.''

I have also added this to the create method in tasks_controller

def create
    @course = Course.find(params[:id])
    @task = @course.tasks.create(params[:task])

    respond_to do |format|
      if @task.save
        redirect_to { course_path(@course), :notice => 'Task was successfully created.'}
        format.xml  { render :xml => @task, :status => :created, :location => @task }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @task.errors, :status => :unprocessable_entity }
      end
    end
  end

This is where I am stuck. I am sure it is a simple solution, I am just having trouble connecting the dots between a few tutorials, guides, and documentation.

Thanks in advance for the help. I am in love with RoR, and can't wait to be part of this community.

Re: problem with created nested models

first of all:

<% form_for([@task, @course.tasks.build]) do |f| %>

If your goal is to get to the url /courses/:course_id/tasks/, then your code should be:

#course controller:
def show
  @course = Course.find(params[:id])
end

# view
<% form_for([@course, @course.tasks.build]) do |f| %>

Next you had:

<%- f.sumbit %>

That should be:

<%= f.submit %>

And lastly in your tasks_controller:

def create
    @course = Course.find(params[:id])
    @task = @course.tasks.create(params[:task])
    ...

Since you are using nested resources, you will automatically have params[:course_id] as well as params[:task].   Since your task model belongs_to Course, that means task has a course_id column...  So there are many different variations of how you could do this..  Here are a few:

def create
    task_params = params[:task].merge(params[:course_id])
    Task.create!(task_params)
   ...

# or

def create
    @course = Course.find(params[:course_id])
    @course.tasks << Task.create!(params[:task])

# or

def create
    @course = Course.find(params[:course_id])
    @task = Task.new(params[:task])
    @task.course = @course
    @task.save

... etc

-patrick

Last edited by patrick99e99 (2011-08-07 18:44:47)