Reputation: 4940
Let's say we have the following pages clip/show/111 image/show/222 sound/show/333 where 111,222 and 333 are the IDs for different contributions
I developed a new controller called "show" that will detect ID and redirect to the right controller show/show/111 will redirect to clip/show/111 and so on
what I want is to render the page clip/show/111 without redirecting, meaning that the URL on the browser will still show "show/show/111" but in fact render the "clip/show/111"
How could I do that?
Thanks all Wa'el
Upvotes: 2
Views: 12538
Reputation: 102250
What you're doing here doesn't actually make any sense and you really just need to think about the problem differently.
In Rails flavored REST the member routes for a collection are:
/clips/123
/images/123
When a GET
request is send this corresponds to the controllers show
action. Adding show
to the path is totally redundant as that is derived from the HTTP verb.
Which resource the controller actually renders is completely up to you as the programmer. Your routes are the external API your application provides while your controllers, models and views are the internal implementation details.
It's just a convention that the route and controller is named after the plural version model of the model that stores the data and that the view can be found in a folder matching the name of the controller.
So for example there is nothing preventing you from doing:
class ImagesController < ApplicationController
# GET /pictures/1
# GET /images/1
def show
# The model name is different
@image = Picture.find(params[:id])
end
end
Or rendering a totally different view:
class ImagesController < ApplicationController
# GET /images/1
def show
@image = Image.find(params[:id])
render 'media/generic', locals: { media: @image }
end
end
Or writing a "clever" generic controller that renders a bunch of different things.
get '/images/:id', to: 'media#show'
get '/pictures/:id', to: 'media#show'
class MediaController < ApplicationController
# GET /images/1
# GET /pictures/1
def show
@media = model.find(params[:id])
end
private
# Uses the request path to guess what model we want to use
# this is overly clever and in most cases it would just be better
# to write two different controllers that just do one thing.
def model
# extract the first part of the request path
model_name = request.route_uri_pattern.match(/\A\/(\w*)\//)[1]
# Get a class matching it like - Image or Picture
model_name.classify.constantize
end
end
You should just know why the convention is there before you break it instead of just making everything up as you go along as that's not a very productive approach (and is a huge red flag).
I developed a new controller called "show"
Please don't. Unless you're actually using the noun show (as in a TV show) it's a horrible name. Almost every controller in Rails shows something so using the most generic name imaginable will just create confusion.
Name your controller after what the represent and not the verbs of what they do as almost all controllers do the same things which is CRUD'ing resources.
Upvotes: 0
Reputation: 10368
It sounds like what you're really trying to do is make aliases for some of your routes, so you can access the same functionality from different URL structures. If that is the case, creating an entire controller that delegates all of its work to another controller would be a code smell (feature envy).
What you probably want to do is define some extra routes for "show/" that simply re-use the same Clip controller. This would be accomplished by simply doing the following:
# routes.rb
# ...
# For Rails 2
map.resources "show", :controller => "clip"
# For Rails 3
resources "show", :controller => "clip"
Upvotes: 1