Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3 routing based on context

I am trying to implement a "context" system similar to the one used by GitHub. For example, a Post may be created belonging either to the User or one of the Companies the User belongs to depending on whether to User is in the "User" context or a context that refers to one of the Companies.

As a part of this, I'd like to be able to do routing based on the user's current context. For example, if the User is in their own context, /dashboard should route to users/show, but if they are in the context for Company with ID 35, then /dashboard should route to companies/35/dashboard.

I could route /dashboard to a special controller responsible for making such decisions, such as context#dashboard which could then do a redirect_to, but this doesn't feel quite right (perhaps because we're taking logic that the Rails routing module should be responsible for and moving it to a controller?)

What would be the proper way to solve this problem in Rails 3?

like image 215
Michelle Tilley Avatar asked Nov 05 '22 08:11

Michelle Tilley


1 Answers

I finally found a solution to my problem that I like. This will use the URLs from my original question.

First, assume a session-stored Context object that stores whether the user is in a "user" context or a "company" context. If the user is in a "company" context, then the ID of the company they're working as is in the object as well. We can get the context via a helper named get_context and we can get the currently logged-in user via current_user.

Now, we set up our routes as so:

config/routes.rb:

MyApplication::Application.routes.draw do
  get "dashboard" => "redirect", :user => "/users/show", :company => "/companies/:id/dashboard"
end

Now, app/controllers/redirect_controller.rb:

class RedirectController < ApplicationController
  def method_missing(method, *args)
    user_url    = params[:user]
    company_url = params[:company]
    context     = get_context

    case context.type
    when :user
      redirect_to user_url.gsub(":id", current_user.id.to_s)
    when :company
      redirect_to company_url.gsub(":id", context.id.to_s)
    end
  end
end

It's easy enough to keep the actual URLs for the redirect where they belong (in the routes.rb file!) and that data is passed in to a DRY controller. I can even pass in the ID of the current context object in the route.

like image 123
Michelle Tilley Avatar answered Nov 09 '22 14:11

Michelle Tilley