我已经开始使用ActiveRecord来访问我的数据库,它非常有用。但是,访问ActiveRecord::Relation
对象内的数据似乎是一个挑战。我使用以下方式查询我的数据库:
post '/login' do
session.clear
r = User.where(:username => params["user"], :password => Digest::MD5.hexdigest(params["pass"]))
if r.count == 1
session[:user] = r
session[:user].delete(:password)
status 200
else
status 401
end
end
返回数据后,Ruby会检查以确保有一行,如果有,则将r
对象的内容设置为散列session[:user]
。然后,理想情况下,它应该从session[:user]
对象中删除密码数据,以便它仅提供识别用户的详细信息。但是,使用此代码,我收到错误:wrong number of arguments (1 for 0)
指向.delete
行。那么,如何从该对象中删除密码数据,或将其转换为哈希值,因为我知道我可以以哈希格式删除密码。
答案 0 :(得分:0)
您在关系上调用delete,而不是在散列或用户中调用。
正如@ sunny1304所说,你可以选择从数据库中获取的字段,你也必须调用#first来只检索一个条目。
r = User.where(:username => params["user"], :password => Digest::MD5.hexdigest(params["pass"])).select(:id, :username, :other_attrs).first
您无论如何都不应将所有用户数据存储在会话中。您应该只保存ID,也可以保存不会更改的内容(例如,如果您的应用程序中存在用户名,则为用户名)。并在每个请求中查询用户数据。
答案 1 :(得分:0)
在重新识别用户时,我通常只在session
对象中存储一个唯一的属性,该属性不容易被篡改(在Rails中,会话存储在现在签名和加密中) -曲奇饼)。数据量通常在会话存储中受限。
为此,在我的Users表中添加token
,每次用户登录时都会重新生成并存储在会话中。通常(在PostgreSQL上)我定义了uuid
类型的这一列,但你也可以使用VARCHAR(128)
或类似的。
如果用户现在返回,我只需发出
@current_user = User.where(token: session['user_token']).first
当用户退出时,我只是取消用户的token
:
@current_user.update_attribute :token, nil
session.clear
答案 2 :(得分:0)
ActiveRecord查询返回一个关系,而不是一个数组或一个对象 - 想想select
,collect
等等。session[:user] = User.all.select{|u| u.id == 1}
没有意义,是吗?
所以,就像上面说的那样:
User.where(:id => 1).class == ActiveRecord::Relation
而
User.find(1).class == User
这样做是为了在链接查询时,ActiveRecord可以将它们转换为一个SQL查询,而不是获取许多记录,将它们转换为Ruby对象,然后在它们上运行Ruby命令。
一个非常简单的例子:
$ User.where(:id => 1).count
(0.5ms) SELECT COUNT(*) FROM "users" WHERE "users"."id" = 1
=> 1
与
$ User.where(:id => 1).all.count
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1
=> 1
.all
将ActiveRecord :: Relation转换为Ruby对象数组,在本例中为User
然后你可以做
User.find(1).update_attributes(:name => "Joseph")
user = User.find(1)
user.name = "Jack"
user.save
因为它是一个Ruby对象。