Rails access request in routes.rb for dynamic rout

2019-05-18 12:30发布

问题:

Our websites should allow to show different contents related to the given url .. something like a multisite in wordpress where we have one installation and serve the content according to the url.

as it is necessary to have the routes in the correct language I want to use a "dynamic route" approach to serve the right content. My problem is now that I dont find a way how to serve the proper routes in routes.rb if they are dynamic.

How can I "access" or "pass" the request object into any method inside the routes.rb file

f.e. like this

routes.rb

  Frontend::Application.routes.draw do
    DynamicRouter.load request
  end

app/models/dynamic_router.rb

class DynamicRouter
  def self.load request
    current_site = Site.find_by_host(request.host)
    Frontend::Application.routes.draw do
      current_site.routes do |route|
        get "#{route.match}", to: "#{route.to}"
      end
    end
  end
end

this doesnt work because request is undefined in routes.rb

回答1:

A possible soluction is to create the default rules on routes.rb and add a rack middleware that can transform a path according to the domain

# routes.rb
get '/category/:id', :to => 'categories#show'

In the middleware you can transform a path like 'categoria/:id' to '/category/:id' if the domain matches '.es', before the application hits the router layer.

More on rack middleware: http://guides.rubyonrails.org/rails_on_rack.html



回答2:

To answer your question: How can I "access" or "pass" the request object into any method inside the routes.rb file Obtain it as ENV object from rack middleware.See code below

# lib/dynamicrouterrequest.rb
require 'rack'
class DynamicRouterRequest
  def initialize(app)
    @app = app
  end
  def call(env)
    request=Rack::Request.new(env)
    ENV["OBJ_REQUEST"]=request.inspect.to_s
    @app.call(env)
  end
end

Grab it again in routes

# routes.rb
Frontend::Application.routes.draw do
  request=ENV["OBJ_REQUEST"]
  DynamicRouter.load request
end