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 p开发者_开发技巧roper way to solve this problem in Rails 3?
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.
Your approach seems like the best way to me. Anything else would be more cluttered and not very standard.
精彩评论