the_
the_

Reputation: 1173

Rails find by username issue

I am a new rails developer trying to get urls like:

www.twitter.com/theusername

Here's my route:

match "/:username" => "posts#index"

this works and routes my localhost:3000/theusername to localhost:3000/posts/

then I use:

def index
  @user = User.find_by_username params[:username]
  @search = Post.search do
    fulltext params[:search]
    with(:user, @user.id)
    paginate(:page => params[:page] || 1, :per_page => 20)
  end
end

Unfortunately, this brings up the error:

Called id for nil, which would mistakenly be 8 -- if you really wanted the id of nil, use object_id

Also, the web server brings up this (in case it helps):

Processing by PostsController#index as HTML
Parameters: {"username"=>"test"}
User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 2 LIMIT 1
User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."username" = 'test' LIMIT 1
Completed 500 Internal Server Error in 2ms

RuntimeError (Called id for nil, which would mistakenly be 8 -- if you really wanted the id of nil, use object_id):
app/controllers/posts_controller.rb:10:in `block in index'
app/controllers/posts_controller.rb:8:in `index'

Upvotes: 0

Views: 2404

Answers (3)

Frederick Cheung
Frederick Cheung

Reputation: 84114

Have you ever wondered why it is that inside your Post.search block you are able to call methods such as fulltext even though there is no such method on your controller ?

It's because inside that block self has been changed (by instance_eval). This is sometimes convenient, particularly when building DSLs such as sunspot's since the DSL methods are then callable without a receiver

However this means that within that block @user refers to an instance variable of the sunspot object (which doesn't have one) and so it is nil. It looks like sunspot has some clever code to proxy methods to the original calling method (that's why calling params) works, but that sort of trick doesn't work with instance variables.

The quick way around this is to do

@search = Post.search do |query|
    query.fulltext params[:search]
    query.with(:user, @user.id)
end

This makes the block a bog standard one with no changing of self, at the price of a little verbosity.

Upvotes: 5

Marcelo De Polli
Marcelo De Polli

Reputation: 29291

That error you're getting is called a whiny nil. It's raised when you try to call the id method on nil.

It's probably related to your @user.id. If @user is nil, calling @user.id will throw up a whiny nil error.

That's only in Rails 3, though. In Rails 4, whiny nils have been replaced by the regular NoMethodError: undefined method 'id' for nil:NilClass.

Upvotes: 0

sunny1304
sunny1304

Reputation: 1694

You have to use to_param method in your User model like this:

class User < ActiveRecord::Base
  def to_param 
    username
  end
end

Upvotes: 2

Related Questions