2009-10-05 62 views
5

我正在使用Rails 2.3构建包含各种模块(博客,日历等)的CMS。每个模块由不同的控制器处理,并且工作得很好。基于数据库的动态导轨路由

我唯一的问题是根URL。根据用户选择的配置,这个默认的URL应该显示一个不同的模块,即不同的控制器,但唯一的方法是确定正确的控制器是通过检查数据库来查看“默认”模块的显示内容。

目前,我正在使用特定的“根”控制器来检查数据库,并将重定向到到正确的控制器。不过,我宁愿URL不要改变,这意味着我想从相同的请求调用正确的控制器。

我试过使用Rails Metal来获取这些信息并手动调用我想要的控制器,但我想我可能会重新发明轮子(确定请求路径来选择控制器,管理会话等)。

有什么想法?提前感谢!

这段代码在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 
config/environment.rb

然后在底部

require 'root_rewriter' 
ActionController::Dispatcher.middleware.insert_after ActiveRecord::QueryCache, DefV::RootRewriter 

这个中间件将检查

回答

5

这个问题可以通过一些Rack中间件来解决请求页面(REQUEST_URI)为'/',然后查找实际路径(执行此操作取决于您;-))。你可能会在缓存这个信息的地方做得很好(Cache.fetch('root_path') { Page.find... }

检查REQUEST_URI有一些问题,因为并不是所有的网络服务器都能正确传递这个信息。对于Rails的整个实现细节看http://api.rubyonrails.org/classes/ActionController/Request.html#M000720(点击“查看源文件”)

+0

是的,这个作品!这或多或少是我已经试图做的,但直到现在还没有成功。谢谢你! – 2009-10-20 09:14:35

2

在Rails 3.2,这是什么,我想出了(还是中间件):

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 

这告诉Rails该路径不同于所请求的(根路径),所以引用link_to_unless_current等仍然工作良好。

加载了中间件,像这样在初始化器:

MyApp::Application.config.middleware.use RootRewriter