routes.rb is not defined correctly - ruby-on-rails

I have two controllers: Tasksadmins and Workers.
I defined two roots, but someone told me that there is a problem with it.
can someone tell me what the problem is?
TODOLIST::Application.routes.draw do
devise_for :users
resources :tasksadmins
root to: "tasksadmins#index"
resources :workers
root to: "workes#index"
end

root doesn't mean the index action of a controller. Instead, it means essentially the home page: what action gets called when I go to http://www.example.com/?
Therefore, it only makes sense to define one root: right now, you're pointing http://www.example.com/ to both tasksadmins#index and workers#index, which doesn't make much sense. Rails will just pick one of them, but that's probably not the behavior you're looking for.
I suspect you're trying to refine your resources routes, but there's no need: resources :workers already defines the route http://www.example.com/workers pointing to workers#index, so that line should be all you need for the workers.
If, however, you want http://www.example.com/ to point to the same workers listing as http://www.example.com/workers, then root 'workers#index' is exactly right.

The root method of the routing DSL allows you to define the default route for the application or a specific namespace: you can't have multiple "root" routes.
The default route for a resource (e.g. /workers) is routed to the index action of the corresponding controller (WorkersController), there is no need to specify it per controller.
If you use the root method multiple times, the last occurence will be used. Here it will be workers#index. Simplify your routes :
TODOLIST::Application.routes.draw do
root to: "workers#index"
devise_for :users
resources :tasksadmins
resources :workers
end

Related

Multiple paths for one Rails resource

Is it possible to send multiple paths to the same resource in Rails?
Example: route both '/foo-bars' and '/foo_bars' to resource :foo_bars
Maybe you'd prefer a permanent redirect instead? Browsers will cache it and possibly less maintenance problems you'll have later on (1 path = 1 resource is something rails programmers typically take for granted)
http://guides.rubyonrails.org/routing.html#redirection
get '/stories/:name', to: redirect('/articles/%{name}')
This may work:
resources :foo_bars
resources :foo_bars, path: "foo-bars", as: "foo-bars"
The as will also alias your path/url helpers, omitting it requires you to use one set of helpers (the originally defined ones).
resources :foo_bars, :foo-bars, controller: :foo_bars do
# nested
end
This (not tested) should give you multiple sets of routes pointing to the same controller.

Why does order matter in Rails routes.rb when using resources?

I receive an error when my route is listed as such:
resources :coupons
get 'coupons/redeem_coupon', to: 'coupons#redeem_coupon', as: 'redeem_coupon'
The error is:
ActiveRecord::RecordNotFound - Couldn't find Coupon with 'id'=redeem_coupon:
When I reverse the order to:
get 'coupons/redeem_coupon', to: 'coupons#redeem_coupon', as: 'redeem_coupon'
resources :coupons
It works fine. I understand that resources creates these routes
GET /coupons
GET /coupons/new
POST /coupons
GET /coupons/:id
GET /coupons/:id/edit
PATCH/PUT /coupons/:id
DELETE /coupons/:id
Is listing my custom route first, more specific or overriding the other route? Why does the order matter?
The error you're getting is because rails tries to match routes starting from the top down. If you're trying to add a custom route to an existing resource, the easier way is to do this. collection is if you want to use it on the group, member is if you want to add a custom route to an individual resource.
resources :coupons do
collection do
get 'redeem_coupon'
end
end
By listing your custom route first, you are overriding the other route. When rails gets a request, it simply starts from the top of your routes.rb file and goes with whichever route matches first.

Rails resources route with dynamic prefix instead of controller name

I have a TextsController, each Text can be of a different (fixed) type.
Let's say I have a "book" type. I want to create a resource route to show a text, and I want the route to look like this:
/book/my-book
Another type, "manual" for instance, should lead to using the following URL:
/manual/rtfm
Well, I have RTFM and I can't get it to work the way I thought it should work.
Here's what I've tried:
scope '/:text_type' do
resources :texts, only: :show
end
rake routes shows me the following route spec:
text GET /:text_type/texts/:id(.:format) texts#show
I don't get why the static 'texts' segment should be there?
So I tried including an empty path option:
scope '/:text_type', path: '' do
resources :texts, only: :show
end
Which doesn't change anything, I guess because (from source) my first argument to scope actually overrides any value given to path.
The only route setup that got me what I'm looking for is this:
scope '/:text_type' do
resources :texts, only: :show, path: ''
end
It seems to completely defeat the purpose of scope which is to "[scope] a set of routes to the given default options".
Why wouldn't any of the previous forms actually override path for my resources call?
Looks like a bug to me?
So should I file a bug report, or will you hit me hard on the head with the f* manual? ^^
First of all the scoping thing. Routes with scope are for namespacing routes, as you would do for admin areas. So the mentioned routes are generated correctly and there is no bug (and no bug report needed). You can read more details about namespacing at Controller Namespaces and Routing.
You could slug the parameters yourself by following 'Creating Vanity URLs in Rails'
or use the friendly_id gem like the Railscast advises.
Though I would stick to ids as long as I could for several reasons.

