I'm building a CMS with various modules (blog, calendar, etc.) using Rails 2.3. Each module is handled by a different controller and that works just fine.
The only problem I have is with the root URL. Depending on the configuration chosen by the user, this default URL should show a different module i.e. a different controller, but the only way I have to determine the correct controller is by checking the database for what "default" module is to be shown.
For the moment I'm using a specific "root" controller which checks the database and redirects to the correct controller. However I'd prefer the URL not to be changed, which means I want to invoke the correct controller from the very same request.
I've tried using Rails Metal to fetch this info and manually calling the controller I want but I'm thinking I may be reinventing the wheel (identify the request path to choose the controller, manage session, etc.).
Any idea? Thanks a lot in advance!
Rails RESTful Design which creates seven routes all mapping to the user controller. Rails also allows you to define multiple resources in one line.
rake routes will list all of your defined routes, which is useful for tracking down routing problems in your app, or giving you a good overview of the URLs in an app you're trying to get familiar with.
Rails routing is a two-way piece of machinery – rather as if you could turn trees into paper, and then turn paper back into trees. Specifically, it both connects incoming HTTP requests to the code in your application's controllers, and helps you generate URLs without having to hard-code them as strings.
Difference between singular resource and resources in Rails routes. So far, we have been using resources to declare a resource. Rails also lets us declare a singular version of it using resource. Rails recommends us to use singular resource when we do not have an identifier.
This problem can be solved with some Rack middleware:
This code in lib/root_rewriter.rb
:
module DefV
class RootRewriter
def initialize(app)
@app = app
end
def call(env)
if env['REQUEST_URI'] == '/' # Root is requested!
env['REQUEST_URI'] = Page.find_by_root(true).uri # for example /blog/
end
@app.call(env)
end
end
end
Then in your config/environment.rb
at the bottom
require 'root_rewriter'
ActionController::Dispatcher.middleware.insert_after ActiveRecord::QueryCache, DefV::RootRewriter
This middleware will check if the requested page (REQUEST_URI
) is '/' and then do a lookup for the actual path (Implementation to this is up to you ;-)). You might do good on caching this info somewhere (Cache.fetch('root_path') { Page.find... }
)
There are some problems with checking REQUEST_URI
, since not all webservers pass this correctly. For the whole implementation detail in Rails see http://api.rubyonrails.org/classes/ActionController/Request.html#M000720 (Click "View source")
In Rails 3.2 this was what I came up with (still a middleware):
class RootRewriter
def initialize(app)
@app = app
end
def call(env)
if ['', '/'].include? env['PATH_INFO']
default_thing = # Do your model lookup here to determine your default item
env['PATH_INFO'] = # Assemble your new 'internal' path here (a string)
# I found useful methods to be: ActiveModel::Naming.route_key() and to_param
end
@app.call(env)
end
end
This tells Rails that the path is different from what was requested (the root path) so references to link_to_unless_current
and the like still work well.
Load the middleware in like so in an initialiser:
MyApp::Application.config.middleware.use RootRewriter
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With