2009-07-30 128 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