2

I am building a To Do application in an attempt to get fluent with Rails. There are four levels of hierarchy in my app.

  1. User
  2. Goals (multiple goals per user)
  3. Tasks (multiple tasks per goal)
  4. Subtasks (multiple subtasks per task)

I have a working front end form for each of these that utilizes nested resources. My routes.rb has something like this

 resources :goal do
  resources :task do
    resources :subtask
  end
 end

What I would like to do now is that have all these forms right in one of the views of the user controller.

This the form that I have attempted to create :

<%= form_for @task, url: {controller: 'task', action: 'create'} do |f| %>

 <%= f.label :description %>

 <%= f.text_field :description %>

 <%= f.submit "Add Goal", class: "btn" %>

<% end %>

But I end up getting this error

No route matches {:action=>"create", :controller=>"task", :id=>"1"}

The :id=>1 corresponds to the user page I am on (http://localhost:3000/user/1)

What I understand is that there is that nowhere have I provided the goal_id for which this step is intended. No idea how to implement this.

Another thing that I have noticed is that a response to rake routes shows a lot of URI paths but nothing for POST method. It does not allow me to use a path from there in the url: in form_for because it does not match the POST method.

So my questions are :

  1. How to route a form_for that when you have nested resources?
  2. How to provide the ID of the parent resource while using form_for so that my create action is correctly routed?
Ram Iyer
  • 57
  • 1
  • 7
  • probably this would give you some idea: http://stackoverflow.com/questions/2034700/form-for-with-nested-resources – dp7 Sep 16 '16 at 08:54
  • Do a rake route and check the create task route. The user id is probably not indicated as :id. – Syl Sep 16 '16 at 09:03
  • no I have `/goal/:goal_id/task` as the create task route. Yes there is no :id in this route, I still need to provide the :goal_id somewhere and I dont know how to do that (as I mentioned in the question). – Ram Iyer Sep 16 '16 at 14:46

1 Answers1

3

It is typically bad practice to nest routes beyond two levels deep. I would change your routes to:

  resources :goal do
    resources :task 
  end

and

  resources :task do
      resources :subtask
  end

Now if you run "bundle exec rake routes" in the command line you will see all of the nested routes and their corresponding helpers. Your current issue lies with the form_for method. You need to add the resource its nested with which in this case should be:

<%= form_for [@goal,@task] do |f| %>
    blah blah
<% end %>

Lastly, @goal is also still undefined so you'll need to define it in your 'new' action in the tasks controller. This is normally done by passing the id of the goal your task will be associated with via the params hash and the "link_to" used to get to the 'new' form. Then in the new action in your tasks controller:

@goal = Goal.find(params[:goal_id]) #The parameter can be named anything
@task = Task.new

Then in your 'create' action you should have the association made:

@task = Goal.tasks.new(task_params)
if @task.save
   flash[:success] = "Woot" 
   redirect_to somewhere_awesome_path
else
  whatever
end
bkunzi01
  • 4,504
  • 1
  • 18
  • 25
  • Using `form_for [@goal,@task]`gives me the error `undefined method goal_tasks_path for #<# – Ram Iyer Sep 16 '16 at 18:53
  • thanks for the reply though, its a great answer. Just need a little bit more of your help :) – Ram Iyer Sep 16 '16 at 18:54
  • No problem. You want to define the '@goal' and '@task' inside the action that is connected to displaying the form so in this case you would define them in your User controller inside the Show action. You can then also define the path the form will submit to as you had with the "url: {controller: 'task', action: 'create'}" part. As for passing the goal_id you can add it as a hidden_field inside the form with a preset value. For example <%= f.hidden_field :goal, value: 'whatever value' %> – bkunzi01 Sep 16 '16 at 18:59