如何调查 Rails 中的异常?

How do I investigate an exception in Rails?

我是 rails 的新手,这是我的第一个项目。你能帮我了解如何调查错误吗?

我编写了一个搜索功能,使用 ransack 和地理编码根据对象的位置显示数据库中的对象。

我这里有一个例外:

@cars_address = Car.where(active: true).near(session[:loc_search], 5, order: 'distance')

我在控制台中收到此错误:

exception = Unsupported argument type: 0 (Integer)

错误发生在我在搜索表单中输入长字符串时,所有内容都适用于“Milan”之类的内容,但地理完整建议出现异常,例如“Milano, Metropolitan City of Milan, Italy”。

这是控制器:

  def search

if params[:q].present? && params[:q].strip != ""
  session[:loc_search] = params[:q]
end
if session[:loc_search] && session[:loc_search] != ""


  #Something Wrong Here?
  @cars_address = Car.where(active: true).near(session[:loc_search], 5, order: 'distance')
  else
  @cars_address = Car.where(active: true).all

end

@q = @cars_address.ransack(params[:q])
@cars = @q.result

@arrCars = @cars.to_a

这是异常的堆栈跟踪

 Processing by PagesController#search as HTML
  Parameters: {"q"=>"Milano, Metropolitan City of Milan, Italy", "start_date"=>"", "end_date"=>"", "commit"=>"Search"}

[4, 13] in /mnt/c/Users/haget/Documents/GitHub/Clapp/app/controllers/pages_controller.rb
    4:     @cars = Car.where(active: true).limit(3)
    5:   end
    6:
    7:   def search
    8:     byebug
=>  9:     if params[:q].present? && params[:q].strip != ""
   10:       session[:loc_search] = params[:q]
   11:     end
   12:     if session[:loc_search] && session[:loc_search] != ""
   13:
(byebug)

[95, 104] in /home/haget/.rvm/gems/ruby-2.7.0/gems/puma-4.3.5/lib/puma/thread_pool.rb
    95:         not_full = @not_full
    96:
    97:         extra = @extra.map { |i| i.new }
    98:
    99:         while true
=> 100:           work = nil
   101:
   102:           continue = true
   103:
   104:           mutex.synchronize do
(byebug)

[19, 28] in /home/haget/.rvm/gems/ruby-2.7.0/gems/actionpack-6.0.3.2/lib/action_controller/metal/rescue.rb
   19:
   20:     private
   21:       def process_action(*args)
   22:         super
   23:       rescue Exception => exception
=> 24:         request.env["action_dispatch.show_detailed_exceptions"] ||= show_detailed_exceptions?
   25:         rescue_with_handler(exception) || raise
   26:       end
   27:   end
   28: end
(byebug)

[32, 41] in /home/haget/.rvm/gems/ruby-2.7.0/gems/actionpack-6.0.3.2/lib/action_controller/metal/instrumentation.rb
   32:       ActiveSupport::Notifications.instrument("process_action.action_controller", raw_payload) do |payload|
   33:         super.tap do
   34:           payload[:status] = response.status
   35:         end
   36:       ensure
=> 37:         append_info_to_payload(payload)
   38:       end
   39:     end
   40:
   41:     def render(*args)
(byebug)

[20, 29] in /home/haget/.rvm/gems/ruby-2.7.0/gems/activesupport-6.0.3.2/lib/active_support/notifications/instrumenter.rb
   20:       def instrument(name, payload = {})
   21:         # some of the listeners might have state
   22:         listeners_state = start name, payload
   23:         begin
   24:           yield payload if block_given?
=> 25:         rescue Exception => e
   26:           payload[:exception] = [e.class.name, e.message]
   27:           payload[:exception_object] = e
   28:           raise e
   29:         ensure
(byebug)
Completed 500 Internal Server Error in 13406ms (ActiveRecord: 0.0ms | Allocations: 788474)



[36, 45] in /home/haget/.rvm/gems/ruby-2.7.0/gems/actionview-6.0.3.2/lib/action_view/rendering.rb
   36:     # Overwrite process to setup I18n proxy.
   37:     def process(*) #:nodoc:
   38:       old_config, I18n.config = I18n.config, I18nProxy.new(I18n.config, lookup_context)
   39:       super
   40:     ensure
=> 41:       I18n.config = old_config
   42:     end
   43:
   44:     module ClassMethods
   45:       def _routes
(byebug)

[25, 34] in /home/haget/.rvm/gems/ruby-2.7.0/gems/actionpack-6.0.3.2/lib/action_dispatch/middleware/callbacks.rb
   25:       error = nil
   26:       result = run_callbacks :call do
   27:         @app.call(env)
   28:       rescue => error
   29:       end
