ChristopherW
ChristopherW

Reputation: 1063

How to change URL after route match in Ruby on Rails

I have been programming in Ruby on Rails for a while now, but never really dug deep into routing until recently. After reading a fair amount of documentation and googling, I haven't been able to answer this question.

How do you change a URL after a route is matched? To better explain this, let me set a scenario I'm trying to solve. The root of my website while testing is localhost:3000. My login page is localhost:3000/login. Once logged in though, I want the URL to read localhost:3000 again with no extension. The actual page name is dashboard and my route is as follows currently.

get 'dashboard' => 'user#dashboard'

This only matches when the URL is localhost:3000/dashboard, but I wan't to have cleaner URL like a lot of sites have. How is this achieved with Ruby On Rails? I want to avoid a javascript solutions or anything that is a workaround.

Any help or tips is greatly appreciated. Many thanks in advance.

Upvotes: 1

Views: 1974

Answers (2)

femmestem
femmestem

Reputation: 621

I've provided the solution below, but I agree with max that your wanting to make a RESTful URL less meaningful is backwards. You should strive to alias a URL to make it more meaningful (e.g. from site.com/posts/34239482069472/ to site.com/posts/my-post-title).

The URL that appears in the address bar is an instruction to an app. When a user puts "site.com/dashboard" into the address bar, they're instructing the app to make an HTTP request get 'dashboard'. The Controller#action is a set of instructions the app executes when it receives that request. If you're following Rails naming convention then Users#dashboard will retrieve data and then by default render the view template at views/users/dashboard.html.erb. Understand this: you're not changing the URL for a given view, you're changing which view template is rendered by the Controller#action that is set for that url.

This means the Controller#action for your root_url (i.e. your root to: 'controller#action' in config/routes.rb) should render one view template if user is logged in and a different view template if a user is not logged in. Assuming root to: welcome#index, your controller action would look something like this:

app/controllers/welcome_controller.rb

def index
  # db queries, logic, set @variables

  if session[:user_id]
    render "users/dashboard" # app/views/users/dashboard.html.erb
  else
    render "index" # app/views/welcome/index.html.erb
  end
end

Note that if the view template you want to render corresponds to the controller, e.g. users_controller.rb action is rendering a view in views/users, then you only need to give the view name, otherwise you need to give a path (relative to app/views).

Upvotes: 1

max
max

Reputation: 102154

Why? /dashboard is a proper RESTful definition of a resource. In REST a route should have the same response independent of state. So having a radically different root page for a logged in user violates REST.

Also your users may want to access the index page as well the dashboard and you would be denying them that possibility.

These kind of URL micro-optimizations do not warrant hacking a bunch of state into your routes definitions.

Upvotes: 0

Related Questions