Rails运行时的动态路由 [英] Dynamic routes on runtime in Rails

查看:132
本文介绍了Rails运行时的动态路由的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用精炼厂开发一个站点。现在,对于在炼油厂后端中创建的一个特定页面,我想使用自己的控制器和视图。用户对该页面所做的全部工作就是设置菜单位置,标题,元信息等。该页面的URL必须与所有其他页面相同。

I'm developing a site using refinery. Now for one specific page that is created in the back-end of refinery, i want to use my own controller and views. All the User can do with this page is to set the menu-position, title, meta-info etc. The URL for this page has to look the same as all the other pages.

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

So for example, the menu structure looks like:


  • menux

  • menu1

    • 菜单2

      • 特定页面

      特定页面的网址类似于 locale / menu1 / menu2 /特定页面

      And the URL for "specific page" looks like "locale/menu1/menu2/specific page"

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

      The site is available in multiple languages, so i have to create these routes for all languages.

      当前我正在创建这样的路线:

      Currently i'm creating the routes like this:

      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
      

      有了这个,我得到了一条路线

      With this, i'm getting a route to the specified page in every language like described above.

      但是问题是,当用户更改页面名称或菜单中的位置时,路线具有再次生成,这种情况不会经常发生。

      But the problem is, when the user changes the name of the page or the position in the menu, the routes have to be generated again, which isn't done too often.

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

      Now my question is, how can i do this more dynamically on run-time? I've read a bit about constraints but i don't know if this is what i need.

      感谢您的帮助!

      推荐答案

      我需要自己在Rails 4应用程序(在下面的示例中称为 ComingSoon)中根据数据库模型构建路由。可以在后端进行编辑,并获得易于使用的名称,该名称存储在Page#name字段中,因此关于我们 标题页通常变为 about_us 名称,它导致 http:// localhost:3000 / about_us 以下是我提出的技术

      I needed to figure out building routes off a database model myself in a Rails 4 application (which is called "ComingSoon" in the examples below. I wanted pages that could be edited on the back-end and given a user-friendly name, which is stored in the Page#name field. So "About Us" titled page typically becomes "about_us" name, which leads to "http://localhost:3000/about_us" The following is the technique I came up with:

      在app / models / dynamic_router.rb中创建新模型

      Create a new model in 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字段上,即IMHO,比使用友好的插件或对模糊值进行查找要好得多。

      The key above is that I pass the page's id as one of the parameters, so look up is still on the Page#id field, which is, IMHO, a lot better than using the friendly plugin or lookups on slugerized values.

      将以下行添加到config / routes.rb

      Add the following line to your config/routes.rb

      ComingSoon::Application.routes.draw do
      
        # ...
      
        DynamicRouter.load
      end
      

      最后,当Page更新后,我们需要重新加载路由,因此在Page模型上添加一个after_safe回调:

      Finally, when the Page is updated, we need to reload the routes, so add an after_safe callback on the Page model:

      class Page < ActiveRecord::Base
        after_save :reload_routes
      
        def reload_routes
          DynamicRouter.reload
        end
      end
      

      我计划进一步完善此方法,以便仅在更改name属性时重新加载路由,并且也许只是编辑现有路由,而不是在性能证明是合理的情况下重新加载所有路由问题(目前还没有)。

      I plan to refine this further to only reload routes if the name attribute is changed and perhaps simply edit the existing route rather than reloading everything if performance proves to be an issue (which at the moment, its not).

      这篇关于Rails运行时的动态路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