Railsチュートリアル 第2章 2.2 Usersリソース
2.2 Usersリソース
・2.1.1節で設定したユーザーのモデル設定と、それを表示するためのWebインターフェイスを組み合わせて「Usersリソース」を作る。
・これによって、ユーザーという概念をオブジェクトとして扱い、HTTPプロトコルに沿って作成/取得/更新/削除などの操作が行えるようになる。
・HTTPとは、"Hyper Text Transfer Protocol"の略で、Webサーバとクライアントが通信するときの手順を決めた規格のこと。簡単に言うと、ブラウザがサーバに送るリクエストの通信の規格みたいなもの?
・Usersリソースは、RoRの機能であるscaffoldジェネレータを使って作る。できたコードを理解する必要はない。
・scaffoldとは「足場」の意味で、家を建てるときに組む足場のこと。データの雛形を簡単に作成するコマンドみたいなもの?
・scaffoldコマンドを作るときには、以下のように、リソース名を指定し、属性(メンバ変数)の名前と型を指定しておく。なお、id:integerはデフォルトでついてくるので指定する必要はない。
$ rails generate scaffold User name:string email:string Running via Spring preloader in process 4145 invoke active_record create db/migrate/20200409173002_create_users.rb create app/models/user.rb invoke test_unit create test/models/user_test.rb create test/fixtures/users.yml invoke resource_route route resources :users invoke scaffold_controller create app/controllers/users_controller.rb invoke erb create app/views/users create app/views/users/index.html.erb create app/views/users/edit.html.erb create app/views/users/show.html.erb create app/views/users/new.html.erb create app/views/users/_form.html.erb invoke test_unit create test/controllers/users_controller_test.rb invoke helper create app/helpers/users_helper.rb invoke test_unit invoke jbuilder create app/views/users/index.json.jbuilder create app/views/users/show.json.jbuilder create app/views/users/_user.json.jbuilder invoke test_unit create test/system/users_test.rb invoke assets invoke coffee create app/assets/javascripts/users.coffee invoke scss create app/assets/stylesheets/users.scss invoke scss create app/assets/stylesheets/scaffolds.scss
・次に、データベースのマイグレートという作業をする必要がある。今、確かにUsersリソースの雛形はできたが、実際にユーザーに登録してもらった内容はデータベースとしてSQLなどで管理する必要があり、このままでは使えない。リソースからデータベースを自動で作ってくれる機能がマイグレーションで、作ったモデルをデータベースの形になおしてくれる。
www.transnet.ne.jp
$ rails db:migrate == 20200409173002 CreateUsers: migrating ====================================== -- create_table(:users) -> 0.0015s == 20200409173002 CreateUsers: migrated (0.0020s) =============================
2.2.1 ユーザーページを探検する
・ここまでやると、プレビューでUserの登録/表示/編集/削除ができるようになる。例のごとくプレビューをブラウザの方で開くと未だ"hello, world!"と表示されるが、そのURLに/usersをつけてみると全ユーザーを表示するページが開ける。/usersが全ユーザーの表示 index、/users/1がid:1のユーザーの表示 show、/users/1/editがid:1のユーザーの編集の edit,/users/newが新規ユーザーの作成 newというアクションにそれぞれ対応している。
・演習
Q1.User was successfully createdの文章のCSSはどうなっている?リロードするとどうなる?
A1.
User was successfully created.
からに変化した。つまり、動的にページが作成されている。Q2.email欄を空白にしてユーザーを作るとどうなる?
A2.Emailに値を持たないUserが作られる。
Q3.正しくないEmailを入力するとどうなる?
A3.そのまま登録される。つまり、ユーザー名の重複、不正なアドレス、Name/Emailのヌケをチェックする機能をつけなければならない。
Q4.上記のユーザーを削除するとなんと言われる?
A4.User was successfully destroyed.
2.2.2 MVCの挙動
・ここまで、scaffoldジェネレータによってUsersリソースが作成されていることは確認できた。実際これがどのように動いているのかを、MVCの挙動を見て理解する。
①ブラウザが/usersというURLのリクエストをRailsサーバーに送る。(ブラウザ→routes.rb)
②routerがリクエストを受け取り、routerによってControllerのindexアクションに割り当てられる。(routes.rb→users_controller.rb)
③indexアクションが実行され、Users Modelに「すべてのユーザーを取り出せ」と指令がいく。(users_controller.rb→users.rb)
④Users Modelが問い合わせを受け、すべてのユーザーをデータベースから取り出す。(users.rb→データベース→users.rb)
⑤ユーザーのデータがUsers ModelからUsers Controllerに渡される。(users.rb→users_controller.rb)
⑥Users Controllerがデータを@users変数(インスタンス変数)に保存し、index Viewに渡す。(users_controller.rb→index.html.erb)
⑦index Viewが起動し、Embed Ruby:ERBに沿ってページをレンダリングして、Users Controllerに返す。(index.html.erb→users_controller.rb)
⑧Users Controllerがページをブラウザに渡す。(users_controller.rb→ブラウザ)
・ルートのページを、hello,からindexに変えたい。そのためにはroutes.rbを以下のように編集すればよい。
Rails.application.routes.draw do resources :users root "users#index" end
・users_controller.rbにある各メソッドは、RESTアーキテクチャというrubyの設計思想を構成する全アクションである。RESTとは"REpresentational State Transfer"の略であり、Webアプリケーションを構成するコンポーネントを「リソース」として扱うというもの。リソースは標準でCreate/Read/Update/Delete(CRUD)の4つのアクションと、POST/GET/PATCH/DELETEの基本的な4つのHTTPリクエストに対応している。要はオブジェクト指向で全オブジェクトがもともと4つのアクションを持っている感じ?
HTTPリクエスト URL アクション 用途 GET /users index すべてのユーザーを一覧するページ GET /users/1 show id=1のユーザーを表示するページ GET /users/new new 新規ユーザーを作成するページ POST /users create ユーザーを作成するアクション GET /users/1/edit edit id=1のユーザーを編集するページ PATCH /users/1 update id=1のユーザーを更新するアクション DELETE /users/1 destroy id=1のユーザーを削除するアクション
・演習
Q1.user/1/editのリクエストが送られたときの処理の図は?
A1.
Q2.どのコードがユーザーデータを取得している?
A2.順番に見ていく。まず、Controllerのusers_controller.rbのeditメソッドには何も書かれていない。(これでどうやってmodelに命令だしてるの?)次に、Modelのuser.rbも、ApplicationRecordクラスをそのまま継承したUserクラスがあるだけなので、editはApplicationRecordクラスにあるメソッドだと思う。最後にViewのedit.html.erbを見ると、以下のようになっている。
<h1>Editing User</h1> <%= render 'form', user: @user %> <%= link_to 'Show', @user %> | <%= link_to 'Back', users_path %>
これを見ると、editのページでは、formページをレンダリングし、ShowとBackの2つのリンクを作ることになっている。formに対し引数として?userインスタンスを@userで渡している。そこでformを作ってそうな、_form.html.erbを見てみる。
<%= form_with(model: user, local: true) do |form| %> <% if user.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2> <ul> <% user.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> </div> <% end %> <div class="field"> <%= form.label :name %> <%= form.text_field :name, id: :user_name %> </div> <div class="field"> <%= form.label :email %> <%= form.text_field :email, id: :user_email %> </div> <div class="actions"> <%= form.submit %> </div> <% end %>
上半分はエラー処理なので、下半分がフォームの本体。渡された@userのnameとemailを表示している。ここまでの作業で、ユーザーのデータを取得しているのはControllerで、その時の命令は、indexのときと違い「id:1のユーザーを取得しろ」となっているはずである。しかしeditメソッドには何も書かれていない。このことから、UsersControllerの親クラスであるApplicationControllerのeditメソッドが、デフォルトで「id:nのユーザーデータを指定しろ」となっているはずである。
Q3.ユーザーの情報を編集するページのファイル名は?
A3.上記のように、edit.html.erb。
2.2.3 Usersリソースの欠点
・このようにscaffoldジェネレータは簡単にモデルを作成できるが、このままでは以下のような問題がある。
・エラー処理がない(名前やメアドを空欄にした場合など)
・ユーザー認証がない(IDとパスワードでログインしないで、誰でも他のユーザーの情報をいじれてしまう)
・テストが書かれていない?(テストとは?)
・デザインに一貫性がない。
・コードが読みづらい。