Override "Show" Resource Route in Rails

Ruby on Rails: How to override the 'show' route of a resource?

You have two routes which point to posts#show (you should be able to confirm this by running rake routes), and your link is using the wrong one.

When you call link_to('show', post) the URL of the link is generated by calling url_for(post) which (eventually, after passing through several other methods on the way) calls post_path(post). Since the route to posts#show that was created by your call to resources(:posts) is named post, that is the route that post_path generates.

You also currently have inconsistent routes for the show, update and destroy actions which will probably cause you problems later on.

You can fix this by changing your routes to the following:

resources :posts, :except => ['show', 'update', 'destroy']
get 'posts/:id/:slug' => 'posts#show', :as => 'post'
put 'posts/:id/:slug' => 'posts#update'
delete 'posts/:id/:slug' => 'posts#destroy'

Unfortunately you still can't use link_to('show', post) just yet, because it relies on being able to use post.to_param as the single argument needed to build a path to a post. Your custom route requires two arguments, an id and a slug. So now your link code will need to look like this:

link_to 'show', post_path(post.id, post.slug)

You can get around that problem by defining your own post_path and post_url helpers in app/helpers/posts_helper.rb:

module PostsHelper
def post_path(post, options={})
post_url(post, options.merge(:only_path => true))
end

def post_url(post, options={})
url_for(options.merge(:controller => 'posts', :action => 'show',
:id => post.id, :slug => post.slug))
end
end

Which means we're finally able to use:

link_to 'show', post

If that all seems like too much work, a common alternative is to use URLs that look more like posts/:id-:slug, in which case you can stick with the standard RESTful routes and just override the to_param method in your Post class:

def to_param
"#{id}-#{slug}"
end

You'll also need to do a little bit of work splitting up params[:id] into an ID and a slug before you can look up the relevant instance in your show, edit, update and destroy controller actions.

Override show resource route in Rails

In your routes.rb put:

get "some_resource" => "some_resource#show"

before the line

resources :some_resource

Then rails will pick up your "get" before it finds the resources... thus overriding the get /some_resource

In addition, you should specify:

resources :some_resource, :except => :index

although, as mentioned, rails won't pick it up, it is a good practice

Overriding a resource route to / (root) in Rails3: not changing the path helper?

Thank you for your answers, it helped me find the exact solution to my question:

resources :subscribers, :only => [:new, :create], :path => '', :path_names => {:new => ''}

Tested and working on Rails 3 :)

Overriding Resource Route in Rails 2

I believe routes are prioritized from top to bottom, the top one being highest priority and the bottom one the lowest. So consider switching your routes like this :

map.connect '/photos', :controller => 'photos',
:action => 'options_stuff', :conditions => {:method => :options }
map.resources :photos

Rails 5: How to overwrite route parameters for extra member route

You're duplicating your routes entries for cats, and you've provided the block for declaring the preview route on the entry missing the param name override. You need to provide the override and the block in the same route declaration.

Rails.application.routes.draw do

resources :cats, param: :name do
get :preview, on: :member
end
end

This gives you the route you want:

$ rake routes
Prefix Verb URI Pattern Controller#Action
preview_cat GET /cats/:name/preview(.:format) cats#preview

Rails 3 Routes: Override Topics#show with Posts#index

add this route

get "/topics/:topic_id" => redirect("/topics/%{topic_id}/messages")

UPD

without redirecting:

get "/topics/:id" => "topic::Messages#index"

Or, if you're using shallow:

get "/topics/:id" => "messages#index"

resources :forums, :shallow => true, :except => :show do
resources :topics, :shallow => true, :except => :show do
resources :messages
end
end

If I want to override the resource path (e.g. post_path(@post)), where do I do that?

There are two sides to routing: route generation and route matching.

The route generation, as you point out, is quite easy. Override to_param in any ActiveModel:

# In a model:
def to_param
# Use another column instead of the primary key 'id':
awesome_identifier.to_s
end

The route matching is less obvious. It is possible to specify :awesome_identifier in place of every occurrence of :id in the default resource routes. However, I have found that Rails will give you less resistance if you leave :id in your routes, and only change the logic in your controller. Note that this is a trade-off, because fundamentally the :id in your routes is not really correct.

# In a controller:
def index
@awesome_record = AwesomeModel.find_by_awesome_identifier(params[:id])
# ...
end

As you have noted, Rails has optimised a single use case: if you want the primary key to be used for quick record look-up, but still prefer a slug to be included in the URL for user-friendliness or search engine optimisation. In that case you can return a string of the form "#{id}-#{whatever}" from the to_param method, and everything after the dash will be ignored when feeding the same string back into the find method.

Rails routing: override the action name in a resource/member block

Is the following better?

resources :stories do
member do
put 'collaborator' => 'controller_name#add_collaborator'
delete 'collaborator' => 'controller_name#remove_collaborator'
end
end

You should also check your routes by launching in a terminal:

$ rake routes > routes.txt

And opening the generated routes.txt file to see what routes are generated from your routes.rb file.

Modify routes in rails

If you have taken,

resources :users

Now change this route as follows,

get '/users/edit', to: 'users#edit', as: 'users_edit'

Now in your view file where you have edit link, change the link to,

<%= link_to 'Edit', users_edit_path(:id => user.id) %>

Now this links to the edit action of users controller with an id parameter.

Now, in the users controller file,

class UsersController < ApplicationController

def edit

// params[:id] will be the ID that you sent through the view file.
@user = User.find(params[:id])

end

end

Thats it, you are done with your custom route, now the route will be users/edit instead of users/:id/edit

In routes, override scope-defined name from w/in the scope block

No, I can't think of a way to do it without moving it outside the scope block. Here's what I would put after that scope block:

get 'author/books' => 'author#my_books', as: 'my_books'


Related Topics



Leave a reply



Submit