=> 30:       raise error if error
   31:       result
   32:     end
   33:   end
   34: end
(byebug)

[12, 21] in /home/haget/.rvm/gems/ruby-2.7.0/gems/actionpack-6.0.3.2/lib/action_dispatch/middleware/executor.rb
   12:       state = @executor.run!
   13:       begin
   14:         response = @app.call(env)
   15:         returned = response << ::Rack::BodyProxy.new(response.pop) { state.complete! }
   16:       ensure
=> 17:         state.complete! unless returned
   18:       end
   19:     end
   20:   end
   21: end
(byebug)

[36, 45] in /home/haget/.rvm/gems/ruby-2.7.0/gems/actionpack-6.0.3.2/lib/action_dispatch/middleware/debug_exceptions.rb
   36:         raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}"
   37:       end
   38:
   39:       response
   40:     rescue Exception => exception
=> 41:       invoke_interceptors(request, exception)
   42:       raise exception unless request.show_exceptions?
   43:       render_exception(request, exception)
   44:     end
   45:
(byebug)

ArgumentError (Unsupported argument type: 0 (Integer)):

app/controllers/pages_controller.rb:16:in `search'

已解决

地理编码器本身无法 return 自动定位建议建议的一些长字符串的坐标,所以我不得不更改 geocoder:config 以告诉地理编码器从 [=40= 获取坐标] 改为放置 api。

我关注这个Medium article on Geocoder

如果您遗漏了部分异常回溯,您通常可以自己修复异常并获得完整的跟踪:

irb(main):002:0> begin; blah; rescue => exc; end
=> nil

irb(main):003:0> exc
=> #<NameError: undefined local variable or method `blah' for main:Object>

irb(main):005:0> puts exc.backtrace.join("\n")
(irb):2:in `rescue in irb_binding'
(irb):1:in `irb_binding'
/home/w/.rbenv/versions/2.7.1/lib/ruby/2.7.0/irb/workspace.rb:114:in `eval'
/home/w/.rbenv/versions/2.7.1/lib/ruby/2.7.0/irb/workspace.rb:114:in `evaluate'
/home/w/.rbenv/versions/2.7.1/lib/ruby/2.7.0/irb/context.rb:439:in `evaluate'
/home/w/.rbenv/versions/2.7.1/lib/ruby/2.7.0/irb.rb:540:in `block (2 levels) in eval_input'
/home/w/.rbenv/versions/2.7.1/lib/ruby/2.7.0/irb.rb:695:in `signal_status'
/home/w/.rbenv/versions/2.7.1/lib/ruby/2.7.0/irb.rb:537:in `block in eval_input'
/home/w/.rbenv/versions/2.7.1/lib/ruby/2.7.0/irb/ruby-lex.rb:150:in `block (2 levels) in each_top_level_statement'
/home/w/.rbenv/versions/2.7.1/lib/ruby/2.7.0/irb/ruby-lex.rb:135:in `loop'
/home/w/.rbenv/versions/2.7.1/lib/ruby/2.7.0/irb/ruby-lex.rb:135:in `block in each_top_level_statement'
/home/w/.rbenv/versions/2.7.1/lib/ruby/2.7.0/irb/ruby-lex.rb:134:in `catch'
/home/w/.rbenv/versions/2.7.1/lib/ruby/2.7.0/irb/ruby-lex.rb:134:in `each_top_level_statement'
/home/w/.rbenv/versions/2.7.1/lib/ruby/2.7.0/irb.rb:536:in `eval_input'
/home/w/.rbenv/versions/2.7.1/lib/ruby/2.7.0/irb.rb:471:in `block in run'
/home/w/.rbenv/versions/2.7.1/lib/ruby/2.7.0/irb.rb:470:in `catch'
/home/w/.rbenv/versions/2.7.1/lib/ruby/2.7.0/irb.rb:470:in `run'
/home/w/.rbenv/versions/2.7.1/lib/ruby/2.7.0/irb.rb:399:in `start'
/home/w/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/irb-1.2.3/exe/irb:11:in `<top (required)>'
/home/w/.rbenv/versions/2.7/bin/irb:23:in `load'
/home/w/.rbenv/versions/2.7/bin/irb:23:in `<main>'
=> nil
irb(main):006:0> 

用失败的表达式替换“blah”。

您也可以使用“s”byebug 命令单步执行一个方法,尽管此策略可能需要一些时间才能到达实际失败的方法。