認証(翻訳)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社エンジニアの「?」を「!」に。原著者の許諾を得て翻訳・公開いたします。GRails5中級チュートリアルはセットアップが短めで、RDBMSにはPostgreSQL、テストにはRSpecを用います。原文が非常に長いので分割します。章ごとのリンクは順次追加します。Railsチュートリアル(https://railstutorial.jp/)(Railsチュートリアル)とは著者も対象読者も異なります。投稿機能そろそろ投稿機能の実装に取りかかれるようになってきました。このアプリの目的は、ユーザーが自分の好みに近い人に出会えるようにすることなので、投稿の著者を識別できるようにしなければなりません。これを行うには認証システムが必要です。gemを使うことにします。認証システムを自作することもできなくはありませんが、相当頑張らないといけないでしょう。本チュートリアルでは楽な道を進むことにします。DeviseはRailsコミュニティで人気の高いgemでもあります。新しいブランチを切りましょう。authentication他のgemと同様、Deviseのセットアップはドキュメントに従って進めます。幸いなことに、セットアップは非常に簡単です。Gemfileに以下を追加します。'devise'以下のコマンドを実行します。devise:install実行後、コマンドプロンプトにいくつか指示が表示されます。本チュートリアルではmailerを使わないので、追加の設定は不要です。Modelの基礎を取り急ぎ読んで、ActiveRecordやActiveModelに慣れておく必要があります。それでは、DeviseのジェネレータでUserモデルを作成しましょう。User以下を実行してアプリのデータベースを初期化します。db:create続いて、以下を実行してデータベースに新しいテーブルを作成します。db:migrate以上で認証システムの技術面のセットアップは終わりです。これで、Deviseが提供するメソッドを用いて新しいユーザーを作成できるようになりました。変更をcommitしましょう。gemをインストールすると、バックエンドの機能の他にデフォルトのビューも使えるようになります。以下を実行してルーティングを表示してみましょう。routesさっきまではrootへのルーティングしかなかったのに、新しいルーティングがたくさんできているのがわかります。wikiのドキュメントを開いて情報を見つけることができます。自分と同じ問題で悩んだ人はたくさんいるはずなので、ググって答えを見つけられる可能性はかなりあります。wiki日本語目次もどうぞ。ルーティングをいくつか試してみましょう。localhost:3000/users/sign_inをブラウザで開くと、以下のようなサインインページが表示されるはずです。localhost:3000/users/sign_upを開いてみると、同じようなページが表示されます。viewsディレクトリを見てみると、どこにもDeviseのディレクトリがありません。Damn!」というところです。Deviseのドキュメントに記載されているように、Deviseのビューを変更するにはジェネレータを使ってビューを生成する必要があります。devise:viewsviewsディレクトリを見てみると、Devise用のディレクトリが生成されているのがわかります。ここでサインアップページやログインページの表示方法を変更できます。このアプリではログインページの実装の方が素直になるので、まずはログインページから変更します。この登録ページに機能を追加したいので、少し手間をかける必要があります。ログインページapp/views/devise/sessions/new.html.erbを開きます。ログインページのビューはこのファイルに保存されており、その実体は単なるログインフォームです。このフォームの生成に[form_for](http://api.rubyonrails.org/v5.1/classes/ActionView/Helpers/FormHelper.html)メソッドが使われていることにお気づきでしょうか。form_forはフォームの生成に便利なRailsのメソッドです。このフォームのスタイルを変更してBootstrapを適用することにします。このファイルの内容を以下で置き換えます(Gist)。%>特別なことは何もしていません。このフォームをBootstrapのフォームに変えるためにメソッド名をbootstrap_form_forに変更し、form-controlクラスをフィールドに追加しているだけです。このメソッドの引数の書き方を見てみましょう。各引数を1行ずつ分けて書いてあります。このように書いた理由は、コードが横に長くなるのを避けるためです。読みやすさのため、コード行は最大80文字を超えないようにするのが普通です。本チュートリアルでは今後もこのスタイルでコードを書くことにします。この時点でlocalhost:3000/users/sign_inをブラウザで開くと、以下のエラーが表示されます。gemの追加が必要です。Gemfileに以下を追加します。'bootstrap_form'続いて以下を実行します。installこれで、以下のようにログインページが表示されるはずです。変更をcommitします。gem."Bootstrapのグリッドシステムをページに適用するには、以下のようにログインフォームをBootstrapのコンテナでラップします(Gist)。</div></div>このログインフォームの幅は12カラムのうち6カラムを使い、オフセットは3カラムにします。画面の小さなデバイスではフル画面の幅でフォームが表示されます。Bootstrapのグリッドはこのように動作します。ここでさらにcommitしておきましょう。変更量が少ないのではないかとお思いかもしれませんが、私は普段このぐらいの粒度でcommitしています。私は、ある部分に明確な変更を実装したらcommitするようにしています。することで変更が追いやすくなり、コードの移り変わりも理解しやすくなると私は思います。container"ログインページにアクセスするURLを、/users/sign_inから/loginに変えるとよさそうです。それにはルーティングの変更が必要ですが、そのためにアクションの場所を知っておく必要があります。ログインページにアクセスすると、その場所にあるアクションを呼び出します。gem自身の中にあります。Deviseのドキュメントを読むと、Deviseのコントローラはすべてdeviseディレクトリの下にあることがわかります。大した発見ではありませんが(U_U)。ルーティングの単純な変更はdevise_scopeメソッドで行えます。routes.rbファイルを開いて以下を追加します。'devise/sessions#new'end変更をcommitします。/login"ログインページはとりあえずこのままにしておきましょう。サインアップページlocalhost:3000/users/sign_upをブラウザで開くと、こちらはDeviseのデフォルトのサインアップページのままになっています。先ほど申し上げたとおり、このページには少し手間をかける必要があります。usersテーブルに:nameカラムを追加して、Userオブジェクトで:name属性を扱えるようにするためです。schema.rbファイルに少し変更を加えます。Recordマイグレーションをひととおり読んでおくことをおすすめします。最初に、usersテーブルにカラムを追加しなければなりません。これは、マイグレーションファイルを新しく作成し、change_tableメソッドでカラムを追加することで行えます。開発はまだ始まったばかりなので、アプリはまだデプロイされていません。そこで、既存のdevise_create_usersマイグレーションファイルにカラムを追加してデータベースを再作成することにします。以下のコマンドを実行して、データベースの削除と再作成を行ってから、マイグレーションを実行します。データベース操作中はRailsサーバーを停止しておきましょう。db:migrateこれでusersテーブルにカラムが追加され、schema.rbファイルが変更されました。追加した属性を送信できるようにするには、Deviseのコントローラで属性を受信できるよう、コントローラレベルの変更を少々行わなければなりません。Deviseコントローラの変更方法はいくつか考えられます。Deviseのジェネレータでコントローラを生成する方法や、ファイルを1つ作成して変更したいコントローラやメソッドをそこで指定する方法があります。どちらの方法でも構いませんが、ここでは後者の方法にします。app/controllersディレクトリに移動してregistrations_controller.rbファイルを作成し、以下のコードをファイルに追加します(Gist)。endend上のコードによってsign_up_paramsメソッドとaccount_update_paramsメソッドがオーバーライドされ、:name属性を受信できるようになります。見てのとおり、2つのメソッドはDeviseのRegistrationsControllerクラスにあるので、このクラスを指定してメソッドを変更しました。2つのメソッドがオーバーライドされるよう、このコントローラをルーティングの内部で指定しなければなりません。route.rbで以下の変更を行います。:users上を以下のコードに置き換えます。"registrations"}変更をcommitします。RegistrationsController"次にnew.html.erbファイルを開きます。app/views/devise/registrations/new.html.erb今度も同様に、フォーム以外のコードをすべて削除し、フォームをBootstrapのフォームに変えます。今回はnameフィールドを追加します(Gist)。%>変更をcommitします。field"フォームをBootstrapコンテナでラップし、テキストを追加します(Gist)。</div></div>変更をcommitします。container"ログインページのときと同様、サインアップページのURLもusers/sign_upから/signupに変えるのがよさそうです。routes.rbファイルに以下のコードを追加します。'devise/registrations#new'end変更をcommitします。/signup"先に進む前に、スタイルを少し変更しておきましょう。app/assets/sytlesheets/partialsに移動してsignup.scssファイルを作成し、以下のCSSコードを追加します(Gist)。20px;}application.scssファイル内でpartialsからファイルをimportしていないので、ここでやっておきましょう。partials/layout/*のすぐ上の行でpartialsディレクトリからすべてのファイルをimportします。変更後のapplication.scssは次のようになります(Gist)。"partials/layout/*";変更をcommitします。application.scss"Webサイト全体の外観に別の変更を加えます。app/assets/stylesheets/baseディレクトリに移動してdefault.scssを作成し、以下のCSSコードを追加します(Gist)。none;}上ではWebサイト全体に一般的なスタイル変更をいくつか適用しています。remが10pxを表すようにします。rem単位がよくわからない場合は、こちらのチュートリアルをご覧ください。Bootstrapフォームでラベル文字を表示したくないので、以下をCSSで設定しています。none;}$backgroundColor変数が使われていることにお気づきでしょうか。この変数はまだ設定されていないので、variables.scssファイルを開いて以下を追加します。Variables」の下にimportを追加します。追加後のapplication.scssファイルは次のようになります。"base/default";...変更をcommitします。application.scss"ナビゲーションバーの更新ここまでに、homeページ、ログインページ、サインアップページを作りました。このあたりで、これらのページを互いにつないでユーザーがWebサイトを楽に操作できるようにしましょう。ナビゲーションバーにサインアップページとログインページへのリンクを置くことにします。_navigation.html.erbファイルを開きます。app/views/layouts/_navigation.html.erbここにコードを少し追加することにします。ここには今後さらにコードを追加する予定です。このままだとファイルのコード量が増え、管理やテストがやりにくくなってしまいます。長いコードを扱いやすくするために、もっと短いコード(チャンク)に分割することにします。本チュートリアルではパーシャルを使って行います。コードを追加する前に、現在の_navigation.html.erbのコードをパーシャルに切り出してみましょう。ここで、アプリのナビゲーションバーの使われ方について簡単に説明しておきます。ナビゲーションバーを2つに分け、一方は画面サイズにかかわらず常に表示し、他方は大画面のときだけ表示して小画面では隠すようにします。.container要素の内部は以下のような構造になる予定です(Gist)。-->app/views/layoutsディレクトリの下にnavigationディレクトリを作成し、その下に_header.html.erbパーシャルファイルを作成します。app/views/layouts/navigation/_header.html.erb_navigation.html.erbファイルの.navbar-headerセクションをまるごとカットして_header.html.erbファイルに貼り付けます。navigationディレクトリの下に別の_collapsible_elements.html.erbパーシャルファイルを作成します。app/views/layouts/navigation/_collapsible_elements.html.erb_navigation.html.erbファイルの.navbar-collapseセクションをまるごとカットして_collapsible_elements.html.erbファイルに貼り付けます。今度は2つのパーシャルを_navigation.html.erbファイルの内部でレンダリングしましょう。変更後のファイルは以下のようになります。--></nav>この時点でhttp://localhost:3000をブラウザで表示しても、表示結果は何も変わっていません。コードを少し整理して開発を進める準備を整えただけです。ナビゲーションバーにリンクを追加する準備が整いました。_collapsible_elements.html.erbファイルを再度開きます。app/views/layouts/_collapsible_elements.html.erbこのファイルにリンクを追加します。置き換え後のファイルは以下のようになります。-->ここでコードの変更点について少し補足します。最初に、2行目で要素のidをnavbar-collapsible-contentに変更しました。これはBootstrapの機能で、コンテンツを折りたたみ可能にするために必要です(デフォルトのidはbs-example-navbar-collapse-1)。この機能をトリガするために、data-target属性を持つボタンが_header.htmlファイルにあります。views/layouts/navigation/_header.html.erbファイルを開いて、data-target属性をdata-target="#navbar-collapsible-content"に変更します。これで、ボタンも折りたたみ可能になりました。次に、_collapsible_elements.html.erbにif/elseロジックがいくつかあり、そこにDeviseのuser_signed_in?メソッドがあります。これは、ユーザーがサインインしているかどうかでリンクを変更するためのものです。ビューのこうしたif/elseロジックを放置するのはよくありません。ビューは判断を一切行わず、ひたすら情報を吐き出す「静的な」記述に徹するべきです。このロジックは後ほどヘルパーを使ってリファクタリングする予定です。最後に、このファイルにpc-menuとmobile-menuという2つのCSSクラスがあります。これらのクラスは、画面サイズが変わったときのリンクの表示を制御するのに使います。これらのクラスのCSSを追加してみましょう。このディレクトリは前の手順で作成済みです)、そこにdesktop.scssファイルとmobile.scssファイルを作成します。Scssファイルを2つ作るのは、画面サイズごとに設定を変えるためです。desktop.scssファイルに以下を追加します(Gist)。}}mobile.scssファイルに以下を追加します(Gist)。}}CSSのメディアクエリがよくわからない方はこちらをお読みください。次に、responsiveディレクトリの内容をapplication.scssでimportします。以下のようにファイルの末尾にimportを追加します(Gist)。"responsive/*";次はnavigation.scssファイルを開きます。app/assets/stylesheets/partials/layout/navigation.scssこのファイルのnav要素セレクタの内側に以下を追加して、ナビゲーションバーのスタイルを微調整します(Gist)。0;}続いて、nav要素の外に以下のCSSコードを追加します(Gist)。!important;}ここまでを終えると、アプリにユーザーがログインしていないときの外観は以下のようになっているはずです。アプリにユーザーがログインしたときの外観は以下のようになります。画面サイズを小さくしたときの外観は以下のようになります。変更をcommitします。style"これで基本的な認証機能ができあがり、要求を満たせました。今度はauthenticationブランチをmasterブランチにmergeしましょう。authentication今度も変更の概要が表示されます。authenticationブランチが不要になったので削除します。コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。チュートリアル第2版の監修および半分程度を翻訳、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れて更新翻訳中。enno.jpを運営。実は最近Go言語が好きで、Goで書かれたRubyライクなGoby言語のメンテナーでもある。仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。Storageを使ってはいけない(翻訳)#Tags#会社紹介#自社サービス#勉強会#Rails#PHP#デザイン#実績#週刊RailsウオッチCONTACTお気軽にご相談ください。(翻訳)CONTACTTechRachoでは、パートナーシップをご検討いただける方からのご連絡をお待ちしております。お気軽にご意見・ご相談ください。