プチゆる週末PJT

コンサル会社で働きながら、プログラミング学習者の「作ってみた」を応援するサイト「Eggineer」の開発・運営を行なっていました。

twtterログインとの死闘(devise+omniauth)

チュートリアルで作成したユーザーモデルやログインフォームや新規登録フォームを壊し、devise、twitter認証を実装したところまでの記録です。

f:id:YO37377306:20180326174234j:plain

 Photo by eflon | Flickr 

前回の続きになります。

www.eggineer.info

Userモデルの削除

自分のアプリはrailsチュートリアルを元にUserモデルを実装しているので、はじめにモデルを削除。

ターミナルで

rails destroy model User

そして適当な名前のmigrationファイルを新たに作成してテーブルも削除

(モデルとテーブルって一緒に消えないんですね。)

def change
 drop_table :users
end 

qiita.com

しかし、ここでエラー

SQLite3::ConstraintException: FOREIGN KEY constraint failed: DROP TABLE "users" 

出たので、中途半端にデータベースをいじるのは諦めて、migrationファイルをいじりながらこちらの記事を参考にしてデータベースをリセット!!!(めちゃ怖かった)

qiita.com

ここまでやるとデータベース関連のエラーが消えたので一歩前進。

devise gemの実装

ここからが本題で、deviseの実装に取り掛かりました。

基本的に下記を参照。

qiita.com

はい。そして、controller、view、routeを設定して試しに、

localhost:3000/users/sign_in

で入ってみましたが、uninitialize constant Usersのエラー。

原因解決方法はこちらを参照。

stackoverflow.com

自分はコントローラーを

devise_for :users, controllers: {
  confirmations: 'users/confirmations',
  passwords:     'users/passwords',
  registrations: 'users/registrations',
  sessions:      'users/sessions',
}

としていたんですが、usersではなくuserにしたら

devise_for :users, controllers: {
  confirmations: 'user/confirmations',
  passwords:     'user/passwords',
  registrations: 'user/registrations',
  sessions:      'user/sessions',
}

/users/sign_inの画面が出ました(涙)

解決に至るまでなかなかの時間を要しました。

ユーザー登録、ログインは可能なことを確認。

そして、そのまま先ほどのリンク先に倣って日本語化。

ここまででリンク先の内容はひと段落。

また、単数形か複数形か問題に関しては、modelなどでも不具合があり、時間を取られました。

ルートの定義を最新のものに変更

その他、エラー出た箇所といえば、パスに関して参照する記事によって

user_omniauth_authorize_path(:twitter)

と書かれていたり、

user_twitter_omniauth_authorize_path

と書かれていたりしますが、gemのバージョンが新しい場合は

user_twitter_omniauth_authorize_path

を使うことになっているようでした。

これも気づくまでに時間を要しました。

ローカル環境最後の大ボス(Invalid credentials)

そのあとは、下記の記事を参考にして、deviseにusernameカラムを追加したり色々しました。

ruby-rails.hatenadiary.com

qiita.comqiita.com

そして最終的につまづいたのはここ。

意味不明でした。

ターミナルには

ERROR -- omniauth: (twitter) Authentication failure! invalid_credentials: OAuth::Unauthorized, 401 Authorization Required

との記載があり。

invalid_credentialsでググると、かなり闇が深そうで、

qiita.com

このあたりが関係しそうだとか、書いてあるのですが、原因は結局分からず。

翌日、色々な記事を見返していた結果、環境変数に問題があることが発覚。

下記記事によると

github.com

Remember that config.omniauth adds omniauth provider middleware to your application. This means you should not add this provider middleware again in config/initializers/omniauth.rb as they'll clash with each other and result in always-failing authentication.

 config/initializers/omniauth.rbには余計なこと書くなと。

前回devise使わないでomniauth実装した時にこのファイルをいじってしまっていたんですよね。

qiita.com

ということで、 config/initializers/omniauth.rbの余計な箇所を消した結果、無事ローカル環境ではツイッターログインできるようになりました!

ローカル環境では!

herokuにアップロードしたらエラー

ということで、本番環境ではエラーが出ました。おそらくこれまた環境変数周りではないかと思っているので、

qiita.com

devcenter.heroku.com

この辺りをよく読んで勉強してみます。

反省点

この記事を最後まで読まれた方は、なんでこんなにエラー多いんだよ、と思われているかもしれませんが、反省点を挙げるなれば、

  1. 参照する記事を吟味せずにコーディングをスタートしてしまったこと
  2. 記事を読み漁っている割には本質的な情報を見逃しており、逆に細かい表記の違いでエラーを起こしてしまっていること

かなと。

次回から、初めて取り組む実装に関して記事を参照する際には

gem含めた環境のバージョンが古くないか

をよく確認して、参照する記事を絞り、少なくとも表記方法のミスを減らせればいいなと思います。

まあ、エラーが出たら出たで、勉強になるのでいいのですが。。。

追記

環境変数周りではなく、データベース周りがおかしかったようでした。

この記事でもはじめにデータベースを削除していますが、そこが中途半端になっていた模様。

何度かリセットしたり、マイグレーションファイルを整理した結果、エラーが消えました。

こちらを参照。

teratail.com

 

また、アセットパイプラインの設定を変更するのも重要なようで

www.transnet.ne.jp

こちらを参考に設定を直したところ、崩れていたレイアウトが少し直りました。

また追記(2018/3/9)

devise+omniauthでTwitterログイン実装したのですが、プロフィール画像もデータベースを保存できるようにしました。

ただ、EggineerはTwitterログインとメールアドレスログインどちらも可能なので、Twitterログインの場合はTwitterプロフィール画像を、メールアドレスログインの場合はCarrierWave(gem)を使って画像をアップロードしようとしたら、上手くいきませんでしたので、報告です。

始めはTwitterから画像を持ってくる処理を実装。

user.username = auth["info"]["nickname"]

とか

username: auth.info.nickname

とかapp/models/user.rbに書いたと思うのですが、そこにimageも足してあげる。

そしてviewページに

<%= image_tag(@user.image) %>

みたいな感じで書くと出力できます。

はい、TwitterログインはOK。

 

次にメールアドレスログインをチュートリアルを参照して実施。

railstutorial.jp

13.4 マイクロポストの画像投稿はmicropostですが、userに書き換えて実施。

あと自分はpictureじゃなくてimageにしてます。

これはこれでできて、メールアドレスログインもOK。

と思ったのですが、Twitterログインの画像が取り込まれなくなったんですよね。

rails sのログ見てみると、さっきまでhttp://-------.jpgが送信されていたのに、突然nilが送信されるようになっていました。

ググったところ、

stackoverflow.com

Carrierwaveを使うと、httpじゃなくてhttpsに変換しないと読み込まれない、と。

納得。

でも、やってもだめ。はい次。

stackoverflow.com

@profile.profile_image = auth.info.image

と書いていたところを、

@profile.remote_profile_image_url = auth.info.image

に直せと。

remote_ _urlの意味は知りませんが、他の方法もないので試しにやってみたらTwiiterの画像もDBに取り込んでくれるようになりました。

remote_image_url:auth.info.image.gsub('http', 'https')

自分はこんな感じで実装。

 

やはりgem組み合わせるとエラーが起きるなあというのが感想です。