0

As rake routes gives the exact route I visited, the page shows
Routing Error uninitialized constant TasksController Did you mean? AppsController

In routes.rb I wrote

  resources :users do 
    resources :tasks do
      collection do
        post 'tasks-info', to: 'users/tasks#tasks_info', format: 'json'
      end
    end
  end

And the tasks_controller.rb is under app/controllers/users folder

def show
end

show.html.slim is under app/views/users/tasks foler
The url I visited is http://localhost:3000/users/1/tasks/1 with rake routes including
user_task_path GET /users/:user_id/tasks/:id(.:format) tasks#show

I really don't know where the error comes from, any help is truly appreciated!

Updated: Problem solved and please refer to the comments below if you have the same issue here(I have summarized based on my own understanding, not sure whether it's exactly correct though)! Or see the answers below as engineersmnky's and Scott's answers should both work.

cweih
  • 125
  • 1
  • 9
  • Is your `TasksController` in the appropriate namespace? Its not just the file location (afaik), but also the content of the file needs to be in the `Users` namespace. Please try that and get back. – Vijay Raghavan Aravamudhan Jul 29 '21 at 03:44
  • 1
    You should not have tasks_controller under app/controllers/users because "users" is not a namespace. More info here, https://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing – razvans Jul 29 '21 at 06:18
  • @VijayRaghavanAravamudhan Yes, I did use `class Users::TasksController < ApplicationController ` – cweih Jul 29 '21 at 08:19
  • @razvans However, my self-defined action of tasks wouldn't work unless I put tasks_controller.rb under a users folder. What should I do to make both self-defined action and auto-generated action work? – cweih Jul 29 '21 at 08:22
  • 1
    @razvans oh, I separated the routes of self-defined actions from the nested resouces, and it works. Thank you for your help! – cweih Jul 29 '21 at 09:06
  • @hcww I appreciate the issue is resolved now, but: *"However, my self-defined action of tasks wouldn't work unless I put tasks_controller.rb under a users folder."* --- Nobody can help with an issue like this unless you **show us the code**. Otherwise, we're completely guessing in the dark about what you may or may not have written, and how you may or may not be able to fix it. – Tom Lord Jul 29 '21 at 11:15
  • @TomLord Thanks for pointing that out, as others might come across the same problems. Actually there are several solutions and by now all the answers are helpful. In my understanding, basically we can choose to put custom method inside the nested rescources with task_controller outside the users folder as well as `TasksController < ApplicationController` (without `Users::`) and do as Scott suggested. Or, we can remain the controller inside and do as engineersmnky said. And of course we can also just write everything in routes by ourselves rather than using resources. – cweih Jul 30 '21 at 02:14
  • @TomLord My code now which works ok is `resources :users do resources :tasks do end end post 'create-task', to: 'tasks#create', format: 'json' post '/users/:user_id/tasks/tasks-info', to: 'tasks#tasks_info', format: 'json'` And the controller is moved outside the users folder. However, it may not very beautiful, as I will refactor them later. – cweih Jul 30 '21 at 02:19

3 Answers3

2

The key is what rails routes is telling you:

user_task_path  GET /users/:user_id/tasks/:id(.:format)  tasks#show

That last section tells you that it’s looking for the show method in the tasks controller – that is, TasksController at the top level of the controller hierarchy.

So rather than placing TasksController at app/controllers/users/tasks_controller.rb, you need to place it at app/controllers/tasks_controller.rb.

The “nesting” of the controller is handled by the params object containing both :user_id and :id when TasksController#show is called.

ScottM
  • 7,108
  • 1
  • 25
  • 42
  • I got it, thanks! But how should I write routers for my self-defined action in routes.rb with nested resources? – cweih Jul 29 '21 at 08:33
  • I tried to write outside the nested resouces do, and it works fine, i wonder whether it is the correct way to do it? – cweih Jul 29 '21 at 08:49
  • Your nested custom method should define itself a path, but you're overriding it with the `to:` parameter. I'd remove that, run `rails routes` to see what it's creating for you and go from there. – ScottM Jul 29 '21 at 10:15
1

Your issue is that resources :tasks infers TasksController but you want Users::TasksController to handle these actions.

Rails provides a method for handling this type of routing ActionDispatch::Routing::Mapper::Scoping#scope

To implement this all you have to do is add another level to your structure using the scope method like so:

  resources :users do 
    scope module: 'users' do 
      resources :tasks do
        collection do
          post 'tasks-info', to: 'users/tasks#tasks_info', format: 'json'
        end
      end
    end
  end

Now all the nested routes to the user tasks will go to Users::TasksController because we specified that Task is in the Users module. Your route in question will now look like this (in rails routes output):

user_task_path  GET /users/:user_id/tasks/:id(.:format)  users/tasks#show
engineersmnky
  • 25,495
  • 2
  • 36
  • 52
  • Thanks sooo much and this should also be an answer! Feel so pity as only one answer can be accepted. – cweih Jul 30 '21 at 02:22
  • @hcww No pity necessary. If this answer helped in anyway you can upvote it or maybe it will help someone else that stumbles across the question in the future (that's what SO is all about) – engineersmnky Jul 30 '21 at 13:25
0

I assume users is folder where you are storing your tasks controller in that scenario you are supposed to use different key rather than using resources. There can be only one resource at a time we can not not resources inside another resource. Technically it indicates we are having controller inside a controller which is not possible.

namespace :users do
  resources :tasks do
    collection do
      post 'tasks-info', to: 'users/tasks#tasks_info', format: 'json'
    end
  end
end
Yarrabhumi
  • 36
  • 6
  • 1
    Thanks for answering, but it is ok to use nested resources, please refer to the answers above if you want to know how to solve the problem.:) – cweih Jul 30 '21 at 07:30