質問編集履歴

2 情報追加

s.k

s.k score 250

2016/11/04 15:25  投稿

SNS認証プラグインにおけるuninitialized constantエラー
今、開発中のサイトでSNS認証機能を実装したいです。
ユーザー登録時パスワードが不要になったりとユーザーにも運営側にもメリットがあるとわかりましたので取り組んでいます!
###前提・実現したいこと
twitter認証を実装したい。
facebook認証はなんとかできました。
下記の記事のコードをほぼそのまま利用させてもらってます。
[Devise+OmniAuthでQiita風の複数プロバイダ認証
](http://qiita.com/mnishiguchi/items/e15bbef61287f84b546e)
###発生している問題・エラーメッセージ
新規ユーザー登録画面上に、「twitterでログインする」リンクを作成しました。
リンクを押すと、下記画面に遷移し、数秒後にエラーが発生します。
【遷移先画面】
![イメージ説明](476762fec2c0077acbcdc13b6c1252bf.png)
【エラー内容】
```
NameError in OmniauthCallbacksController#twitter
uninitialized constant OAuthPolicy::Twitter
```
調べたところ、モデル名がRailの記法に合っていない場合に発生するエラーであると書いてありました。ただ、どうあっていないのかがよくわかりません…
###該当のソースコード
流れはこのようになっています。
```
app/controllers/omniauth_callbacks_controller.rb:10:in `callback_for_all_providers'
app/helpers/o_auth_service/get_o_auth_user.rb:7:in `call'
app/models/social_profile.rb:9:in `find_for_oauth'
app/models/social_profile.rb:17:in `save_oauth_data!'
app/c:34:in `policy'←★エラー箇所★
```
【app/models/social_profile.rb:34:in `policy'】
```ruby
32 def policy(provider, auth)
33    class_name = "#{provider}".classify
34     "OAuthPolicy::#{class_name}".constantize.new(auth) ←★OAuthPolicyをヘルパーで呼び出す際にエラーが起きている模様…★
35 end
```
以下、関連ヘルパーのコードです。
2つとも同じファイルに入っています。
★追加部分★
【app/helpers/o_auth_service/o_auth_policy.rb】★本件のエラー原因だと思われるヘルパー★
★追加部分★
```ruby
module OAuthPolicy
 class Base
   attr_reader :provider, :uid, :name, :nickname, :email, :url, :image_url,
               :description, :other, :credentials, :raw_info
 end
 class Facebook < OAuthPolicy::Base
   def initialize(auth)
     @provider   = auth["provider"]
     @uid        = auth["uid"]
     @name       = auth["info"]["name"]
     @nickname   = ""
     @email      = ""
     @url        = "https://www.facebook.com/"
     @image_url  = auth["info"]["image"]
     @description = ""
     @credentials = auth["credentials"].to_json
     @raw_info   = auth["extra"]["raw_info"].to_json
     freeze
   end
 end
 class Twitter < OAuthPolicy::Base
   def initialize(auth)
     @provider   = auth["provider"]
     @uid        = auth["uid"]
     @name       = auth["info"]["name"]
     @nickname   = auth["info"]["nickname"]
     @email      = ""
     @url        = auth["info"]["urls"]["Twitter"]
     @image_url  = auth["info"]["image"]
     @description = auth["info"]["description"].try(:truncate, 255)
     @credentials = auth["credentials"].to_json
     @raw_info   = auth["extra"]["raw_info"].to_json
     freeze
   end
 end
end
```
【o_auth_service/get_o_auth_user.rb】
【app/helpers/o_auth_service/get_o_auth_user.rb】
```ruby
module OAuthService
 class GetOAuthUser
   def self.call(auth)
     # 認証データに対応するSocialProfileが存在するか確認し、なければSocialProfileを新規作成。
     # 認証データをSocialProfileオブジェクトにセットし、データベースに保存。
     profile = SocialProfile.find_for_oauth(auth)
     # ユーザーを探す。
     # 第1候補:ログイン中のユーザー、第2候補:SocialProfileオブジェクトに紐付けされているユーザー。
     user = current_or_profile_user(profile)
     unless user
       # 第3候補:認証データにemailが含まれていればそれを元にユーザーを探す。
       user = User.where(email: email).first if verified_email_from_oauth(auth)
       # 見つからなければ、ユーザーを新規作成。
       user ||= find_or_create_new_user(auth)
     end
     associate_user_with_profile!(user, profile)
     user
   end
   private
     class << self
       def current_or_profile_user(profile)
         user = User.current_user.presence || profile.user
       end
       # 見つからなければ、ユーザーを新規作成。emailは後に確認するので今は仮のものを入れておく。
       # TEMP_EMAIL_PREFIXを手掛かりに後に仮のものかどうかの判別が可能。
       # OmniAuth認証時はパスワード入力は免除するので、ランダムのパスワードを入れておく。
       def find_or_create_new_user(auth)
         # Query for user if verified email is provided
         email = verified_email_from_oauth(auth)
         user = User.where(email: email).first if email
         if user.nil?
           temp_email = "#{User::TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com"
           user = User.new(
             username: auth.extra.raw_info.name,
             email:   email ? email : temp_email,
             password: Devise.friendly_token[0,20]
           )
           # email確認メール送信を延期するために一時的にemail確認済みの状態にする。
           user.skip_confirmation!
           # email仮をデータベースに保存するため、validationを一時的に無効化。
           user.save(validate: false)
           user
         end
       end
       def verified_email_from_oauth(auth)
         auth.info.email if auth.info.email && (auth.info.verified || auth.info.verified_email)
       end
       # ユーザーとSocialProfileオブジェクトを関連づける。
       def associate_user_with_profile!(user, profile)
         profile.update!(user_id: user.id) if profile.user != user
       end
     end
   end
end
```
###試したこと
①実は、このエラーの前にも同種のエラーが起きました。
その際は、ネットに記事が落ちていましたので、それを参考にし解決できました。
[Ruby on Rails、Controllerからhelpersフォルダのクラスを使おうとするとuninitialized constantが発生する。](http://blog.naichilab.com/entry/uninitialized_constant)
②、①ではヘルパーのフォルダ名を変更し、ヘルパー自身の名前も変更すると解決できたので、今回も同様にo_auth_policyをget_auth_policyに変更したり、別ファイルを作りそこにこのヘルパーを収納してみたりしました。ですが、できませんでした。
以上です。
よろしくお願いします((+_+))
  • Twitter

    790 questions

    Twitterは、140文字以内の「ツイート」と呼ばれる短文を投稿できるサービスです。Twitter上のほぼ全ての機能に対応するAPIが存在し、その関連サービスが多く公開されています。

  • Facebook

    442 questions

    Facebookは、実名登録制のSNS(ソーシャル・ネットワーキング・サービス)です。開発者用のデベロッパーサイトが存在し、一般ユーザーによるFacebook向けアプリケーション開発が可能です。

  • Ruby on Rails 4

    2542 questions

    Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

1 情報の追加

s.k

s.k score 250

2016/11/04 15:25  投稿

SNS認証プラグインにおけるuninitialized constantエラー
今、開発中のサイトでSNS認証機能を実装したいです。
ユーザー登録時パスワードが不要になったりとユーザーにも運営側にもメリットがあるとわかりましたので取り組んでいます!
###前提・実現したいこと
twitter認証を実装したい。
facebook認証はなんとかできました。
下記の記事のコードをほぼそのまま利用させてもらってます。
[Devise+OmniAuthでQiita風の複数プロバイダ認証
](http://qiita.com/mnishiguchi/items/e15bbef61287f84b546e)
###発生している問題・エラーメッセージ
新規ユーザー登録画面上に、「twitterでログインする」リンクを作成しました。
リンクを押すと、下記画面に遷移し、数秒後にエラーが発生します。
【遷移先画面】
![イメージ説明](476762fec2c0077acbcdc13b6c1252bf.png)
【エラー内容】
```
NameError in OmniauthCallbacksController#twitter
uninitialized constant OAuthPolicy::Twitter
```
調べたところ、モデル名がRailの記法に合っていない場合に発生するエラーであると書いてありました。ただ、どうあっていないのかがよくわかりません…
###該当のソースコード
流れはこのようになっています。
```
app/controllers/omniauth_callbacks_controller.rb:10:in `callback_for_all_providers'
app/helpers/o_auth_service/get_o_auth_user.rb:7:in `call'
app/models/social_profile.rb:9:in `find_for_oauth'
app/models/social_profile.rb:17:in `save_oauth_data!'
app/c:34:in `policy'←★エラー箇所★
```
【app/models/social_profile.rb:34:in `policy'】
```ruby
32 def policy(provider, auth)
33    class_name = "#{provider}".classify
34     "OAuthPolicy::#{class_name}".constantize.new(auth) ←★OAuthPolicyをヘルパーで呼び出す際にエラーが起きている模様…★
35 end
```
以下、関連ヘルパーのコードです。
2つとも同じファイルに入っています。
【o_auth_service/o_auth_policy.rb】★本件のエラー原因だと思われるヘルパー★
★追加部分★
【app/helpers/o_auth_service/o_auth_policy.rb】★本件のエラー原因だと思われるヘルパー★
★追加部分★
```ruby
module OAuthPolicy
 class Base
   attr_reader :provider, :uid, :name, :nickname, :email, :url, :image_url,
               :description, :other, :credentials, :raw_info
 end
 class Facebook < OAuthPolicy::Base
   def initialize(auth)
     @provider   = auth["provider"]
     @uid        = auth["uid"]
     @name       = auth["info"]["name"]
     @nickname   = ""
     @email      = ""
     @url        = "https://www.facebook.com/"
     @image_url  = auth["info"]["image"]
     @description = ""
     @credentials = auth["credentials"].to_json
     @raw_info   = auth["extra"]["raw_info"].to_json
     freeze
   end
 end
 class Twitter < OAuthPolicy::Base
   def initialize(auth)
     @provider   = auth["provider"]
     @uid        = auth["uid"]
     @name       = auth["info"]["name"]
     @nickname   = auth["info"]["nickname"]
     @email      = ""
     @url        = auth["info"]["urls"]["Twitter"]
     @image_url  = auth["info"]["image"]
     @description = auth["info"]["description"].try(:truncate, 255)
     @credentials = auth["credentials"].to_json
     @raw_info   = auth["extra"]["raw_info"].to_json
     freeze
   end
 end
end
```
【o_auth_service/get_o_auth_user.rb】
```ruby
module OAuthService
 class GetOAuthUser
   def self.call(auth)
     # 認証データに対応するSocialProfileが存在するか確認し、なければSocialProfileを新規作成。
     # 認証データをSocialProfileオブジェクトにセットし、データベースに保存。
     profile = SocialProfile.find_for_oauth(auth)
     # ユーザーを探す。
     # 第1候補:ログイン中のユーザー、第2候補:SocialProfileオブジェクトに紐付けされているユーザー。
     user = current_or_profile_user(profile)
     unless user
       # 第3候補:認証データにemailが含まれていればそれを元にユーザーを探す。
       user = User.where(email: email).first if verified_email_from_oauth(auth)
       # 見つからなければ、ユーザーを新規作成。
       user ||= find_or_create_new_user(auth)
     end
     associate_user_with_profile!(user, profile)
     user
   end
   private
     class << self
       def current_or_profile_user(profile)
         user = User.current_user.presence || profile.user
       end
       # 見つからなければ、ユーザーを新規作成。emailは後に確認するので今は仮のものを入れておく。
       # TEMP_EMAIL_PREFIXを手掛かりに後に仮のものかどうかの判別が可能。
       # OmniAuth認証時はパスワード入力は免除するので、ランダムのパスワードを入れておく。
       def find_or_create_new_user(auth)
         # Query for user if verified email is provided
         email = verified_email_from_oauth(auth)
         user = User.where(email: email).first if email
         if user.nil?
           temp_email = "#{User::TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com"
           user = User.new(
             username: auth.extra.raw_info.name,
             email:   email ? email : temp_email,
             password: Devise.friendly_token[0,20]
           )
           # email確認メール送信を延期するために一時的にemail確認済みの状態にする。
           user.skip_confirmation!
           # email仮をデータベースに保存するため、validationを一時的に無効化。
           user.save(validate: false)
           user
         end
       end
       def verified_email_from_oauth(auth)
         auth.info.email if auth.info.email && (auth.info.verified || auth.info.verified_email)
       end
       # ユーザーとSocialProfileオブジェクトを関連づける。
       def associate_user_with_profile!(user, profile)
         profile.update!(user_id: user.id) if profile.user != user
       end
     end
   end
end
```
###試したこと
①実は、このエラーの前にも同種のエラーが起きました。
その際は、ネットに記事が落ちていましたので、それを参考にし解決できました。
[Ruby on Rails、Controllerからhelpersフォルダのクラスを使おうとするとuninitialized constantが発生する。](http://blog.naichilab.com/entry/uninitialized_constant)
②、①ではヘルパーのフォルダ名を変更し、ヘルパー自身の名前も変更すると解決できたので、今回も同様にo_auth_policyをget_auth_policyに変更したり、別ファイルを作りそこにこのヘルパーを収納してみたりしました。ですが、できませんでした。
以上です。
よろしくお願いします((+_+))
  • Twitter

    790 questions

    Twitterは、140文字以内の「ツイート」と呼ばれる短文を投稿できるサービスです。Twitter上のほぼ全ての機能に対応するAPIが存在し、その関連サービスが多く公開されています。

  • Facebook

    442 questions

    Facebookは、実名登録制のSNS(ソーシャル・ネットワーキング・サービス)です。開発者用のデベロッパーサイトが存在し、一般ユーザーによるFacebook向けアプリケーション開発が可能です。

  • Ruby on Rails 4

    2542 questions

    Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る