チュートリアルで作成したユーザーモデルやログインフォームや新規登録フォームを壊し、devise、twitter認証を実装したところまでの記録です。
- Userモデルの削除
- devise gemの実装
- ルートの定義を最新のものに変更
- ローカル環境最後の大ボス(Invalid credentials)
- herokuにアップロードしたらエラー
- 反省点
- 追記
- また追記(2018/3/9)
前回の続きになります。
Userモデルの削除
自分のアプリはrailsチュートリアルを元にUserモデルを実装しているので、はじめにモデルを削除。
ターミナルで
rails destroy model User
そして適当な名前のmigrationファイルを新たに作成してテーブルも削除
(モデルとテーブルって一緒に消えないんですね。)
def change
drop_table :users
end
しかし、ここでエラー
SQLite3::ConstraintException: FOREIGN KEY constraint failed: DROP TABLE "users"
出たので、中途半端にデータベースをいじるのは諦めて、migrationファイルをいじりながらこちらの記事を参考にしてデータベースをリセット!!!(めちゃ怖かった)
ここまでやるとデータベース関連のエラーが消えたので一歩前進。
devise gemの実装
ここからが本題で、deviseの実装に取り掛かりました。
基本的に下記を参照。
はい。そして、controller、view、routeを設定して試しに、
localhost:3000/users/sign_in
で入ってみましたが、uninitialize constant Usersのエラー。
原因解決方法はこちらを参照。
自分はコントローラーを
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カラムを追加したり色々しました。
そして最終的につまづいたのはここ。
Twitterログイン実装は戦いの末、Invalid credentialsのエラー。ググってもあまり例が出てこないなあ。
— YO@Rails学習中 (@YO37377306) 2018年2月12日
意味不明でした。
ターミナルには
ERROR -- omniauth: (twitter) Authentication failure! invalid_credentials: OAuth::Unauthorized, 401 Authorization Required
との記載があり。
invalid_credentialsでググると、かなり闇が深そうで、
このあたりが関係しそうだとか、書いてあるのですが、原因は結局分からず。
翌日、色々な記事を見返していた結果、環境変数に問題があることが発覚。
下記記事によると
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実装した時にこのファイルをいじってしまっていたんですよね。
ということで、 config/initializers/omniauth.rbの余計な箇所を消した結果、無事ローカル環境ではツイッターログインできるようになりました!
ローカル環境では!
herokuにアップロードしたらエラー
ということで、本番環境ではエラーが出ました。おそらくこれまた環境変数周りではないかと思っているので、
この辺りをよく読んで勉強してみます。
反省点
この記事を最後まで読まれた方は、なんでこんなにエラー多いんだよ、と思われているかもしれませんが、反省点を挙げるなれば、
- 参照する記事を吟味せずにコーディングをスタートしてしまったこと
- 記事を読み漁っている割には本質的な情報を見逃しており、逆に細かい表記の違いでエラーを起こしてしまっていること
かなと。
次回から、初めて取り組む実装に関して記事を参照する際には
gem含めた環境のバージョンが古くないか
をよく確認して、参照する記事を絞り、少なくとも表記方法のミスを減らせればいいなと思います。
まあ、エラーが出たら出たで、勉強になるのでいいのですが。。。
追記
環境変数周りではなく、データベース周りがおかしかったようでした。
この記事でもはじめにデータベースを削除していますが、そこが中途半端になっていた模様。
何度かリセットしたり、マイグレーションファイルを整理した結果、エラーが消えました。
こちらを参照。
また、アセットパイプラインの設定を変更するのも重要なようで
こちらを参考に設定を直したところ、崩れていたレイアウトが少し直りました。
また追記(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。
次にメールアドレスログインをチュートリアルを参照して実施。
13.4 マイクロポストの画像投稿はmicropostですが、userに書き換えて実施。
あと自分はpictureじゃなくてimageにしてます。
これはこれでできて、メールアドレスログインもOK。
と思ったのですが、Twitterログインの画像が取り込まれなくなったんですよね。
rails sのログ見てみると、さっきまでhttp://-------.jpgが送信されていたのに、突然nilが送信されるようになっていました。
ググったところ、
Carrierwaveを使うと、httpじゃなくてhttpsに変換しないと読み込まれない、と。
納得。
でも、やってもだめ。はい次。
@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組み合わせるとエラーが起きるなあというのが感想です。