NoMethodError, undefined method

4.3k views Asked by At

Hello I can not understand what the cause of the error when searching the Sphinx. Controller:

class SearchesController < ApplicationController
 def show
   @results = Search.get_results(params[:query], params[:context])
 end
end

Model:

class Search < ApplicationRecord
  CONTEXTS = ['Questions', 'Answers', 'Comments', 'Users']

  def get_results(query, context)
   query = ThinkingSphinx::Query.escape(query)
   klasses = [context.singularize.constantize] if CONTEXTS.include?(context)
   @results = ThinkingSphinx.search(query, classes: klasses, order: 'model_order ASC') if query.present?
  end
 end

Error: NoMethodError in SearchesController#show,

undefined method `get_results' for Search(id: integer, created_at: datetime, updated_at: datetime):Class

when used in self in the method

def self.get_results(query, context)
# ...
end

the error will be: undefined method `gsub' for nil:NilClass in string

query = ThinkingSphinx::Query.escape(query)

I am a beginner ... but I can not understand .. maybe sphinx installed incorrectly

Thanks in advance!

1

There are 1 answers

0
Taryn East On BEST ANSWER

These are two different bugs.

The first one is that you are defining an instance method, but using it on the class (instead of on an instance). A class method starts self eg

def self.my_method_name

and can be called on the main class eg Search.my_method_name instead of a specific instance of the search class. An example of calling an instance method with the same name would be:

my_search = Search.new(:some => :attributes)
my_search.my_method_name

SO, your first error message tells you "there is no method called get_results on the Search class" - and this is because you have defined it as def get_results instead of def self.get_results

So, then you tried adding self. and this error went away.

This then exposed the next bug - which is completely unrelated to the first one.

The second error complains that you are calling gsub on nil.

the gsub is probably something happening inside of the ThinkingSphinx::Query.escape(query) call.

and you can't (easily) change anything inside of another library... but you can still glean useful information from the error message. In this case, the error is complaining that you're calling a method on nil... that means that something is nil that it was expecting to be not-nil.

Given this is a search-query thing... my best guess would be that it is assuming that the query variable is some kind of string... containing a search-query.

It probably is expecting that query * NOT * to be a nil.

and yet in this instance it is.

What if...

a) somebody hits the "go" button without entering a search-query?

b) you accidentally made a typo in the parameter name in your form and so nothing is actually coming through for params[:query] ?

c) the nesting of your params is slightly different to what you expect (eg params[:search_form][:query])

Firstly - you should double-check that your forms are sending through the params that your controller actually expects. You can do this by looking in the logs -> either in the terminal/console window, or in your logfiles (usually log/development.log) and watching what happens when you hit the submit-button on your search form. The logs will list the parameters that come through when you submit that form and you can double-check it's exactly what you expect.

Secondly: you probably should not actually do the searching if no query comes through - people will accidentally hit the submit button even when they haven't typed something - and it'd be a nicer GUI if your app didn't explode when that happens :)

You could do something like this:

def self.get_results(query, context)
  return nil unless query.present?
  # ... the rest of the method here
end

Just make sure that your view explicitly checks for nil and doesn't explode in that case.