`scope` around `mount` ineffective?

2019-07-24 10:30发布

问题:

(While this discusses Blacklight engine, I believe the question is actually purely about Rails.)

I am trying to add internationalisation to my Blacklight app. To that end, I

  • wrapped everything in config/routes.rb into scope "(:locale)", locale: /en|ja/, and

  • in app/controllers/application_controller.rb I added before_action :set_locale and overrode default_url_options

as suggested by Rails i18n guide. Most things work, but there's one thing I haven't been able to figure out.

All of my application routes are correctly mapped, e.g. http://www.example.com/en/catalog/12345 correctly matches with (/:locale)/catalog/:id(.:format), and gets routed to catalog#show with {:id=>/[^\/]+(?=\.json|\.html|$|\/)/, :locale=>/en|ja/}). All of Devise's URLs are fine. Everything works... except the mount-ed Blacklight engine.

Apparently, the Blacklight engine doesn't listen to scope. rake routes shows:

Routes for Blacklight::Engine:
      search_history GET    /search_history(.:format)            search_history#index
      ....

and not (:locale)/search_history(.:format) as I would hope.

I have modified the Blacklight template so that I get a language chooser pointing to the current page in both Japanese and English, but when I navigate to search_history, url_for suddenly throws up when confronted with the :locale parameter.

Why does mount ignore scope? How do I solve my problem (engine routes also responding to :locale)?

Here's my default Blacklight-generated config/routes.rb, modified with scope:

Rails.application.routes.draw do

  scope "(:locale)", locale: /en|ja/ do
    mount Blacklight::Engine => '/'
    root to: "catalog#index"
      concern :searchable, Blacklight::Routes::Searchable.new

    resource :catalog, only: [:index], as: 'catalog', path: '/catalog', controller: 'catalog', id: /[^\/]+(?=\.json|\.html|$|\/)/ do
      concerns :searchable
    end

    devise_for :users
    concern :exportable, Blacklight::Routes::Exportable.new

    resources :solr_documents, only: [:show], path: '/catalog', controller: 'catalog', id: /[^\/]+(?=\.json|\.html|$|\/)/ do
      concerns :exportable
    end

    resources :bookmarks, id: /[^\/]+(?=\.json|\.html|$|\/)/ do
      concerns :exportable

      collection do
        delete 'clear'
      end
    end
  end
end

tl;dr: scope prefixes all of my routes, except the routes by mount. Why, and how to fix?

回答1:

It seems that Rails is indeed ignoring scope in the engine routes, but I can add a scope for the engine explicitly:

Blacklight::Engine.routes.default_scope = { path: "(:locale)", locale: /en|ja/ }
mount Blacklight::Engine => '/'

However, that still does not solve my issues (continued in link_to with parameters for an Engine route).