Best practice to match the 2nd level (nested) resource index action

(I am doing the exercise of online course from codeschool, the rails app from scratch part 1)
Here is my routes.rb
resources :destinations, only: :index
resources :trips do
resources :destinations
end
and the rake routes result has these two routes go to the same action:
Prefix Verb URI Pattern Controller#Action
destinations GET /destinations(.:format) destinations#index
trip_destinations GET /trips/:trip_id/destinations(.:format) destinations#index
I wish to match the trip_destinations to trip#show, i.e. redirect to /trips/:id, I have some solutions like hard code it in routes.rb or add redirection in destination#index. Which one is better? Is there a best practice to accomplish this task?
resources :trips do
resources :destinations do
member do
get 'index' => 'trips#show'
end
end
end
This will work for you, but it's based on faulty design because the response does not match the request. In other words, it's a bad route. A trip's destination index resource should respond with a trip's destination index, not the trip object itself.
The /trips/:id/destinations path should not be redirecting or rendering /trips/:id. There shouldn't be a link pointing to trips/:id/destinations in the first place, unless your application can respond with the appropriate resource.
It's very easy to get carried away with fancy routes and URL presentation. Be sure your routes make sense. It will save you loads of trouble in the future.

Rails 3 Routing - specifying an exact controller from within a namespace

I'm having a bit of a problem with route namespaces that I've not encountered before. This is actually a part of some gem development I'm doing - but i've reworked the problem to fit with a more generic rails situation.
Basically, I have a namespaced route, but I want it to direct to a generic (top-level) controller.
My controller is PublishController, which handles publishing of many different types of Models - which all conform to the same interface, but can be under different namespaces. My routes look like this:
# config/routes.rb
namespace :manage do
resources :projects do
get 'publish' => 'publish#create'
get 'unpublish' => 'publish#destroy'
end
end
The problem is that this creates the following routes:
manage_project_publish GET /manage/projects/:project_id/publish(.:format) {:controller=>"manage/publish", :action=>"create"}
manage_project_unpublish GET /manage/projects/:project_id/unpublish(.:format) {:controller=>"manage/publish", :action=>"destroy"}
Which is the routes I want, just not mapping to the correct controller. I've tried everything I can think of try and allow for the controller not to carry the namespace, but I'm stumped.
I know that I could do the following:
get 'manage/features/:feature_id/publish' => "publish#create", :as => "manage_project_publish"
which produces:
manage_project_publish GET /manage/projects/:project_id/publish(.:format) {:controller=>"publish", :action=>"create"}
but ideally, I'd prefer to use the nested declaration (for readability) - if it's even possible; which I'm starting to think it isn't.
resource takes an optional hash where you can specify the controller so
resource :projects do
would be written as
resource :projects, :controller=>:publish do
Use scope rather than namespace when you want a scoped route but not a controller within a module of the same name.
If I understand you correct, you want this:
scope :manage do
resources :projects, :only => [] do
get 'publish' => 'publish#create'
get 'unpublish' => 'publish#destroy'
end
end
to poduce these routes:
project_publish GET /projects/:project_id/publish(.:format) {:action=>"create", :controller=>"publish"}
project_unpublish GET /projects/:project_id/unpublish(.:format) {:action=>"destroy", :controller=>"publish"}
Am I understanding your need correctly? If so, this is what Ryan is explaining.
I think what you want is this:
namespace :manage, module: nil do
resources :projects do
get 'publish' => 'publish#create'
get 'unpublish' => 'publish#destroy'
end
end
This does create the named routes as you wish(manage_projects...) but still call the controller ::Publish
It's a bit late but for anyone still struggling with this, you can add a leading slash to the controller name to pull it out of any existing namespace.
concern :lockable do
resource :locks, only: [] do
post "lock" => "/locks#create"
post "unlock" => "/locks#destroy"
end
end
Now if you include that concern anywhere (either namespaced or not) you will always hit the LocksController.

Resources