我正在尝试将Facebook登录信息集成到我的网站中。
到目前为止,我已经建立了这样的模型(我可以添加一个更好的电子邮件验证器):
class FBUser < ActiveRecord::Base
attr_accessor :access_token, :expires_in, :reauthorize_in
attr_reader :email, :fb_id
validates :fb_id, :email, :access_token, allow_blank: false, uniqueness: true
validates :access_token, :expires_in, :reauthorize_in, presence: true
end
当用户使用Facebook登录时,它将返回的参数传递给此开发中的控制器功能:
def fb_login
params[:email] ||= params[:userID][-7...-1] + "@facebook.com"
fb_user = FBUser.create({
fb_id: params[:userID],
email: params[:email],
access_token: params[:accessToken],
expires_in: params[:expiresIn],
reauthorize_in: params[:reauthorize_required_in]
})
sign_in!(fb_user)
render json: fb_user
end
所有这些参数都存在,但是在创建过程中进行验证时,它将为电子邮件和fb_id传递NULL。 从Rails输出:
FBUser存在(0.4ms)从“ fb_users”到“ fb_users”的“ SELECT 1”为1。“ fb_id”为NULL LIMIT 1
FBUser存在(0.2ms)从“ fb_users”到“ fb_users”的“ SELECT 1”为1。“ email”为NULL LIMIT 1
FBUser存在(0.4毫秒)从“ fb_users”中的“ fb_users”中选择1作为一个。“ access_token” ='EAAEDVcUvjT4BACT8es ...
SQL(0.2ms)插入“ fb_users”(“ fb_id”,“电子邮件”,“ created_at”,“ updated_at”)值($ 1,$ 2,$ 3,$ 4)返回“ id” [[[“ fb_id”, “ 101564XXXXXXX688”],[“电子邮件”,“ XXXX68@facebook.com”],[“ created_at”,“ 2018-08-17 02:42:20.440539”],[“ updated_at”,“ 2018-08-17 02 :42:20.440539“]]
我知道这是唯一性验证,因为如果删除它,那些查询就会消失。实际上,唯一性验证没有做任何事情。我不知道为什么访问令牌根本没有传递给INSERT语句,但这是次要问题。
我已经将“ param []”参数传递给了一个变量,但没有执行任何操作。我很困惑为什么它为唯一性检查而不是email和fb_id的值而不是访问令牌的值传递NULL。此后,它将传递从同一create方法调用的INSERT中的值!
我正在使用相同的fb_id和电子邮件创建多个FBUser,但是该表的创建方式为:
create_table :fb_users do |t|
t.string :fb_id, null: false, unique: true
t.string :email, unique: true
t.string :access_token ...
更多陌生人...
答案 0 :(得分:1)
ActiveRecord属性(即存储在数据库中的列)与实例变量不同。你有这个:
attr_reader :email, :fb_id
在您的模型中。这只是简写:
def email
@email
end
def fb_id
@fb_id
end
因此,每当有人说fbuser.email
或fbuser.fb_id
时,您都会在查看实例变量。但是,当您说:
FBUser.create({
fb_id: params[:userID],
email: params[:email],
...
})
ActiveRecord将调用fb_id=
和email=
方法,将这两个值存储在模型实例中。 ActiveRecord为您创建了这些mutator方法,它们将更新属性,而不是实例变量。通常,AR还会创建fb_id
和email
方法来读取这些属性,但是您已经通过attr_reader
调用创建了这些方法。
结果是fbuser.email
将从@email
读取,但是fbuser.email = something
会写入其他内容,因此fbuser.email
总是会给您nil
。对于fbuser.fb_id
同样。
您可能希望完全摆脱attr_reader
和attr_accessor
的调用,并使模型看起来像这样:
class FBUser < ActiveRecord::Base
validates :fb_id, :email, :access_token, allow_blank: false, uniqueness: true
validates :access_token, :expires_in, :reauthorize_in, presence: true
end