Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails RubyonRails——未定义的方法“持久化”和#x27;零级:零级_Ruby On Rails_Ruby_Facebook - Fatal编程技术网

Ruby on rails RubyonRails——未定义的方法“持久化”和#x27;零级:零级

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

我是RubyonRails新手,我正尝试将oauth与Facebook结合使用,但我遇到了以下错误:
未定义的方法“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=…
    ,其作用域将仅在当前方法中

注意,您在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}