How to find current abstract route in Rails middware
You need to pass ActionDispatch::Request
or Rack::Request
to recognize
method. Here is an example from another app:
main:0> req = Rack::Request.new("PATH_INFO" => "/customers/10", "REQUEST_METHOD" => "GET")
main:0> Rails.application.routes.router.recognize(req) { |route, params| puts params.inspect }; nil
{:controller=>"customers", :action=>"show", :id=>"10"}
=> nil
The same will work with ActionDispatch::Request
. Inside middleware, you can easily create this object:
request = ActionDispatch::Request.new(env)
And if you need more information about recognized route, you can look into that route object that is yielded to block, by recognize
method.
Update
The above solution will work for normal Rails routes, but since you only have spree engine mounted you need to use different class
request = ActionDispatch::Request.new(env)
Spree::Core::Engine.routes.router.recognize(request) { |route, params|
puts params.inspect
}
I guess the best would be find a generic solution that works with any combination of normal routes and engines, but this will work in your case.
Update #2
For more general solution you need to look at the source of Rails router, which you can find in ActionDispatch
module. Look at Routing
and Journey
modules. What I found out is that the returned route from recognize
method can be tested if this is a dispatcher or not.
request = ActionDispatch::Request.new(env)
Rails.application.routes.router.recognize(req) do |route, params|
if route.dispatcher?
# if this is a dispatcher, params should have everything you need
puts params
else
# you need to go deeper
# route.app.app will be Spree::Core::Engine
route.app.app.routes.router.recognize(request) do |route, params|
puts params.inspect
}
end
end
This approach will work in case of your app, but will not be general. For example, if you have sidekiq installed, route.app.app
will be Sidekiq::Web
so it needs to be handled in different way. Basically to have general solution you need to handle all possible mountable engines that Rails router supports.
I guess it is better to build something that will cover all your cases in current application. So the thing to remember is that when initial request is recognized, the value of route
yielded to black can be a dispatcher or not. If it is, you have normal Rails route, if not you need to recursive check.
How can I find out the current route in Rails?
To find out URI:
current_uri = request.env['PATH_INFO']
# If you are browsing http://example.com/my/test/path,
# then above line will yield current_uri as "/my/test/path"
To find out the route i.e. controller, action and params:
path = ActionController::Routing::Routes.recognize_path "/your/path/here/"
# ...or newer Rails versions:
#
path = Rails.application.routes.recognize_path('/your/path/here')
controller = path[:controller]
action = path[:action]
# You will most certainly know that params are available in 'params' hash
How to get the current route in rails
To retrieve the URLs:
# Current URL:
request.original_url
# Current relative URL:
request.request_uri
Additionally, you can check with the current_page
method whether you are in a certain route.
current_page?(my_path)
# => true / false
For Rails 4 use:
# Current URL:
request.original_url
# Current relative URL:
request.fullpath
Rails, how to get the route name from the actual request (routing reverse lookup)
IMHO you could use the code explained by KinOfCain on How can I find out the current route in Rails?
Rails.application.routes.router.recognize(request){ |route, matches, parameters| puts route.name }
The router is not storing the route recognized in any place at least I wasn't able to find it
How do I use a Rack middleware only for certain paths?
You could have MyMiddleware check the path and not pass control to the next piece of middle ware if it matches.
class MyMiddleware
def initialize app
@app = app
end
def call env
middlewary_stuff if env['PATH_INFO'] == '/foo'
@app.call env
end
def middlewary_stuff
#...
end
end
Or, you could use URLMap w/o the dslness. It would look something like this:
main_app = MainApp.new
Rack::URLMap.new '/'=>main_app, /^(foo|bar)/ => MyMiddleWare.new(main_app)
URLMap is actually pretty simple to grok.
match route using a splat. What does it do?
This is called route globbing and is explained in the Routing guide's section on route globbing:
Route globbing is a way to specify that a particular parameter should be matched to all the remaining parts of a route. For example:
get 'photos/*other', to: 'photos#unknown'
This route would match
photos/12
or/photos/long/path/to/12
, settingparams[:other]
to "12" or "long/path/to/12". The fragments prefixed with a star are called "wildcard segments".Wildcard segments can occur anywhere in a route. For example:
get 'books/*section/:title', to: 'books#show'
Rack middleware trapping stack trace
I finally found the solution to this. It turns out that the last line in what is considered my application is in the middleware. I was running the rest of the code in a local rails engine located in a components
directory. All we needed to do was create a new silencer for BacktraceCleaner
. Notice components dir is now included.
# config/initializers/backtrace_silencers.rb
Rails.backtrace_cleaner.remove_silencers!
Rails.backtrace_cleaner.add_silencer { |line| line !~ /^\/(app|config|lib|test|components)/}
If you are interested here is an issue I posted on the rails project about how to replicate this in detail. https://github.com/rails/rails/issues/22265
Rails Routes homepage setting throws Controller#index is missing a template for request formats
My View file is app/views/index.html.erb
This is the issue. Your view file should be present at app/views/foos/index.html.erb
Rails will automatically render a view that matches the name of the controller and action. Convention Over Configuration! Views are located in the app/views directory. So the index action will render app/views/foos/index.html.erb
by default.
You can read more on this official Rails page.
Related Topics
Delete Contents of Array Based on a Set of Indexes
Ruby on Rails Incompatible Library
Convert Hash Keys to Lowercase -- Ruby Beginner
How to Transpose Different Sized Ruby Arrays
How to Get the Current Test Filename from Rspec
Encryption-Decryption in Rails
Homebrew Install Ruby Keg-Only Can't Find Gem
Capistrano 3 Change Ssh_Options Inside Task
Symbol#To_Proc with Custom Methods
Add a CSS Class to <%= F.Submit %>
Rails 3.1 - Changing Default Scaffold Views and Template
Best Way to Handle Dynamic CSS in a Rails App
Possible to Use Stylesheet.Css.Erb in Rails
Integrating @Font-Face Files into Rails Asset Pipeline