Ruby on rails RubyonRails——未定义的方法“持久化”和#x27;零级:零级
我是RubyonRails新手,我正尝试将oauth与Facebook结合使用,但我遇到了以下错误:Ruby on rails RubyonRails——未定义的方法“持久化”和#x27;零级:零级,ruby-on-rails,ruby,facebook,Ruby On Rails,Ruby,Facebook,我是RubyonRails新手,我正尝试将oauth与Facebook结合使用,但我遇到了以下错误:未定义的方法“persisted”(持久化),用于nil:NilClass。当我尝试登录Facebook时就会发生这种情况。你知道为什么吗 模型: usuarios.rb class Usuario < ActiveRecord::Base # Include default devise modules. Others available are: # :c onfirmab
未定义的方法“persisted”(持久化),用于nil:NilClass
。当我尝试登录Facebook时就会发生这种情况。你知道为什么吗
模型:
usuarios.rb
class Usuario < ActiveRecord::Base
# Include default devise modules. Others available are:
# :c onfirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
devise :omniauthable, omniauth_providers: [:facebook]
def self.find_or_create_by_omniauth(auth)
usuario = Usuario.where(provider: auth[:provider], uid: [:uid]).first
return usuario if usuario
usuario = Usuario.create[
nombre: auth[:nombre],
apellido: auth[:apellido],
username: auth[:username],
email: auth[:email],
uid: auth[:uid],
prvider: auth[:provider],
password: Devise.friendly_token[0,20]
]
end
end
class OmniauthCallbacksController < ApplicationController
def facebook
auth = request.env["omniauth.auth"]
data = {
nombre: auth.info.first_name,
apellido: auth.info.last_name,
username: auth.info.nickname,
email: auth.info.email,
provider: auth.provider,
uid: auth.uid
}
@usuario = Usuario.find_or_create_by_omniauth(data)
if @usuario.persisted?
sign_in_and_redirect @usuario, event: :authentication
else
session[:omniauth_errors] = @usuario.errors.full_messages.to_sentence unless @usuario.save
session[:omniauth_data] = data
redirect_to new_usuario_registration_url
end
end
def failure
redirect_to new_usuario_registration_url
end
end
非常感谢您的任何帮助。您的
查找\u或\u创建\u by \u omniauth
方法在创建新Usuario时返回nil
。rails方法返回方法中的最后一条语句,当您创建记录时,它返回nil。您只需在方法末尾添加usuario
,如:
def self.find_or_create_by_omniauth(auth)
usuario = Usuario.where(provider: auth[:provider], uid: [:uid]).first
return usuario if usuario
usuario = Usuario.create[
nombre: auth[:nombre],
apellido: auth[:apellido],
username: auth[:username],
email: auth[:email],
uid: auth[:uid],
prvider: auth[:provider],
password: Devise.friendly_token[0,20]
]
usuario
end
得到零的原因是使用括号而不是括号
# creates two things
Thing.create [{ name: foo }, { name: bar}]
# => nil
当您创建[nombre:auth[:nombre]时,…您实际上是在传递一个数组-ActiveRecord将尝试创建多个记录,并始终返回nil
除此之外,您的代码还充斥着拼写错误:
您还应该注意,omniauth创建的request.env[“omniauth.auth”]
hash遵循-您没有使用正确的键,因此模型中的许多属性最终将为零
因此,让我们重构。通过\u omniauth查找\u或\u创建\u
:
def self.find_or_create_by_omniauth(auth)
self.where(auth.slice(:uid, :provider))
# see the auth hash schema for available keys
.create_with(auth[:info].slice(:email))
.first_or_create do |user|
user.nombre = auth[:nombre] # will most likely be nil!
user.apellido = auth[:apellido] # will most likely be nil!
user.password = Devise.friendly_token[0,20]
end
end
Hash#slice
是一种很酷的ActiveSupport方法,它允许您复制哈希,但只能使用所需的键,而无需手动复制:
hash = { a: 1, b: 2, c: 3}
{ a: hash[:a], c: hash[:c] } # wow, much typing, such boring
hash.slice(:a,:c)
# => { a: 1, c: 3}
问题是您使用了create[]
而不是create()
。
到底发生了什么ARSubClass.create[foo:1,bar:2,baz:3]
等于ARSubClass.create[{foo:1,bar:2,baz:3}]
ARSubClass.create
尝试创建一个ARSubClass
的实例,但是失败了,因为我猜是验证并返回了非持久记录。
然后你用一个参数
{foo:1,bar:2,baz:3}
实例[{foo:1,bar:2,baz:3}=>nil
解决方案是像这样使用
create
create(…)
更多的“RailsWay”方法将用于通过omniauth实现
find\u或\u create\u
请注意,如果将块传递给
find_或
,则只会在create
情况下对其求值
传统注释:
- 不要使用
where(foo:'baz',bar:'mar')。首先使用
find_by(foo:'baz',bar:'mar')
- 在控制器中,如果不打算在某些视图中使用它,则不要将
设置为实例变量(带有@usuario
前缀)@
。
只需将其设置为变量
,其作用域将仅在当前方法中usuario=…
prvider:auth[:provider],
-它应该是provider:auth[:provider],
,带有o
。这并不能解决问题。在Ruby中,方法中的最后一个值(不是最后一个语句!)是隐式返回的。他得到零的真正原因是他使用括号而不是括号。如果你使用Usuario.create(电子邮件:'test@example.com“)
它返回记录。但是create还允许您通过传递哈希数组一次创建多个记录,但返回值为零。Usuario.create[foo:'bar'…]
被视为散列数组。是的,最后一行/最后一个值/最后一个语句是从方法返回的。因为他在最后创建方法(使用括号),它返回nil。因此,nil被返回。:)谢谢,这帮助我解决了我的问题。我来自PHP背景,所以所有这些对我来说都是全新的。再次感谢。
hash = { a: 1, b: 2, c: 3}
{ a: hash[:a], c: hash[:c] } # wow, much typing, such boring
hash.slice(:a,:c)
# => { a: 1, c: 3}