2009-07-30 132 views
0

我必须分开模型:嵌套节和文章,部分has_many文章。 两人都喜欢AAA/BBB/CCC路径属性,例如:开关导轨控制器

movies # section 
movies/popular # section 
movies/popular/matrix # article 
movies/popular/matrix-reloaded # article 
... 
movies/ratings # article 
about # article 
... 

在路线我:

map.path '*path', :controller => 'path', :action => 'show' 

如何创建show动作像

def show 
    if section = Section.find_by_path!(params[:path]) 
    # run SectionsController, :show 
    elsif article = Article.find_by_path!(params[:path]) 
    # run ArticlesController, :show 
    else 
    raise ActiveRecord::RecordNotFound.new(:) 
    end 
end 

回答

1

您应该使用Rack中间件来拦截请求,然后重写适当的Rails应用程序的url。这样,你的路线文件仍然非常简单。

map.resources :section 
map.resources :articles 

在您查找与路径有关的实体和重新映射的URL简单的内部URL的中间件,让Rails的路由分派到正确的控制器,通常调用过滤器链。

更新

下面是一个使用Rails Metal组件,你提供的代码添加这种功能的一个简单的演练。我建议你考虑简化路径段的查找方式,因为你用当前代码复制了很多数据库。

$ script/generate metal path_rewriter 
     create app/metal 
     create app/metal/path_rewriter.rb 

path_rewriter.rb

# Allow the metal piece to run in isolation 
require(File.dirname(__FILE__) + "/../../config/environment") unless defined?(Rails) 

class PathRewriter 
    def self.call(env) 
    path = env["PATH_INFO"] 
    new_path = path 

    if article = Article.find_by_path(path) 
     new_path = "/articles/#{article.id}" 

    elsif section = Section.find_by_path(path) 
     new_path = "/sections/#{section.id}" 

    end 

    env["REQUEST_PATH"] = 
    env["REQUEST_URI"] = 
    env["PATH_INFO"] = new_path 

    [404, {"Content-Type" => "text/html"}, [ ]] 
    end 
end 

对于一个很好的介绍,以一般使用金属和机架,看看Ryan Bates的Railscast episode on Metalepisode on Rack

1

而不是实例其他控制器我只会根据路径是否匹配节或文章,从PathController的show动作渲染不同的模板。即

def show 
    if @section = Section.find_by_path!(params[:path]) 
    render :template => 'section/show' 
    elsif @article = Article.find_by_path!(params[:path]) 
    render :template => 'article/show' 
    else 
    # raise exception 
    end 
end 

的原因是,虽然你可以在另一个创建一个控制器的情况下,它不会工作,你想要的方式。即第二个控制器不能访问你的参数,会话等,然后调用控制器将无法访问实例变量和渲染第二个控制器中的请求。

+0

但我必须复制这些控制器中的所有过滤器,并显示所有动作 – tig 2009-07-30 15:53:37

+0

您有哪些过滤器?也许他们可以移动到一个普通的超类或mixin中,因为大概你希望它们适用于PathController以及SectionController和ArticleController。你是否曾经通过SectionController和ArticleController显示节目或动作,或者是否现在都通过PathController路由显示请求? – mikej 2009-07-30 16:15:50