我正在使用炼油厂开发一个网站。现在,对于在炼油厂后端创建的一个特定页面,我想使用自己的控制器和视图。用户可以使用此页面设置菜单位置,标题,元信息等。此页面的URL必须与所有其他页面的URL相同。
例如,菜单结构如下:
“特定页面”的网址看起来像“locale / menu1 / menu2 / specific page”
该网站提供多种语言版本,因此我必须为所有语言创建这些路径。
目前我正在创建这样的路线:
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 :(得分:5)
我需要在Rails 4应用程序(在下面的示例中称为“ComingSoon”)中找出自己构建数据库模型的路径。我希望页面可以在后端进行编辑,并且用户友好name,存储在Page#name字段中。所以"About Us"
标题页通常会变成"about_us"
名称,这会导致"http://localhost:3000/about_us"
以下是我提出的技术:
在app / models / 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字段,即恕我直言,比使用友好插件或查找slugerized值要好得多。
将以下行添加到config / routes.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属性时重新加载路由,并且可能只是编辑现有路由而不是重新加载所有内容,如果性能证明是一个问题(目前,它不是)。