Rails按用户名问题查找

时间:2013-06-27 16:49:09

标签: ruby-on-rails ruby

我是一名新的铁路开发人员,试图获取网址:

www.twitter.com/theusername

这是我的路线:

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

这可以工作并将我的localhost:3000 / theusername路由到localhost:3000 / posts /

然后我用:

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

不幸的是,这会带来错误:

  

如果你真的想要的话,被称为nil的id,这将错误地为8   nil的id,使用object_id

此外,Web服务器会提示(如果它有帮助):

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'

3 个答案:

答案 0 :(得分:5)

你有没有想过为什么在你的Post.search块中你可以调用fulltext之类的方法,即使你的控制器上没有这样的方法?

这是因为该块self内部已被更改(instance_eval)。这有时很方便,特别是在构建像太阳黑子这样的DSL时,因为DSL方法可以在没有接收器的情况下调用

然而,这意味着在该块@user内引用了太阳黑子对象的实例变量(没有一个),因此它是零。看起来太阳黑子有一些聪明的代码来代理原始调用方法的方法(这就是为什么调用params)有效,但这种技巧不适用于实例变量。

快速解决这个问题的方法是

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

这使得该块成为一个标准的块,没有更改self,但代价是有点冗长。

答案 1 :(得分:2)

您必须在用户模型中使用to_param方法,如下所示:

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

答案 2 :(得分:0)

您获得的错误称为 whiny nil 。当您尝试在id上调用nil方法时,会引发此问题。

这可能与您的@user.id有关。如果@user为零,则调用@user.id会产生一个小的错误。

但这只是在Rails 3中。在Rails 4中,whiny nils已被常规NoMethodError: undefined method 'id' for nil:NilClass取代。