【Ruby on Rails】フォームからDBに値登録・画面にDBの内容表示
0. はじめに
Ruby on RailsでDB(sqllite)をいじってみました。
フォームからの登録→Web画面に表示
をやってみました。
説明が雰囲気で理解している感が強めです。
あと、結果よりプロセスを前面に出してます。
目次
1. Modelについて
Ruby on RailsでDBをいじるために、
Modelという概念を理解します。
下記の記事が端的にまとめていて、
理解しやすかったです。
Railsのmodelを徹底解説!知っておくべき3つの知識も…|Udemy メディア
Modelとは、
データベースのテーブルに対応するRubyのクラス
とのことです。
2. Modelを作ってみる
下記のコマンドで生成します。
rails generate model <モデル名> <カラム名>:<型> [<カラム名>:<型> …]
モデル名は単数形(末尾がsではない)でなければなりません。
<カラム名>:<型>
は複数カラムがある場合は後ろに追記していきます。
ちなみに、Modelの削除は下記のコマンドです。
rails destroy model <モデル名>
date | amount |
---|---|
貯金した日付 | 金額 |
こんなテーブルを作りたかったので、
下記のコマンドで作成しました。
>rails generate model saving date:date amount:integer invoke active_record create db/migrate/20191128052254_create_savings.rb create app/models/saving.rb invoke test_unit create test/models/saving_test.rb create test/fixtures/savings.yml
なにやらrailsが必要なファイルを生成してくれたようです。
db/migrate/20191128052254_create_savings.rb がミソで、
下記のようになっています。
DBに「Savingsってテーブル作ってちょ!」と依頼してます。
class CreateSavings < ActiveRecord::Migration[6.0] def change create_table :savings do |t| t.date :date t.integer :amount t.timestamps end end end
rails db:migrate
コマンドを実行することで、
その依頼が実行されます。
>rails db:migrate == 20191128052254 CreateSavings: migrating ==================================== -- create_table(:savings) -> 0.0074s == 20191128052254 CreateSavings: migrated (0.0100s) ===========================
3. フォームを作ってみる
Web画面のフォームから値を投入させたいので、
まず、Viewでフォームを作ってみます。
後々Controllerをがちゃがちゃいじるので、
下記のコマンドを実行しておきます。
>rails generate controller saving create app/controllers/saving_controller.rb invoke erb create app/views/saving invoke test_unit create test/controllers/saving_controller_test.rb invoke helper create app/helpers/saving_helper.rb invoke test_unit invoke assets invoke scss create app/assets/stylesheets/saving.scss
app/views/saving
ができてますね。
ここに、new.html.erbを作っていじっていきます。
View
- app/views/saving/new.html.erb
<h1>貯蓄管理</h1> <h2>貯蓄入力</h2> <%= form_for @saving do |f| %> <div class="field"> <%= f.label :date, "日付" %> <%= f.date_select( :date, use_month_numbers: true, start_year: 2018, date_separator: '/') %> </div> <div class="field"> <%= f.label :amount, "金額 ¥" %> <%= f.number_field :amount %> </div> <div class="actions"> <%= f.submit "登録" %> </div> <% end %>
まずは入力分だけです。
後で表示分作ります。
<%= %>
は、Rails on Ruby独特の記法のようで、
記法に則って書くと、HTMLに変換してくれるみたいです。
フォームを作るには、この記事が参考になりました。
Railsのform_forを使ったフォームのController,View,Modelの連携した処理フロー - Rails Webook
ポイントを説明します。
form_forメソッド
基本的な書式は下記の通りです。
<%= form_for モデルのオブジェクト do |文字列| %> <% end %>
フォームの中身の記法は下記の通り
<%= 文字列.label :ラベル名, "Webに表示する項目名"> <%= 文字列.フォームの種類 :controllerに引き渡すparamのキーになる文字列>
登録ボタンはこちら
<%= 文字列.submit "登録" %>
なかなか説明がいけてないが、
まぁ、よいでしょう。(よくない)
私が使ったフォームの種類は以下の二つです。
- date_select
- number_field
controller
Viewで外観ができたので、
中の処理を作っていきます。
app/controllers/saving_controller.rbは、
自動生成済みなので、それを編集します。
- app/controllers/saving_controller.rb
class SavingController < ApplicationController def new @saving = Saving.new end
フォームを表示するために、
newメソッドの定義が必要です。
@変数名 = モデル名.new
で、
データベースのオブジェクトを@変数名に格納します。
ControllerはDBに投入する処理でもう少しいじることになります。
まだ完成形ではありません。
他には以下のような準備が必要です。
- routes.rbの編集
config/routes.rbに2行追加します。
get '/saving_setting' => "saving#new"
「/saving_settingにアクセスしたら、savingコントローラのnewアクションを実施しなさい」
と、定義しています。post 'savings' => "saving#create"
「テーブルsavingsにPostされたら、savingコントローラのcreateアクションを実施しなさい」
と、定義しています。Viewの紐づけ newアクションが実行されたら表示するために、
Viewのファイルはnew.html.erbという名前になっています。
ここまでやると、画面からフォームが見れます。
登録ボタン押しても、まだ動きません。
4. DBにフォームの入力値を登録してみる
入力値の登録処理は、
コントローラに定義していきます。
下記のようになります。
- app/controllers/saving_controller.rb
class SavingController < ApplicationController def new @saving = Saving.new end def create @saving = Saving.create( date: Date.new(saving_params["date(1i)"]&.to_i, saving_params["date(2i)"]&.to_i, saving_params["date(3i)"]&.to_i), amount: saving_params[:amount] ) redirect_to '/saving_setting' end private def saving_params params.require(:saving).permit(:date, :amount) end end
ポイントを押さえていきます。
createメソッド
やり方はいくつかあるようですが、
私は、モデル名.createでレコードを生成させました。
def create モデルのオブジェクト変数 = モデル名.create( カラム名: 値 … ) redirect_to '登録ボタン押したらリダイレクトさせるパス end
フォームのdate_selectから渡される値に癖があったので、
以下の記事が参考になりました。
Ruby on Rails - date_selectの値がデータベースに登録できない|teratail
格納先のDBカラムの型はdate型なのですが、
フォームから受け取っている値は、
ハッシュ型(xxx:n, yyy:n, zzz:n)の数値だったので、
Date.newで加工する必要がありました。
ストロングパラメータ
Viewから渡されるparamsを受け取るために、
ストロングパラメータというものを使います。
Rubyのストロングパラメータ(Strong Parameters)を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン
DBを更新するのに必要なパラメータだけを受け取るために
ストロングパラメータを定義する必要があります。
private def ストロングパラメータ名 params.require(:モデル名).permit(:DBカラム名) end
ここで受け取って、
先述のcreateメソッド部分で、
amount: saving_params[:amount]
のように使ってます。
ここまでで、DBにデータを投入する仕組みが整いました。
確認方法
え、ほんとにDBに入ったの?
って確認する方法を紹介します。
こんな感じでフォームに入れてもらって、
「登録」ボタンを押します。
rails dbconsoleを使います。
>rails dbconsole SQLite version 3.30.1 2019-10-10 20:19:45 Enter ".help" for usage hints. sqlite>
- テーブル一覧表示
sqlite> .table ar_internal_metadata savings schema_migrations
- テーブル表示
sqlite> select * from savings; 1|2018-02-17|30000|2019-11-28 07:39:08.354420|2019-11-28 07:39:08.354420 2|2018-05-29|30000|2019-11-29 02:37:20.483411|2019-11-29 02:37:20.483411
入力値がDBに登録されているか確認できます。
5. DBの値を表示してみる
DBに値が入ったので、
いよいよWEB画面に表示させてみます。
Viewをいじります。
私は、登録フォームの下に表示されるようにしました。
- new.html.erb
<h1>貯蓄管理</h1> <h2>貯蓄入力</h2> <%= form_for @saving do |f| %> <div class="field"> <%= f.label :date, "日付" %> <%= f.date_select( :date, use_month_numbers: true, start_year: 2018, date_separator: '/') %> </div> <div class="field"> <%= f.label :amount, "金額 ¥" %> <%= f.number_field :amount %> </div> <div class="actions"> <%= f.submit "登録" %> </div> <% end %> <h2>貯蓄履歴</h2> <table border="1"> <tr> <th>日付</th> <th>金額</th> </tr> <% @list.each do |set| %> <tr> <td><%= set.date %></td> <td><%= set.amount %></td> </tr> <% end %> </table>
上記の<h2>貯蓄履歴</h2>
からが追記箇所です。
表の作り方は、HTML記法に倣ってますが、
DBから値を引っ張ってくるrails独自の記法は下記の部分です。
<% モデルのオブジェクト変数.each do |文字列| %> …(省略)… <%= 文字列.カラム名 %> …(省略)… <% end %>
モデルのオブジェクト変数は、
Controllerで定義しておく必要があります。
- saving_controller.rb
class SavingController < ApplicationController def new @saving = Saving.new @list = Saving.all end (以下略)
全カラムの全レコードを@listに
格納するように、
newメソッドで定義しました。
@list = Saving.all
これで、下記のように、
DBの値がWeb画面に表示されました。
まとめ
伝えたいことは、 独学でも、 ググりながら格闘すれば、 何とかそれっぽいWEBアプリができそうだということです。