如何访问.where ActiveRecord返回的数据

时间:2013-06-02 15:12:55

标签: ruby activerecord sinatra

我已经开始使用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行。那么,如何从该对象中删除密码数据,或将其转换为哈希值,因为我知道我可以以哈希格式删除密码。

3 个答案:

答案 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查询返回一个关系,而不是一个数组或一个对象 - 想想selectcollect等等。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对象。