# インターンシップ開発体験:下 # 4. データベースの操作 それではデータベースを直接操作してみましょう。 画面と見比べながら結果を確認します。 SQLと呼ばれる言語で操作を行います。 ターミナルは現在、`rails s`でサーバを動作させていますから、別ウィンドウを開きましょう。ターミナル上部の下矢印からUbuntuを選択します。 ![](https://i.imgur.com/IDo7qXh.png) 新しく開いたウィンドウでも、プロジェクトホームに移動します。 ``` $ cd $ cd project/rails/moneta3 ``` データベースの操作画面を開くためには以下のコマンドを入力してください。 ``` $ rails dbconsole sqlite> ``` ![](https://i.imgur.com/Jf4Ir8p.png) `.help`で色々な操作の方法が分かります。`.tables`でテーブルの一覧を確認してみましょう。 ``` sqlite> .tables ``` ![](https://i.imgur.com/STfkA7C.png) ## データの読み取り(select文) 銀行テーブルの内容を確認してみましょう。データの読み取りはSQLのselect文を使用します。 ここで**id**,**kana_name**などはフィールド名です。設計書または設定ファイルから確認することができます。 ``` sqlite> select id, name, kana_name from banks; ``` > select 項目名 from テーブル名; ![](https://i.imgur.com/paIrSGL.png) 全ての項目を見るのであれば、*で省略できます。 ``` sqlite> select * from pages; ``` ![](https://i.imgur.com/0Qo6VBN.png) 条件を指定してデータを取得するには、where句を使用します。 ``` sqlite> select id, name, kana_name from banks where id < 3; ``` 支店テーブルの内容を確認してみましょう。銀行は複数の支店を持ち、支店はひとつの銀行に所属しています。 自身が所属する銀行は、漢字の名前ではなく、bank_idというフィールドに番号で持っているようです。 ![](https://i.imgur.com/ccf5Rot.png) それでは、支店名と銀行名を同時に取得するにはどうすれば良いのでしょうか。SQLのjoin構文を使用すると、複数のテーブルの内容を組み合わせて情報を取得できます。 ``` sqlite> select banks.name, branches.name from branches join banks on banks.id = branches.bank_id; ``` > コマンドが長いので二行に表示していますが、実際には繋げて1行で入力してください。 ![](https://i.imgur.com/p5DdCFZ.png) ## データベースコンソールの終了 データベースコンソールを終了します。 ``` sqlite> .quit ``` ## ER図 銀行テーブルと支店テーブルの関係のように、データベースではそれぞれのつながりを設定して操作することができました。テーブルによるデータの実体(Entity)と関係(Relation)を図示する方法として、ER図というものが用いられます。 monetaのER図は下記の通りです。 先ほどのselect文では分からなかったフィールド名を確認することができます。 ※下図のer図は少々古いです。最新のer図はプロジェクトフォルダ直下のerd.pdfを参照して書き加えてみましょう。図表を手で書いてみることも理解の近道です。 ![](https://i.imgur.com/Gdl1fW9.png) それぞれのテーブルの日本語の意味は以下の通りです。 モデル名はプログラムから呼び出すときの名前、テーブル名はSQLから呼び出すときの名前です。テーブル名はモデル名の複数形になっています。 | モデル名 | テーブル名 | 説明 | | -------- | -------- | -------- | | Page | pages | メニュー画面 | | Bank | banks | 銀行 | | Branch | branches | 支店 | | Product | products | 商品 | | Account | accounts | 口座 | | Statement | statements | 取引明細 | | User | users | ご利用者 | | State | states | 状態 | | Issue | issues | バグ報告 | | Currency | currencies | 通貨 | | Rate | rates | 為替レート | ## データベースモデルの操作 SQLは強力ですが、少々記述が難しいところがあります。実際の開発では、プログラム言語から扱いやすいような**モデル**として設定しています。javaやrubyなどのオブジェクト指向言語では、ORM(object relation mapper)やDAO(data access object)などと呼びます。 厳密な定義はともかく、やってみましょう。 以下のコマンドでコンソールを開きます。 ``` $ rails c ``` > cはコンソールの省略形です コンソールが開いたら、データベースの出力結果を見やすくするため、`Hirb.enable`と設定コマンドを入力しておきましょう。 ![](https://i.imgur.com/XnM0JTu.png) 銀行テーブルは`banks`でしたね。プログラムではBankオブジェクトとして定義されています。すべての行データを取得するには、`all`メソッドを使用します。 ![](https://i.imgur.com/YtdT6cb.png) 自動的にSQLが発行された上に、フィールド名まで表示されています。便利ですね。 先ほどと同じように、銀行テーブルと支店テーブルを結合して検索してみましょう。 `$ Bank.joins(:branches).select("banks.name, branches.name as branch_name")` ![](https://i.imgur.com/ScwVzX9.png) 自動生成されたSQLが青字で表示されます。SQLを直接記述する場合に比べて簡潔に記述できていることが分かります。 SQLの場合と異なり、支店名に`as branch`として別名を付けています。モデルで表示させた場合、見出しが付けられますが、banks.nameと、branches.nameが同じ見出しになってしまうため、これを付けないと表示されません。 ## 件数の確認 テーブルの件数を確認してみましょう。 スタティックメソッドの`count`を使うと、先ほどSQLで記述した`count(*)`形式が生成されます。 ![](https://i.imgur.com/Mo9xvVE.png) 現在の銀行テーブルの件数は6件のようです。 ## 新規レコードの追加 新しいレコードを追加してみましょう。 `Bank.create(name:"name", number:1, myself: true)` ![](https://i.imgur.com/XZ2KvWD.png) データが追加されました。countメソッドで件数が増えたことを確認しましょう。 ## レコードの更新 データの更新を行ってみましょう。 インスタンスとしてレコードを取得して、インスタメンスメソッドのupdateを使用します。 ``` $ bank = Bank.find_by(name:"name") $ bank.update(name: "newname", number:2) ``` ![](https://i.imgur.com/ragiM6S.png) 条件を付けての検索(where句)や、update文による更新を行うSQLが生成されていることが分かります。 ## レコードの削除 せっかく更新したレコードですが、削除することにします。destroyメソッドを使用します。 ``` $ bank.destroy $ Bank.find(7) ``` ![](https://i.imgur.com/sDCsOuv.png) destroyメソッドは条件に合致したレコードをすべて削除するので、`1 row in set`と表示して「1行だけ削除しました」と表示しています。 `find`メソッドは、特にID番号で検索するメソッドですが、削除しているので、RecordNotFound(レコードが見つかりません)が出ています。 ## データベースと画面の連携 ブラウザでトップページを表示しましょう。 「もねた銀行」と表示されていますね。 これはPageテーブルに入っています。修正してみましょう。 ``` $ page = Page.find_by(title: "もねた銀行") $ page.update(title: "おれの銀行") ``` 「おれの銀行」のところは、自由に自分の名前などに変えてください。 ブラウザをリロードして確認します。 ![](https://i.imgur.com/TOFNhwr.png) 更新されました。 このように、開発・テスト中は、データベースを直接操作しながら確認を行うことがあります。 # 5.プログラムの修正 次はソースコードを修正します。画面と見比べながら確認していきましょう。 WEBアプリケーションでは、複数のプログラムやデザインの言語を使用します。一度にすべて覚えるのは無理ですから、実現したい内容に応じて少しづつ理解していきましょう。 ## エディタの起動 それではいよいよプログラムの修正と確認を行ってみましょう。今回はVisual Studio Codeと呼ばれるエディタを利用します。 ターミナルから`code -a .`と入力して起動します。 ![](https://i.imgur.com/xs3uexu.png) ## プロジェクトエクスプローラ 左列の重なった書類のアイコンをクリックすると、プロジェクトエクスプローラーが開き、ファイルとフォルダの全体が表示されます。たくさんのフォルダがありますね。 ![](https://i.imgur.com/tD7Cij0.png) まずはview(ビュー)から見ていきましょう。画面定義を行うプログラムが格納されています。 ![](https://i.imgur.com/I6nEg2a.png) `show.html.slim`をクリックします。 ![](https://i.imgur.com/NAxcEg2.png) ページを定義しているプログラムが表示されました。`slim`というhtmlを生成する言語が使用されています。 ブラウザから画面と見比べてみましょう。ブラウザでF12キーを押すか、右上のメニューボタンから「デベロッパーツール」を開きます。 ![](https://i.imgur.com/FBo1EkT.png) デベロッパーツールには開発用の色々な機能がありますが、画面部品の検査機能を使用してみます。 四角を矢印がさしているアイコンをクリックします。 ![](https://i.imgur.com/1lpeRpj.png) 画面内で動かすと、名称の吹き出しや、レイアウトエリアの色分けが表示されます。 ![](https://i.imgur.com/ePiDWv3.png) 色々動かして、ビュープログラムとの関連を確認してみましょう。 ## ビューの修正 まずは色を変えてみましょう。`.jumbotron`要素の後ろにつなげて、`bg-danger`と追記して`ctrl+s`で保存しましょう。 ![](https://i.imgur.com/5ofbgWu.png) ブラウザの更新ボタンを押すと赤く変わりました。 ![](https://i.imgur.com/uXHhm9v.png) 色などのデザインには`bootstrap4`というライブラリを使用しています。そのほかの色やほかのデザイン要素については、リンク先も参照してください。 https://getbootstrap.com/docs/4.0/utilities/colors/ ## ログの確認 サーバ処理のターミナルを見てみましょう。今の処理のログが出力されています。 ![](https://i.imgur.com/v9fBqq0.png) ログの内容を追うと以下の順番で処理されていることが分かります。 |実施者|操作|内容| |--|--|--| |ブラウザ|送信|GET pages/1| |コントローラ|PagesController|showメソッドを実施| |ビュー|show.html.slim|画面表示用htmlを生成| |ブラウザ|受信・描画|受け取ったhtmlで画面を描画| ## コントローラの修正 それでは次は、コントローラ(PagesController)を修正してみましょう。プロジェクトエクスプローラから`app/controller/`を探して開きます。 ![](https://i.imgur.com/ejU6iw4.png) ファイルの数が多いので、探すことも大変です。エディタが横断検索の機能を提供しているので以下のように行うこともできます。 `ctrl+p`を押して表示された窓に、ファイル名の一部を入力してみましょう。必ずしも連続していなくてもかまいません。下の例では`pagecon`と入力しています。 ![](https://i.imgur.com/fvbdflc.png) いくつか候補が表示されるので、上下矢印+enterかクリックして開きましょう。 ## コントローラーとメソッド 内容を見るとずいぶんすっきりしています。`Page.find_by`の書き方は、データベースの確認の時に見ましたね。 先頭に'@'が付いている変数はインスタンス変数と言い、コントローラーからビューへのデータの受け渡しに使用されます。 ![](https://i.imgur.com/5sNYqlh.png) `@pages.pages`の部分が初めてですね。ターミナルの`rails c`に戻って確認してみましょう。 ``` $ page = Page.find_by(id: 1) $ page.pages ``` ![](https://i.imgur.com/g6lQJAb.png) ビューに連携する必要はないので、'@'はつけていません。「現在のページ」は複数の「次のページ」を持ちますが、このメソッドで次のページの一覧が取得できるようです。 ## タイトルの変更 データベースから取得した情報を、インスタンス変数に格納してビューに送っていることがわかりました。またビューを見ると、`title`フィールドを表示に使用しています。(なので、先ほどデータベースを変更したときにタイトルの表示が変わったのですね) データベースから取得した値を、ビューに渡す前に変更してみましょう。以下の通り`title`と`description`フィールド(属性)を書き換えます。 > ruby言語で編集しています。次のセクションでサンプルと合わせてこれらの編集方法の説明があります。 ![](https://i.imgur.com/zreGhJ2.png) 保存してブラウザをリロードしてみましょう。 ![](https://i.imgur.com/gSAp9SK.png) タイトルと説明文が変更されました。また、他のページに移動してみてください。すべてのページが同じタイトルになってしまっています。 分かりにくいですから、元に戻しておきましょう。 ## リンクボタンの追加 取引明細画面ですが、一覧に戻るボタンがなくて不便ですね。 ![](https://i.imgur.com/usYU3CF.png) 赤枠の部分に一覧に戻るボタンを追加してみましょう。 戻りたい画面を手動で表示すると、urlは`localhost:3000/accounts`のようです、これが`GET /accounts`に変換されて送信されているんでしたね。 `views/statements/index.html.slim`の最終行に以下の通り追加して確認してみましょう。 ![](https://i.imgur.com/OL7cgJD.png) 戻るボタンが追加されました。クリックして元の画面に戻ることを確認してみましょう。 ![](https://i.imgur.com/ftLCo8h.png) > 画面はslim言語で記述されています > https://github.com/slim-template/slim/blob/master/README.jp.md # 6.内部設計 それでは、発見した**バグ**の発生場所と原因の調査を進めていきましょう。 グループワークになりますので、だれがどの**バグ**の調査をするのか、話し合って手分けして行います。 発見したら、バグ報告を更新します。stateを修正に変更し、説明欄に発見した障害箇所と原因、修正方針を記載して、報告するをクリックします。 ![](https://i.imgur.com/0PnLKvm.png) ## バグの探し方 **バグ**の場所の探し方は色々ありますが、実際に操作を行いログを追ってみることで、処理が行われたプログラムと行番号を知ることもできます。 口座開設を行ってログを見ると、POST "/accounts"から処理が始まり、app/forms/account_form.rb:34の'save'メソッドでSQLのINSERT文が発行されているようです。 ![](https://i.imgur.com/ZuwBRkx.png) そのプログラムの34行目を見てみると、確かにsaveメソッドです。なにやら保存処理をしているようですね。 ![](https://i.imgur.com/yJzfCYo.png) ログをさらに追うと、二つのUPDATE文が続いています。 ![](https://i.imgur.com/mHaqCpF.png) 一つ目は`app/models/account.rb:45 in 'withdrow'` ![](https://i.imgur.com/ck1mOcQ.png) 二つ目は`app/models/account.rb:50 in 'deposit'` ![](https://i.imgur.com/2ctfT5H.png) プログラムの該当処理を見てみると、出金処理、入金処理のようです。 ## ルーティング URLから、コントローラーやメソッドへの紐づけをルーティングと呼び、ルーティングを行う機能をルーターと呼びます。 ルーターの定義は、`config/routes.rb`で行っています。 ![](https://i.imgur.com/Lx37I1l.png) `GET /login`が、`SessionsController`の`new`メソッドに送られていることが分かりますが、複数のルーティングを一括して生成するメソッド`resources`等があり、これだけではよくわかりません。 ![](https://i.imgur.com/UO1BJki.png) ファイル上部にコメントの形で生成されたルーティング情報が出力されていますので、こちらで確認することもできます。 ## 自動テスト コーディング内容に**バグ**が無いのか、手動操作で確認する代わりに、確認をプログラムで自動で行わせる仕組みがあります。 ターミナルから以下の通り入力してみましょう。 ``` $ rails test -v ``` ![](https://i.imgur.com/8uJdm9P.png) 218件の項目について自動テストが行われました。 ルーティングのテストを見てみましょう。 `test/controllers/router_test.rb`を開いて下さい。 ![](https://i.imgur.com/1hJeZm2.png) これは`POST '/accounts'`が`AccountsController`の`create`メソッドに送られることを確認する。というテスト処理を記述しています。 先ほど、テスト全項目が失敗無く終了(緑)したことを確認したので、これらの動作は全て正しいです。 そのため、テストドキュメントを設計書代わりに読むこともできます。 ## 設計レビュー グループ内で、まずはバグの修正担当を割り振りましょう。できれば設計者とは別のメンバーが修正したほうが良いでしょう。 > 実際の業務でも、設計者と開発者のコミュニケーションは重要な要素であるため、その練習です 自分の設計内容の説明をしましょう。どのようなバグで、どのようにモジュールを特定したか説明しましょう。 特に修正担当のメンバーは「この報告内容で正しく自分が修正に取り掛かれるか」を考えながら、不足があれば指摘します。指摘内容は反映しましょう。 # 6.開発(コーディング) 自分の担当分の修正開発を行っていきます。プログラムを修正して動作を確認します。 その前に、色々修正した状態を確認しましょう。 ``` $ git diff ``` ![](https://i.imgur.com/T2KfLpt.png) ファイル毎の修正内容が確認できます。ページの色の変更は戻しましたか。明細の戻るボタンはそのままにしておきましょう。 ``` $ git add --all $ git status ``` ![](https://i.imgur.com/YuB4wFf.png) 修正したプログラムが緑で表示され、登録候補(ステージング)になったことが示されます。 何かファイルを適当に修正しましょう。壊してしまってもかまいません。(2-3行削除するとか) `git add`時点に戻すには、以下のコマンドを使用します。 ``` $ git checkout . ``` 元に戻ったでしょうか。 ## gitによるソードコード管理 gitでは、修正したファイルは以下のような順番で管理されます。 |順番|コマンド|名称|説明| |:--|:--|:--|:--| |1||未登録|登録前(statusで赤字)| |2|add|ステージング|ファイル単位で仮登録| |3|commit|コミット|まとめて登録する| |4|push|プッシュ|githubに登録する| 一つの**バグ**について修正を行い、動作確認が済んだら、ステージングに続いて、コミットを行います。 ``` $ git add --all $ git commit -m "Fix バグの説明" ``` ## githubの原本への反映 github IDからforkした場合のみ実施します。 ``` $ git push ``` githubのID/パスワードが求められたら入力します。 # ruby言語の文法 コントローラのプログラムなどで、rubyという言語のコードを見てきました。他の言語と似た部分があることに気が付いたかと思います。JavaやPythonのプログラムを書いたことがあれば、特に馴染みのあるものが多いでしょう。 正式にすべての仕様を学ぶのには多くの時間がかかりますので、ここでは、サンプルを動かしながら**バグ**を修正できるだけの最小の知識を得ることにしましょう。 以下のような項目についてサンプルと動作させる環境を用意してあります。 - 文字列 - 数値 - 整数 - 浮動小数点数 - 2進数 - 16進数 - 配列 - ハッシュ - 範囲クラス - 制御構文 - if else - 正規表現 - メソッド定義 - 演算子 - クラス ## コードの実行環境 ターミナルから、`rails watch`と入力してください。 ![](https://i.imgur.com/8qHIBOd.png) `start watcing`と表示されたら、変更を検出してプログラムを実行する準備ができています。 エディタから、`code/ruby/01_練習用.rb`を開きましょう。 ![](https://i.imgur.com/zwskyCM.png) 何も変更しなくても、`ctrl+s`で保存すると実行されます。実行結果はターミナルに出力されます。 ![](https://i.imgur.com/5Jp1Ade.png) 主要機能のサンプルを13本用意してありますので、順番に実行して結果とプログラムを見比べましょう。変更したり書き直したりしながら、実行しても良いでしょう。 `git`でステージングしてあれば、`git checkout .`でいつでも修正前に戻すことができます。 `00_練習用.rb`は、サンプルにない機能を試してみる場所ですので、自由に修正して試してみましょう。 ## コードレビュー ## github IDを保有している場合 プログラムの修正およびgithubへの登録まで終わったら、講師かチューターを交えてコードレビューを行います。 コートレビューはあなたのgithubのページを各自で参照しながら行いましょう。github上ではコードの差分が色付きで表示されますので、レビューに適しています。 修正したプログラムを探すと、先ほど`commit`で付与したコメントがあります。コメントをクリックします。 ![](https://i.imgur.com/XuEtzTq.png) 追加箇所が緑、削除箇所が赤で色分けして修正内容が表示されます。 ![](https://i.imgur.com/w2YnsW6.png) 指摘や質問があれば、`issue`を発行しましょう。 ![](https://i.imgur.com/VTQgTfu.png) ![](https://i.imgur.com/DXp0Kuf.png) ## github IDを保有していない場合 ## visual studio codeによる差分表示 左列のツールアイコンから、二股に枝分かれしたアイコンをクリックします。小さな丸付き数字は、修正してコミットしていないファイルの数です。 ファイルを選択すると、左右に修正前後の内容が並んで表示されます。赤色が削除部分、黄色が追加部分です。 ![](https://i.imgur.com/2klttwL.png) こちらを表示させながら、コードレビューを実施します。 # 7. 要件定義 さて、バグの修正を中心に開発の流れを追ってきましたが、お客様からシステム化の要望を受けて開発を行う場合、実現したい機能を元に**要件定義**を行います。 これからグループワークとして、monetaの新機能を考えて、システム化の検討を行っていきましょう。今現在、お客様からは次のような要望が出ています。 - 振込手数料について、銀行別の別段預金口座に収容して、残高、明細を確認できるようにしたい。 - お客様情報を一覧できるマイページを追加し、ログイン直後に表示させたい。 - 外貨預金について複数通貨の取扱を可能にしたい。 - 手数料をもっと細かく設定したい。銀行が異なる場合、支店が異なる場合で別の手数料にしたい また、開発部門からの提案として、これ以外のテーマを選定しても構いません。グループで話し合って幾つかテーマを選定したら、バグ報告に登録します。 ## リファクタリング 我々が開発したシステムは5年〜10年と長いあいだ利用されます。その間プログラムの修正が発生するたびに、ソースコードを見て修正する場所を探したり、影響の有無を確認する作業が発生します。 プログラムの読みやすさを保つための変更は、リファクタリングと呼ばれますが、システムを安定して運用するための大事な取り組みになります。 例えば、`controllers/question_controller.rb`は使われていないように見えます。未使用のコードは混乱の元ですから、削除してしまったほうが良いはずですが、思わぬところで影響が出るかもしれません。 リファクタリングによる修正もバグ報告に登録します。 ## 自動テスト リファクタリングによる無影響を確認する場合に自動テストがあると安心です。 `controllers/question_controller.rb`を削除して、`rails test`を実行してみましょう。 ![](https://i.imgur.com/jvgh7fb.png) 全て緑ですから、全項目大丈夫です。削除した状態でステージングしましょう。 もし、テストでエラーが発生していたら、`git checkout .`で戻すことができます。 ## フォームテスト 沢山テストがあるようですが、フォームのテストを見てみましょう。それぞれのエラーが発生するデータをセットして、エラー出力をテストしています。 ![](https://i.imgur.com/VybzG5v.png) ## 要件定義レビュー グループワークにより登録した内容について、他のグループに説明しましょう。説明を聞いた他のグループは、不明瞭な部分については質問して明確にしましょう。 指摘事項を反映して修正したら、設計者を設定します。 # 10. 振り返り 本日の成果を報告しましょう。不備・障害一覧には、担当者名で絞り込みを行う機能があります。その機能を使って、自分が担当した「報告」「設計」「開発」「検証」について振り返りを行うと良いでしょう。 慌ただしくも駆け足の対応でしたが、お疲れ様でした。