Rails: Displaying different view for the same URL?
First, an example of what I'm trying to do:
- If you go to http://www.meetup.com and you are not signed in, you see a page that shows 'Do something • Learn something...' etc. which is a public page
- But when you are logged in, that same page (URL) shows 'Welcome, xxx...Whats happening...' etc. which is specific to you.That is what I'm trying to do in my app as well.
How to go about this in Rails 2.3.8?
So far, I have:
- An
AboutsController
intended to serve up semi-static pages (wish the About wasn't plural!) - Root route is
map.root => :controller => "about"
.
Now, when a non-logged-in-user goes to the http://www.abc.com
, he would get the contents of the view about/index
. So far so good.
But, when a user is logged in, I want that the products/index
view should be displayed for the same URL i.e. http://www.example.com
URL (and not http://www.example.com/开发者_Python百科products
)
Is this possible in Rails 2.3.8?
The cleanest way to do this is with something called a before_filter. It's a command at the top of your controller that is called before any action in that controller (that you want). Normally, you'll want to do the same check for more than one action in the controller, so it doesn't make sense to put that check into each action directly.
Let's say you have a Comments controller, and you want the edit, update, and destroy actions to be something only a logged in user can do. This is very common. Let's look at an example. For the sake of brevity I won't spell out all the controller actions, just the unique stuff:
class CommentsController < ApplicationController
before_filter :user_logged_in?, :only => [:edit, :update, :destroy]
# all your actions would go here - index, show, etc #
protected
def user_logged_in?
redirect_to dashboard_path unless current_user
end
end
In the example above, the user_logged_in?
method is going to run before the edit, update, or destroy actions are run. If a render or redirect is called inside that method, rails will stop short and never run the action That's why it's called a filter. Instead will honor the render or redirect request given.
The current_user
method is a common helper that most user authentication plugins give you, which is usually nil if there is no current user. So our filter method is telling rails to redirect to a certain path, unless the user is logged in.
This is the de facto rails way to handle something like this. Very good question.
It's certainly possible. You can render whichever views you need conditionally like this:
def index
if current_user
render :action => 'products', :controller => 'index'
else
render :action => 'index', :controller => 'about'
end
end
Assuming that you're authenticating with Authlogic, Devise. Whatever logic you use to determine if a user is logged in would go into the conditional.
I've seen a lot of websites handle this with a redirect to, say, /dashboard
, to keep their application as clean internally as possible. No need to get too worked up about it still being the root URL, though it's distinctly possible, as the other solutions indicate :)
精彩评论