Search code examples
ruby-on-railsrubyransackgeocomplete

How do I investigate an exception in Rails?


I'm really new to rails and this is my first project. Can you help me to understand how to investigate the error?

I wrote a search function using ransack and geocode to display objects in database based on their location.

I got an exception here:

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

and I get this error in the console:

exception = Unsupported argument type: 0 (Integer)

The error occurs when in my search form I put longs strings, everything work with something like "Milan" but got the exception with the geocomplete suggestion such as "Milano, Metropolitan City of Milan, Italy"" for example.

This is the controller:

  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

and this the stacktrace of the exception

 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'

SOLVED

Geocoder itself wasn't able to return the coordinates from some longs string suggest by autolocation suggestions, so I I had to change the geocoder:config to tell geocoder to take coords from google places api instead.

I follow this Medium article on Geocoder


Solution

  • If you are getting portions of exception backtrace omitted, you can generally rescue the exception yourself and obtain the full trace:

    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> 
    

    Replace "blah" with the expression that is failing.

    You can also use "s" byebug command to step into a method, though this strategy may take some time before you get to the method that is actually failing.