大佬教程收集整理的这篇文章主要介绍了ruby-on-rails – 如何在Rails middware中找到当前的抽象路由,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
狂欢版:’3.1.1′
TlDr:
如何在Rails 4应用程序的中间件中获取路径as / api / products /:id或控制器以及该路由的操作.
细节:
我在rails应用程序中添加了一个类似于gem scout_statsd_rack的中间件.这会将以下middleware添加到rails应用程序以通过statsd发送指标:
def call(env) (status,headers,body),response_time = call_with_timing(env) statsd.timing("#{env['requEST_PATH']}.response",response_timE) statsd.increment("#{env['requEST_PATH']}.response_codes.#{status.to_s.gsub(/\d{2}$/,'xx')}") # Rack response [status,body] rescue Exception => exception statsd.increment("#{env['requEST_PATH']}.response_codes.5xx") raise end def call_with_timing(env) start = Time.now result = @app.call(env) [result,((Time.now - start) * 1000).round] end
我想要的是在中间件中找到当前路由,以便我可以发送特定于每个路由的度量.
我尝试了描述here的方法,它告诉env [‘PATH_INFO’]可以提供路径,但是它提供了这样的URL参数:/ api / products / 4但我想要的是/ api / products /:id as我的目的是跟踪/ api / products /:id API的性能.
env [‘requEST_PATH’]和env [‘requEST_URI’]也给出相同的响应.
Rails.application.routes.router.recognize({"path_info" => env['PATH_INFO']})
或者像这样
Rails.application.routes.router.recognize(env['PATH_INFO'])
但它给出了以下错误:
这个answer讨论了request.original_url,但是我如何访问变量请求,我认为它应该与env相同但不能从中获取路由.
编辑#1
您可以看到示例仓库here,其中包含rails中间件here的代码,可以按照README中的说明完成此设置,并且可以命中此API:http:// localhost:3000 / api / v1 / products / 1.
编辑#2
def call(env) (status,response_time = call_with_timing(env) request = ActionDispatch::request.new(env) request = Rack::request.new("PATH_INFO" => env['requEST_PATH'],"requEST_METHOD" => env["requEST_METHOD"]) Rails.application.routes.router.recognize(request) { |route,params| puts "I am here" puts params.inspect puts route.inspect }
但我得到了以下回应:
I am here {} #<ActionDispatch::Journey::route:0x007fa1833ac628 @name="spree",@app=#<ActionDispatch::routIng::Mapper::ConsTraints:0x007fa1833ace70 @dispatcher=false,@app=Spree::Core::ENGIne,@consTraints=[]>,@path=#<ActionDispatch::Journey::Path::Pattern:0x007fa1833acc90 @spec=#<ActionDispatch::Journey::Nodes::Slash:0x007fa1833ad230 @left="/",@memo=nil>,@requirements={},@separators="/.?",@anchored=false,@names=[],@optional_names=[],@required_names=[],@re=/\A\//,@offsets=[0]>,@consTraints={:required_defaults=>[]},@defaults={},@required_defaults=nil,@required_parts=[],@parts=[],@decorated_ast=nil,@precedence=1,@path_formatter=#<ActionDispatch::Journey::Format:0x007fa1833ac588 @parts=["/"],@children=[],@parameters=[]>>
我也推动了这些变化here.
这同样适用于ActionDispatch :: request.在中间件中,您可以轻松创建此对象:
request = ActionDispatch::request.new(env)
如果您需要有关已识别路径的更多信息,可以通过识别方法查看要阻止的路径对象.
更新
上面的解决方案适用于普通的Rails路由,但由于你只安装了狂欢引擎,你需要使用不同的类
request = ActionDispatch::request.new(env) Spree::Core::ENGIne.routes.router.recognize(request) { |route,params| puts params.inspect }
我想最好的是找到适用于普通路由和引擎的任意组合的通用解决方案,但这将适用于您的情况.
更新#2
有关更一般的解决方案,您需要查看Rails路由器的源代码,您可以在ActionDispatch模块中找到它.查看路由和旅程模块.我发现如果这是一个调度员,可以测试来自识别方法的返回路由.
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
这种方法适用于您的应用,但不一般.例如,如果你安装了sidekiq,那么route.app.app将是Sidekiq :: Web,因此需要以不同的方式处理它.基本上要有一般解决方案,您需要处理Rails路由器支持的所有可安装引擎.
我想最好能够构建一些能够涵盖当前应用中所有情况的东西.所以要记住的是,当识别出初始请求时,产生黑色的路由值可以是调度员.如果是,你有正常的Rails路由,如果不是,你需要递归检查.
以上是大佬教程为你收集整理的ruby-on-rails – 如何在Rails middware中找到当前的抽象路由全部内容,希望文章能够帮你解决ruby-on-rails – 如何在Rails middware中找到当前的抽象路由所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。