nil object - very strange behavior

Hi there,

I have a search form on my application that is set to return data
based on users input (username, surname)

What os happening is quite odd, so I though if I provide the
controller method code, It should help.

Basically – if I type test, or something a result is returned. If I
enter a surname, I tend to get the error listed below.

It’s quite odd, because it does return a result if I type test (which
happens to be the last name of a registered user) I can’t understand
why it returns the error when I type anything else.

The stack trace mentions line 40 in my controller, which is this:
users.each { |user| user.info ||= Info.new }

I know it’s the user.info it’s talking about, but I have amended this,
but with no luck….

Can anyone help?

Code below…

Thanks for reading.

NoMethodError in BuddiesController#search

You have a nil object when you didn't expect it!
The error occurred while evaluating nil.info

def search

      if params[:q]
        query = params[:q]
        curr_page = params[:page] || 1
        # First find the user hits...
  # @users = User.search(query)
        users = User.find_with_ferret(query)
        # ...then the subhits.
        infos = Info.find_with_ferret(query)
        hits = infos
        # Now combine into one list of distinct users sorted by last
name.
  # @users.concat(hits.collect { |hit| hit.user }).uniq!
        users.concat(hits.collect { |hit| hit.user }).uniq!
        # Sort by last name (requires a spec for each user).
  # @users.each { |user| user.spec ||= Spec.new }
  # @users = @users.sort_by { |user| user.spec.last_name }
        users.each { |user| user.info ||= Info.new }
        users = users.sort_by { |user| user.info.last_name }
        @buddies = users.paginate(:page => curr_page, :per_page =>
10)
       end
end

I haven't used ferret, but I would think you could throw in a
debugging line or two to figure out the problem. Put it in before
your call to the nil object and check your log file. You might
consider cleaning up your code a bit too, It is a bit difficult to
read with the old code stuck in there but commented out.

logger.debug users.inspect
users.each { |user| user.info ||= Info.new }

you could also change line 40 to this:
users.each { |user| user.info ||= Info.new if user }

maybe i'm wrong, but it could be something like the following:

if your users (=hits) are User.find_by_ferret and thus of the class
User. a user.user would return nil, like in this line:
  users.concat(hits.collect { |hit| hit.user }).uniq!
now you have a collection of nils and try to call nil.info on them.

in any case set a debugger and take a deeper look into your variables.

Thanks for the replies.

I will try this and let you know...

You may find the rails guide on debugging useful. In particular how
to use ruby-debug. (google rails guides)

Colin

I couldn't get the debug to work,

But I'm still not 100% sure why the code sometimes returns results,
and not others.
I would have thought it would be all the time, or none of the time...

I guess i'll have to do a bit more digging.

Thanks all...

I couldn't get the debug to work,

Try harder or come back with the problem. You need to be able to debug.

Did you remember to use script/server --debugger (that is two - chars)

Colin

I'd assume that there's a stray Info record with user_id == nil in the
database someplace. Try this at the console:

Info.find(:all, :conditions => 'user_id IS NULL')

(I'm assuming here that the FK from Info to User is named user_id).

--Matt Joens

Hi All,

Info.find(:all, :conditions => 'user_id IS NULL') returns nothing

I might try clearng all the results and indexes from ferret and
restart the web server. I would understand if it never worked. The
fact that it does 'sometimes' return results, must mean the code is
OK?

Hi all (again)...

I deleted the index and restarted the web server.

Once I created a few more users, the search fields worked fine. It
must have been ferret playing up in development. (hopefully it wont do
that in Prod) or the site wont be too good!

thanks for your replies.