【问题标题】:Rails 4 with Devise, Omniauth and multiple service providersRails 4 与 Devise、Omniauth 和多个服务提供商
【发布时间】:2015-12-07 09:47:02
【问题描述】:

我正在拼命寻找一种方法来让设计在我的 Rails 4 应用程序中工作。我已经尝试了所有可以找到的教程来进行设置。

当前教程为:http://sourcey.com/rails-4-omniauth-using-devise-with-twitter-facebook-and-linkedin/

我之前关于相关问题的赏金问题(通常被否决,我不明白为什么),展示我完成这项工作的其他尝试。

我目前的问题是用户模型中的这段文字:

def self.find_for_oauth(auth, signed_in_resource = nil)

    # Get the identity and user if they exist
    identity = Identity.find_for_oauth(auth)

    # If a signed_in_resource is provided it always overrides the existing user
    # to prevent the identity being locked with accidentally created accounts.
    # Note that this may leave zombie accounts (with no associated identity) which
    # can be cleaned up at a later date.
    user = signed_in_resource ? signed_in_resource : identity.user

    # Create the user if needed
    if user.nil?

      # Get the existing user by email if the provider gives us a verified email.
      # If no verified email was provided we assign a temporary email and ask the
      # user to verify it on the next step via UsersController.finish_signup
      email_is_verified = auth.info.email && (auth.info.verified || auth.info.verified_email)
      email = auth.info.email if email_is_verified
      user = User.where(:email => email).first if email

      # Create the user if it's a new registration
      if user.nil?
        user = User.new(
          name: auth.extra.raw_info.name,
          #username: auth.info.nickname || auth.uid,
          email: email ? email : "#{auth.uid}-#{auth.provider}.com",
          password: Devise.friendly_token[0,20]
        )
        user.skip_confirmation!
        user.save!
      end
    end

问题是(指向这一行:user = User.new)在上述方法中:

unknown attribute 'name' for User.

在我尝试的上一个教程中,我发现当我将属性更改为时,linkedin 工作:

# self.email = omniauth['extra']['raw_info']['emailAddress'] 
 #      self.first_name = omniauth['extra']['raw_info']['firstName']
    #     self.last_name = omniauth['extra']['raw_info']['lastName']

omniauth 策略的字段名称与教程中显示的不同(至少对于linkedin)。但是如果 Facebook 或 twitter 再次使用不同的字段名称,本教程如何解决呢?

另外,在我的用户表中,我有名为 first_name 和 last_name 的属性,但我尝试将行更改为:

first_name: auth.extra.raw_info.'firstName',

那也没用。

当我尝试时:

first_name: auth.extra.raw_info.name

我收到此错误:

