我是一个新的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
所取代。