Override "show" route of a resource - ruby-on-rails-4

How to make the second route work?
resources :users, only: [:edit, :update]
get ':id', :to => 'users#show', :as =>'user'
Rails gives error because of the second line:
Invalid route name, already in use: 'user' You may have defined two routes with the same name using the `:as` option, or you may be overriding a route already defined by a resource with the same naming. For the latter, you can restrict the routes created with `resources` as explained here: http://guides.rubyonrails.org/routing.html#restricting-the-routes-created

(Expanding my comment for reference of future viewers.)
Switching the order of the routes will change the precedence, giving the get route preference to the RESTful routes.
From the documentation in a new config/routes.rb:
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".

Related

generated path does not match custom route?

(Rails 4.2)
I have a miss-match of routes that's in the routes.rb file vs the generated from my page. What is it I am doing wrong?
This is the raked route I want to access :
see_hint_deck_card_tracker GET /decks/:deck_id/cards/:card_id/trackers/:id/see_hint(.:format) trackers#see_hint
I am actually taken to what I think is the correct url, but it tells me I don't have a route for this page:
http://localhost:3000/decks/9/cards/2/trackers/1/see_hint
I have the following routes:
resources :decks do
resources :cards do
resources :trackers do
member do
get 'see_hint'
end
end
end
end
app/controllers/tracker_controller.rb :
class TrackerController < ApplicationController
def show_hint
puts 'we found this'
end
end
inside my /decks/:id/cards/:id/show I have this link_to: (get_tracker, calls for a helper method to get the correct tracker)
<%= link_to "Reveal Hint", see_hint_deck_card_tracker_path(#card.deck, #card, get_tracker), id: "reveal_hint_button" %>
I think your error message is probably telling you you don't have a Controller for that route, not that the Route is missing. This is because you're using the plural resources in your routes.rb, but your controller name is singular:
# Your Code:
resources :trackers
controller TrackerController
# Expected Code:
resources :trackers
controller TrackersController
^^^
You'll also want to make sure your controller is available at app/controllers/trackers_controller.rb (note the plurality).

Customize resource routing in Rails 4

think of the resource routing of a photo-class for example.
If I this to my routes.rb I will get following routes:
resources :photos
# GET '/photos/', :to => 'photos#index'
# GET '/photos/:photo_id/, :to => 'photos#show'
# and so on and so on
Now what I want is to replace the word /photos in all the routes with a simple /p so that I can get a short URL like /p/1 for the first photo. Is there a way to simply alter the resource-line or do I have to manually add each route?
This will make all your routes via :photos through p
resources :p, :controller => "photos"
To be more concise and avoid the issue with p_id, you could do it like this :
resources :photos, path: 'p'
This way, you benefits from the readibility on your end (it will generate helpers like edit_photo_path, you will access variables as photo_id in case of a nested route and such) and generate the named URLs you do want.

Ruby on rails - removing routes created by resource

I have the following in my routes file
resources :users do
resource :question
end
which creates a /users/:user_id/question route to question#show among other ones. However instead of a URL which has user id in it to show every question the particular user created, I want a URL to show details of one specific question. Something like /question/:id
So to do this I added the line below to my routes file
resources :questions, param: :question_id
which generated a list of routes
questions_path GET /questions(.:format) questions#index
POST /questions(.:format) questions#create
new_question_path GET /questions/new(.:format) questions#new
edit_question_path GET /questions/:id/edit(.:format) questions#edit
question_path GET /questions/:id(.:format) questions#show
PATCH /questions/:id(.:format) questions#update
PUT /questions/:id(.:format) questions#update
DELETE /questions/:id(.:format)
This list produces the /questions/:id path but unfortunately with the same questions#show connection which collides with the previous one. So I removed the "resources :questions, param: :question" and added the following
get 'questions/:id', :to => 'questions#show_question'
This produces the appropriate route but for some reason doesn't get rid of routes created from "resources :questions, param: :question" even after restarting the server. So every time i visit /question/:id it's going to question#show instead of question#show_question
How do i get rid of the effect of "resources :questions, param: :question" even after having removed it from the routes.rb file?
I would remove the route get 'questions/:id', :to => 'questions#show_question'
and use shallow routes instead
resources :users do
resources :questions, shallow: true
end
And then your url_helper should be
<td><%= link_to 'Show', question_path(question) %></td>
This allows URLs for resources that otherwise would be deeply nested such as a comment on a blog post like /users/a-long-permalink/comments/1234 to be shortened to just /comments/1234.
More info on shallow routes here http://edgeguides.rubyonrails.org/routing.html

Rails 4 - how do I add an index route for a nested resource, in order to list all items independent of parent resource

I've got a nested resource Bar that belongs to Foo. I can successfully list all Bar objects that belong to any given Foo. But I also want to be able to generate a view with all Bar items listed together, from whatever Foo object they belong to.
The model structure is:
# app/models/foo.rb
class Foo < ActiveRecord
has_many :bars
end
# app/models/bar.rb
class Bar < ActiveRecord
belongs_to :foo
end
The routing is defined as:
# config/routes.rb
resources :foos do
resources :bars
end
I get the expected routes from this configuration:
foo_bars GET /foos/:foo_id/bars(.:format) bars#index
POST /foos/:foo_id/bars(.:format) bars#create
new_foo_bar GET /foos/:foo_id/bars/new(.:format) bars#new
edit_bar GET /bars/:id/edit(.:format) bars#edit
bar GET /bars/:id(.:format) bars#show
PATCH /bars/:id(.:format) bars#update
PUT /bars/:id(.:format) bars#update
DELETE /bars/:id(.:format) bars#destroy
foos GET /foos(.:format) foos#index
POST /foos(.:format) foos#create
new_foo GET /foos/new(.:format) foos#new
edit_foo GET /foos/:id/edit(.:format) foos#edit
foo GET /foos/:id(.:format) foos#show
PATCH /foos/:id(.:format) foos#update
PUT /foos/:id(.:format) foos#update
DELETE /foos/:id(.:format) foos#destroy
What I need is to generate a route for bars#index that isn't scoped within the context of foo. In other words, I essentially want:
bars GET /bars(.:format) bars#index
I've tried using the shallow option, thus:
# config/routes.rb
resources :foos, shallow: true do
resources :bars
end
However, this doesn't support the :index action, per the documentation.
What's the best way to do this? There's a helpful Stack Overflow discussion here, using a before_filter to determine scope -- but it's from 2009. Appreciate any specific guidance on how to set up both the controller and the config/routes.rb file appropriately!
If you want to keep the scoped index method foo_bars and a separate bars route/view:
Create a custom route in routes.rb:
get 'bars' => 'bars#index', as: :bars
Set up your index method in your bars controller as described in your link or simply:
def index
if params[:foo_id]
#bars = Foo.find(params[:foo_id]).bars
else
#bars = Bar.all
end
end
Then create a bars view directory (if you don't have one) and index.html.erb.
If you don't want to keep the scoped index method foo_bars:
Create a custom route in routes.rb:
get 'bars' => 'bars#index', as: :bars
Edit your existing routes to exclude the nested index:
resources :foos do
resources :bars, except: :index
end
Then the bars controller could just be:
def index
#bars = Bar.all
end
Then create a bars view directory (if you don't have one) and index.html.erb.

Rails 4 renaming route for "create" action

# routes.rb
resource: :users, only: :create, path_names: { create: 'register' }
Following the routing guide at guides.rubyonrails.org, this line is expected to replace /users with /users/register, but the path_names argument seems to have no effect whatsoever. What am I doing wrong?
EDIT:
Interesting that it only applies to new and edit. In any case, this is the work around I used
resource :users, only: :nothing do
post "register", to: :create
end
Done this way to make it slightly easier to enable more actions for users in the future
From rails guide:
The :path_names option lets you override the automatically-generated
"new" and "edit" segments in paths
It seems that you can't rename the create action.