undefined method `password_required?' for #<User:0x007fb7bc2ce6f8>

但无论如何,我只想在该字段中使用名字,我认为这是将整个名字放入名字中(尽管我不确定)。此外,如果这将被修改为适用于linkedin,这是否意味着它不适用于 Facebook 和 twitter?

这一切都是一团糟。我越来越对此感到沮丧。有谁知道如何解决这个特定问题。我已经尝试了 2.5 年以使设计/omniauth 正常工作。

我最近之前的教程链接问题是:

https://stackoverflow.com/questions/33888972/rails-devise-omniauth-strategies-omniauthcallbackscontroller

Devise Omniauth - setup & defining strategies

Rails, Devise & Omniauth - problems with setup

还有其他几个,但我不是靠自己的努力解决这个问题的。我在 codementor.io 上进行了几次会议,但未能找到帮助。非常感谢您的帮助。

所以尝试下面的建议,我尝试将用户模型中的方法更改为:

def self.find_for_oauth(auth, signed_in_resource = nil)

    # Get the identity and user if they exist
    identity = Identity.find_for_oauth(auth)

    # If a signed_in_resource is provided it always overrides the existing user
    # to prevent the identity being locked with accidentally created accounts.
    # Note that this may leave zombie accounts (with no associated identity) which
    # can be cleaned up at a later date.
    user = signed_in_resource ? signed_in_resource : identity.user

    # Create the user if needed
    if user.nil?

      # Get the existing user by email if the provider gives us a verified email.
      # If no verified email was provided we assign a temporary email and ask the
      # user to verify it on the next step via UsersController.finish_signup
      email_is_verified = auth.info.email && (auth.info.verified || auth.info.verified_email)
      email = auth.info.email if email_is_verified
      user = User.where(:email => email).first if email

      # Create the user if it's a new registration
      if user.nil?
        user = User.new(
          case auth.provider
            when 'linkedin'
              first_name: auth.extra.raw_info.firstName,
              last_name: auth.extra.raw_info.lastName,
              email: emailAddress ? email : "#{auth.uid}-#{auth.provider}.com",
              #username: auth.info.nickname || auth.uid,
              # email: email ? email : "#{auth.uid}-#{auth.provider}.com",
              password: Devise.friendly_token[0,20]
            when 'facebook'
              first_name: auth.extra.raw_info.first_name,
              last_name: auth.extra.raw_info.last_name,
              email: auth.extra.raw_info.email ? email : "#{auth.uid}-#{auth.provider}.com",
              password: Devise.friendly_token[0,20]

            when 'twitter' 
            first_name: auth.extra.raw_info.nickname, 
          end
        )
        user.skip_confirmation!
        user.save!
      end
    end

这有几个问题,是:

unexpected ':', expecting keyword_end first_name: auth.extra.raw_info.firstName,
unexpected tLABEL, expecting '=' last_name: auth.extra.raw_info.lastName
unexpected tLABEL, expecting '=' email: emailAddress ? email : "#{au... ^
unexpected ',', expecting keyword_end
unexpected keyword_when, expecting keyword_end when 'facebook' ^
unexpected ':', expecting keyword_end first_name: auth.extra.raw_info.first_name, ^ 
unexpected tLABEL, expecting '=' last_name: auth.extra.raw_info.last_name,
unexpected tLABEL, expecting '=' email: auth.extra.raw_info.email ? ... ^
unexpected ',', expecting keyword_end
unexpected keyword_when, expecting keyword_end when 'twitter' ^ 
unexpected ':', expecting keyword_end first_name: auth.extra.raw_info.nickname, ^
unexpected keyword_end, expecting '='

我不知道如何解决这个问题 - 我找不到任何例子(除了下面帖子中的例子)如何解决这个问题 - 这显然不起作用)。

除了以上所有内容之外,我还能用 Twitter 做什么?它有一个昵称字段。如何将单词分开,以便第一个单词保存为 first_name,第二个单词保存为 last_name?

从下面特别刻薄的 cmets 推断,我再次尝试了该建议,使用 if 语句。还是不行。

def self.find_for_oauth(auth, signed_in_resource = nil)

    # Get the identity and user if they exist
    identity = Identity.find_for_oauth(auth)

    # If a signed_in_resource is provided it always overrides the existing user
    # to prevent the identity being locked with accidentally created accounts.
    # Note that this may leave zombie accounts (with no associated identity) which
    # can be cleaned up at a later date.
    user = signed_in_resource ? signed_in_resource : identity.user

    # Create the user if needed
    if user.nil?

      # Get the existing user by email if the provider gives us a verified email.
      # If no verified email was provided we assign a temporary email and ask the
      # user to verify it on the next step via UsersController.finish_signup
      email_is_verified = auth.info.email && (auth.info.verified || auth.info.verified_email)
      email = auth.info.email if email_is_verified
      user = User.where(:email => email).first if email

      # Create the user if it's a new registration
      if user.nil?
        user = User.new(
          if auth.provider = linkedin
              first_name: auth.extra.raw_info.firstName,
              last_name: auth.extra.raw_info.lastName,
              email: emailAddress ? email : "#{auth.uid}-#{auth.provider}.com",
              #username: auth.info.nickname || auth.uid,
              # email: email ? email : "#{auth.uid}-#{auth.provider}.com",
              password: Devise.friendly_token[0,20]
          end

          if auth.provider = facebook    
              first_name: auth.extra.raw_info.first_name,
              last_name: auth.extra.raw_info.last_name,
              email: auth.extra.raw_info.email ? email : "#{auth.uid}-#{auth.provider}.com",
              password: Devise.friendly_token[0,20]

          end

          if auth.provider = twitter
            first_name: auth.extra.raw_info.firstName, 
          end
        )
        user.skip_confirmation!
        user.save!
      end
    end

在此板上找不到解决方案,如果您认为支付专业人员帮助解决这些问题是合理的,我将不胜感激。

我已经返回并注释掉了与设计和 OMNIAUTH 相关的所有代码,现在再次尝试,OMNIAUTH Wiki 上的文档称为:管理多个提供者

看来这个文档可能有经验丰富的编码人员可以阅读过去的错别字。

目前正在生成如下错误信息:

/Users/config/routes.rb:35: syntax error, unexpected [, expecting keyword_do or '{' or '(' ...', to: 'sessions#create', via [:get, :post] ... ^ /Users/config/routes.rb:36: syntax error, unexpected [, expecting keyword_do or '{' or '(' match '/logout', to: 'sessions#destroy', via [:get, :post] ^

我直接从用户指南中复制了这些路线。我远不是专家,但我也很困惑为什么在这个文档中的某些地方使用了“==”而在其他地方使用了“=”。例如:

if signed_in?
            if @identity.user == current_user

同时:

@identity.user = current_user

在相同的方法中存在差异。

我也很困惑为什么会话控制器不从设计控制器继承。在我完成的其他每个教程中,都有一个会话控制器,它继承自 devise。

本教程还有很多其他令人困惑的方面(比如为什么它没有注册控制器,为什么没有其他路由可供设计,为什么应用程序控制器有创建和销毁方法)?

急切地寻求帮助。

【问题讨论】:

  • unknown attribute 'name' for User. 我猜你的用户模型上没有属性名称?那么如何不将整行 name: auth.extra.raw_info.name 更改为 first_name: auth.extra.raw_info.'firstName'。首先尝试first_name: auth.extra.raw_info.name

标签: ruby-on-rails devise omniauth omniauth-linkedin


【解决方案1】:

这不是一个完整的答案,但我已经解决了部分问题。

oauth gem 的重点是从每个社交媒体策略中获取属性并将它们统一为一种通用的表达形式。

通过合并策略中的 raw_info,代码无法使用 oauth。例如,linkedin auth hash 返回标记为“firstName”的数据,其中 oauth 将其识别为 first_name。如果你使用

first_name: auth.extra.raw_info.first_name,

调用链接时该属性将为 nil。这对我来说已经很奇怪了,因为 LinkedIn 提供了基本的个人资料详细信息,表明标签是名字。

无论如何,我修复的部分是删除上述行中对“extra.raw”的引用并使用 auth.info.first_name。这应该可以解决策略标签之间的差异。

我仍在努力解决此设置中出现的其他问题。 sourcey 教程中的一些问题是语法问题,其他问题更重要。如果我能把它们整理出来,我会再发一次。

【讨论】:

    【解决方案2】:
    unknown attribute 'name' for User.
    

    这意味着users 表中没有name 列。您需要创建此列或使用您拥有的其他列(如first_nameusername)。像这样:

    username: auth.extra.raw_info.name
    

    但是如果 Facebook 或 twitter 再次使用不同的字段名称,如何 教程能解决这个问题吗?

    是的,本教程只提供了一种变体,但其他变体并不难找到。您只需要知道,哪些字段会返回这个或那个提供者(twitter、facebook 或linkedin)并执行以下操作:

    def self.find_for_oauth(auth, signed_in_resource = nil)
      ...
      # Create the user if needed
      if user.nil?
        case auth.provider
          when 'facebook'
            # Take fields that Facebook provides and use them when creating a new user
          when 'twitter'
            # Take fields that Twitter provides and use them when creating a new user
          when 'linkedin'
            # Take fields that Linkedin provides and use them when creating a new user
        end
      end
      ...
    end
    

    如果您为每个提供者实现单独的方法并在某些when 中调用它们,则对代码组织会更好。

    还可以查看 https://github.com/intridea/omniauth/wiki/Auth-Hash-Schema 以了解 env['omniauth.auth'] 的内容。

    【讨论】:

    • 嗨 Jeiwan,我有名字和姓氏,但我不知道如何在本教程中使用
    • 那么在创建用户的时候就使用first_name,像这样:first_name: auth.extra.raw_info.name 但是我觉得创建列name比较好,因为你不知道auth.extra.raw_info.name里面有什么,它也可以包含全名,如果您将全名存储在first_name 列中,那就不好了。这里的主要问题是正确创建users 表中的所有列,因为不同的提供者提供不同的信息。
    • 但是名字不会把全名放到我称之为“名字”的字段中,我找到的linkedin字段被称为“名字”,但这不起作用
    • 如果您使用此代码first_name: auth.extra.raw_info.name,那么,是的,您将在 first_name 列中有全名。对于linkedin,您应该尝试first_name: auth.extra.raw_info.firstName(不需要在名字周围加上引号)
    • 对我来说很奇怪,我尝试遵循的教程专门针对具有多种策略的omniauth,但它没有办法解决这个问题。我会尝试您对“何时”选项的建议。谢谢
    猜你喜欢
    • 2014-02-10
    • 1970-01-01
    • 1970-01-01
    • 2015-08-27
    • 2016-02-26
    • 2016-12-14
    • 1970-01-01
    • 2014-09-25
    • 1970-01-01
    相关资源
    最近更新 更多