アカウント有効化の導入に苦戦した話

Webエンジニアへの道

はじめに

circleCIの設定が終わり次はメール送信による通知機能を実装しようということで、まずはアカウントの有効化を導入することになりました。Railsチュートリアルでやったことなので、それに沿ってやればすぐ終わるだろうと高を括っていたら、意外と苦戦したので、今回はそのことについて話そうと思います。

そもそも一周やった時にあまり理解できていなかった

そもそもrailsチュートリアルを一周したときは、サンプルアプリを完成させるということに力を注いでいたので、これよくわからないなってコードがあっても、割とガンガン進んでいました。アカウント有効化とかの部分は特に複雑だったので、もう一回やってみると、これはちゃんと調べないといけないなということが結構出てきました。例えば、

・digestとtokenは何のために書いているのか?

一週目の認識としてはwebサービスのセキュリティ的につけないといけないものといものでしたが、今回ちゃんと調べたところ、digestは、有効化に必要な情報をそのままDBに保存すると危険なので、ハッシュ化(ハッシュ値と呼ばれる規則性のない固定長の値を求め、その値によって元のデータを置き換えること)してデータを解析しにくくするためのもので、tokenはパスワードと同じような秘匿されるべき情報でパスワードとの違いは、ユーザー自体が生成したり、管理するものですがtokenは、コンピュータが自動で生成する点です。とはいうものの掴みづらいし、難しいですね。セキュリティの関係のことはもっとやっていくうちに分かっていくのでしょうか。。

ActiveModel::SecurePassword.min_costって何?

この部分はチュートリアル一週目の時は何か、ごちゃごちゃしているなと思って、ただコピペしてしまっていました。よくないですね。

2回目でもuserモデルでUser.digestを定義するときにActiveModel::SecurePassword.min_costというものを使用しているのですが、これが何をやっているのかいまいちわかりませんでした。それはこちらの記事によるとhttps://qiita.com/shinya_ichinoseki/items/cedde49adc1d1e886195

ActiveModel::SecurePassword.min_costがtrueの時はRails.env.test(テスト環境)を表すらしく、Rails.env.test?を使った方が分かりやすいのではとメンターの方に言われ、

 

このように変更しました。三項演算子ではなくif文を使用している理由は後で述べます。こちらの方が前よりは断然何を行っているかがわかりやすいですね。

RSpecでエラーめちゃ出る

アカウントの有効化を実装したの良いのですが、テスト時にめちゃくちゃエラーがでるようになってしまいました。↓プロフィールページのテスト,修正前のprofile_spec.rbの一部

 

・エラーが出ていた理由

アカウント有効化を実装していたのに、テストの方は有効化することを無視してlogin_pathに飛ぼうとしていたからです。本当分かりやすいミスですね、有効化してないのにログインできるわけありません(笑)

・解決策

理由は分かっていましたが、どういうメソッドを定義したらいいんだと、ハマってしまいました。解決策として、activate(user)というのを定義して、それをlogin_userの上に記しました。詳しくは私のgithubのコードを見て頂ければと思います。(https://github.com/br-to/game-share/tree/master/spec)色々試してこいつ動くぞ!ってなったのが下のコードです。

上でも一応動きますが、ちなみにメンターの方に示していただいたのが

え、これだけでいいの?ってなりましたが考えてみれば、activatedがfalseからtrueになれば有効化は出来ているわけですから、これだけで問題ないのです。上の2行のコードは無駄でしかありません。

rubocopに怒られまくる

railsチュートリアルに沿ったコードの書き方をしているとrubocopさんから色んな警告を受けました。

Style/MultilineTernaryOperator: Avoid multi-line ternary operators, use if or unless instead.  

直訳すると「複数行にわたる三項演算子を避けて、代わりにifかuselessを使いなさい」ですね。

上でdigestを定義するとき、if文使ったのはこのためです。

Rails/SaveBang: Use update! instead of update if the return value is not checked.

直訳で「戻り値にチェックがない場合、updateの代わりにupdate!を使いなさい。」ですね。if文とかじゃなければupdateではなく、update!を使った方がよいということです。

この感嘆符有り無しの問題で私はまた結構ハマりました。。updateでは有効化がうまくいくのに、update!では有効化が出来ずエラーになってしまったからです。

 

☝update!にしたときでたエラー

感嘆符について調べるとupdate、saveのように!がない場合はnilを返して、update!やsave!のように!が付くと、例外を発生させる、つまり異常があった時に!をつけることで気づくことが出来るということですね。

それで、次に感嘆符は分かったけど、どうやってこのエラー解決するんや!ってなりました。これについても検索すれば割とすぐに見つかって、allow_nilというものをバリテーションに含めればよいということでした。allow_nilはnilの場合、検証をスキップするものです(Ruby on Rails5 アプリケーションプログラミングより)

これでうまく行きました☻

これでも確かに、エラーは消すことは出来ますが、presence: trueとallow_nilの組み合わせはよろしくないので、Railsチュートリアルに書いてあるようにupdate!の代わりにupdate_attributeを用いるのが正解でした。

ちなみにupdate_attributeとするとバリーテーションにかからないようにすることが出来ます。この場合allow_nilは不要でした!😳

ただupdate_attributeに変更したら、次はrubocopにupdate_attributeを使用することを避けなさいという警告を受けます。

Rails/SkipsModelValidations: Avoid using update_attribute because it skips validations.

なのでこの場合は警告をキャンセルさせればよいので、これをrubocopの設定をしているファイルに入れます

 
これでうまく行きました!😆

まとめ

アカウント有効化なかなか手強かったです。書く内容もいつもより多くなってしまいました。メール送信についての話もしようと思いましたが別の機会にします。次からはよくわからんなと思っても、コピペで凌ごうとせず、色々納得するまで調べないといけませんね、今回みたいに痛い目に合うかもしれないので!

コメント

タイトルとURLをコピーしました