按用户名问题查找轨道



我是一个新的rails开发人员,试图获得这样的网址:

www.twitter.com/theusername

这是我的路线:

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

这有效并将我的本地主机:3000/用户名路由到本地主机:3000/帖子/

然后我使用:

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

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

将 id 称为 nil,这将错误地为 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'

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

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

然而,这意味着在该块中,@user引用太阳黑子物体的实例变量(没有(,因此它是零。看起来 sunspot 有一些聪明的代码将方法代理到原始调用方法(这就是调用 params 的原因(有效,但这种技巧不适用于实例变量。

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

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

这使得该块成为沼泽标准块,没有改变self,代价是有点冗长。

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

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

你得到的错误被称为抱怨的nil。当您尝试在 nil 上调用 id 方法时,会引发它。

这可能与你的@user.id有关。如果@user为 nil,则调用 @user.id 将引发一个抱怨的 nil 错误。

不过,这只是在Rails 3中。在 Rails 4 中,抱怨的 nils 已被常规NoMethodError: undefined method 'id' for nil:NilClass所取代。

最新更新