2013-08-28 33 views
1

我正在开发使用炼油厂的网站。现在,在炼油厂的后端创建一个特定的页面,我想使用我自己的控制器和视图。所有用户可以使用此页面来设置菜单位置,标题,元信息等。此页面的URL必须与所有其他页面相同。Rails运行时动态路由

因此,例如,菜单结构如下:

  • menux
  • MENU1
    • MENU2
      • 特定页面
  • menux

而对于“特定的页面”的URL看起来像“区域设置/菜单1/MENU2 /特定页面”

该网站提供多种语言,所以我必须创建这些路由所有的语言。

目前我创建的路线是这样的:

specific_page_id = 1 
Refinery::I18n.frontend_locales.each do |lang| 
    slugs = [] 
    page = Refinery::Page.find_by_path_or_id(nil, specific_page_id) 
    # get slug for page in current language 
    slugs << page.translations.select { |p| p.locale == lang }.first.slug 

    # get all slugs from parrent pages 
    while !page.parent_id.blank? 
    page = Refinery::Page.find_by_path_or_id(nil, page.parent_id) 
    slugs << page.translations.select { |p| p.locale == lang }.first.slug 
    end 

    match "/:locale/#{slugs.reverse.join("/")}" => "controller#action", :via => :get, :constraints => { :locale => /#{lang}/ } 
end 

有了这个,我越来越到指定页面的路径在每一个语言如上述。

但问题是,当用户更改页面的名称或菜单中的位置时,必须重新生成路由,但这并不经常进行。

现在我的问题是,如何在运行时更动态地执行此操作?我已阅读了一些关于约束的内容,但我不知道这是否是我需要的。

感谢您的帮助!

+0

一点儿也不缺省路由,这样|获取'照片/:id',到:'photos#show'|为你工作? – techvineet

+0

没有,因为用户可以改变照片制作成图片,然后路线将不得不像:让“图片/:身份证”,到:“照片#秀” –

+0

如果控制器一样,你会更好地转移部分到占位符的路径并使用约束。可能是'':name /:id',为:'photo#show''比较好。 – Bigxiang

回答

5

我需要弄清楚建设路线关(数据库模型自己在Rails应用4这是在下面的例子中被称为“ComingSoon”。我想,可能在后端进行编辑,并给予用户页面。友好的名称,它存储在页#名称字段,以便"About Us"标题页通常会变得"about_us"名,从而导致"http://localhost:3000/about_us"以下是我想出了技术:

创建应用程序/模型/ dynamic_router新模式.rb

class DynamicRouter 
    def self.load 
    ComingSoon::Application.routes.draw do 
     Page.all.each do |pg| 
     get "/#{pg.name}", :to => "pages#show", defaults: { id: pg.id }, as: "pages_#{pg.name}" 
     end 
    end 
    end 

    def self.reload 
    ComingSoon::Application.routes_reloader.reload! 
    end 
end 

上面的关键是我将页面的ID作为其中一个参数,因此查找仍然在Page#id字段上,即,恕我直言,比使用友好的插件或查找漫反值要好得多。

将以下行添加到您的配置/路由。RB

ComingSoon::Application.routes.draw do 

    # ... 

    DynamicRouter.load 
end 

最后,当网页被更新,我们需要重新加载路线,所以在页面模型添加after_safe回调:

class Page < ActiveRecord::Base 
    after_save :reload_routes 

    def reload_routes 
    DynamicRouter.reload 
    end 
end 

我计划进一步完善这一只重装路线如果name属性被改变,也许只需编辑现有的路由,而不是重新加载一切,如果性能被证明是一个问题(这在目前,它不是)。

+0

对于那些有兴趣,我贴到我的博客更IN-一点关于在运行时生成路由的深度:http://bit.ly/1c4Ppqc欢迎在这里或博客文章本身发表评论! –