0

我是一名新的 Rails 开发人员,试图获取以下网址:

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'
4

3 回答 3

5

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

这是因为该块内部self已更改(按instance_eval)。这有时很方便,特别是在构建诸如 sunspot 之类的 DSL 时,因为 DSL 方法可以在没有接收器的情况下调用

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

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

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

这使得该块成为一个沼泽标准块,没有任何变化self,但代价是有点冗长。

于 2013-06-27T18:01:42.983 回答
2

你必须to_param在你的用户模型中使用这样的方法:

class User < ActiveRecord::Base
  def to_param 
    username
  end
end
于 2013-06-27T16:55:42.810 回答
0

你得到的那个错误被称为whiny nil。当您尝试idnil.

应该和你的有关@user.id。如果@user为 nil,调用@user.id将抛出一个 whiny nil 错误。

不过,这只是在 Rails 3 中。在 Rails 4 中,whiny nils 已被常规的 NoMethodError: undefined method 'id' for nil:NilClass.

于 2013-06-27T17:10:43.047 回答