views:

50

answers:

3

First, an example of what I'm trying to do:

  1. 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
  2. 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:

  1. An AboutsController intended to serve up semi-static pages (wish the About wasn't plural!)
  2. 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/products)

Is this possible in Rails 2.3.8?

+2  A: 

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.

njorden
Got the concept, thanks! But it may be a typo in your code (:controller should be 'about' for both?)
Zabba
Yeah, whatever view you need to render, this is the basic syntax for rendering it conditionally.
njorden
This is not my preferred method, but also the way it's done in the example is incorrect. A call to "render" will only display the view you've requested. It doesn't actually run the AboutController#index action. If the action doesn't do anything, it will work okay. But if the AboutController#index action sets variables, these won't be set and the view will fail. Redirect should be used instead.
Jaime Bellmyer
It's true, a redirect will likely keep things cleaner and cause less headaches in the long run. However, if it must be the same URL, then this should do what you need. It isn't necessarily a complete example...If you need instance variables you'll need to set them up for each case.
njorden
+1  A: 

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 :)

Matchu
That's true too. Now I'm confused as to which approach to take :)
Zabba
@Zabba: I think the answers on @njorden's answer cover it: you probably want to show things to the user on their dashboard, which likely includes some things you want to set as instance variables, so redirecting is probably cleaner overall. But it's all dependent on your application's requirements.
Matchu
+1  A: 

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.

Jaime Bellmyer