Динамическая Rails маршрутизация на основе базы данных - PullRequest
5 голосов
/ 05 октября 2009

Я создаю CMS с различными модулями (блог, календарь и т. Д.), Используя Rails 2.3. Каждый модуль обрабатывается отдельным контроллером, и это прекрасно работает.

Единственная проблема, с которой я столкнулся, - это корневой URL. В зависимости от конфигурации, выбранной пользователем, этот URL-адрес по умолчанию должен показывать другой модуль, то есть другой контроллер, но единственный способ определить правильный контроллер - это проверить базу данных на предмет того, какой модуль «по умолчанию» должен быть показан.

На данный момент я использую специальный «корневой» контроллер, который проверяет базу данных и перенаправляет на правильный контроллер. Однако я бы предпочел, чтобы URL не менялся, а это значит, что я хочу вызвать правильный контроллер из того же запроса.

Я пытался использовать Rails Metal для получения этой информации и вручную вызывать нужный мне контроллер, но я думаю, что, возможно, я заново изобретаю колесо (определите путь запроса для выбора контроллера, управления сеансом и т. Д.).

Есть идеи? Заранее большое спасибо!

Ответы [ 2 ]

5 голосов
/ 19 октября 2009

Эту проблему можно решить с помощью некоторого промежуточного программного обеспечения Rack:

Этот код в lib/root_rewriter.rb:

module DefV
  class RootRewriter
    def initialize(app)
      @app = app
    end

    def call(env)
      if env['REQUEST_URI'] == '/' # Root is requested!
        env['REQUEST_URI'] = Page.find_by_root(true).uri # for example /blog/
      end

      @app.call(env)
    end
  end
end

Тогда в вашем config/environment.rb внизу

require 'root_rewriter'
ActionController::Dispatcher.middleware.insert_after ActiveRecord::QueryCache, DefV::RootRewriter

Это промежуточное ПО проверит, является ли запрашиваемая страница (REQUEST_URI) «/», а затем выполнит поиск фактического пути (реализация этого зависит от вас ;-)). Вы могли бы быть полезны при кэшировании этой информации где-то (Cache.fetch('root_path') { Page.find... })

Есть некоторые проблемы с проверкой REQUEST_URI, так как не все веб-серверы проходят это правильно. Для получения полной информации о реализации в Rails см. http://api.rubyonrails.org/classes/ActionController/Request.html#M000720 (Нажмите «Просмотреть исходный код»)

2 голосов
/ 01 октября 2015

В Rails 3.2 это было то, что я придумал (все еще промежуточное ПО):

class RootRewriter
  def initialize(app)
    @app = app
  end

  def call(env)
    if ['', '/'].include? env['PATH_INFO']
      default_thing = # Do your model lookup here to determine your default item
      env['PATH_INFO'] = # Assemble your new 'internal' path here (a string)
      # I found useful methods to be: ActiveModel::Naming.route_key() and to_param
    end

    @app.call(env)
  end
end

Это говорит Rails, что путь отличается от того, который был запрошен (корневой путь), поэтому ссылки на link_to_unless_current и т.п. все еще работают хорошо.

Загрузите промежуточное ПО примерно так же в инициализаторе:

MyApp::Application.config.middleware.use RootRewriter
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...