RailsでDBを使う方法

2020-06-10 hit count image

Ruby on Railsを使ってDBへデータをCRUD(Create Read Update Delete)する方法について共有します。

概要

このブログポストではRailsを使って本格的データを使ってみようかと思います。本格的データを使うためDBを設定して、DBテーブ路を生成する予定です。 このように生成されたDBへRailsを使ってCRUD(Create Read Update Delete)をして、Railsでデータを使う方法を理解してみようかと思います。

このブログポストはシリーズで作成されてます。詳しく内容は下記のリンクを参考してください。

ここで使ったソースコードはGithubで確認できます。

DB設定

まず、DBを使うためにはRailsへDBに関する設定をする必要があります。ここにはmysqlを設定する方法だけ紹介します。 mysqlは既にローカルにインストールされたと思って進めます。

RailsでDBの設定はconfig/database.ymlファイルが担当してます。config/database.ymlファイルを開いたら、下記のような内容が確認されます。

default: &default
  adapter: sqlite3
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000

development:
  <<: *default
  database: db/development.sqlite3

test:
  <<: *default
  database: db/test.sqlite3

production:
  <<: *default
  database: db/production.sqlite3

Railsは基本的sqlite3を設定しております。ここではmysqlを使う予定なので、上の設定を下記のように修正します。

default: &default
  adapter: mysql2
  encoding: utf8
  database: study_rails
  pool: 5
  username: root
  password:
  socket: /tmp/mysql.sock

development:
  <<: *default

test:
  <<: *default

production:
  <<: *default

上の設定でdatabase, username, passwordを自分のローカル環境に合わせて修正します。

上の設定では全ての設定をdefaultへ作成して、他の環境ではdefaultにある内容を参考するようにしました。特定な環境に必要な情報を修正したい場合は、下記のように修正することができます。

production:
  <<: *default
  username: root
  password: XXXX

上のように修正すると、production環境時だけ、ここに書いてるusernameとpasswordを使うようになります。

mysql2

RailsでMysqlに接続するためにはmysql2と言うgemが必要です。下記のコマンドでmysql2をインストールします。

bundle add mysql2

インストールが完了されたら、下記のコマンドでデータベースを生成します。

bundle exec rake db:create

もし、下記のようなエラーメッセージが表示されて、データベースが生成されない場合、

warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
The called method `initialize' is defined here
[BUG] Segmentation fault at 0x0000000000000000
...

下記のコマンドを使ってmysql2をインストールします。

gem install mysql2 -- --with-ldflags=-L/usr/local/opt/openssl/lib --with-cppflags=-I/usr/local/opt/openssl/include

そして、まだ、下記のコマンドを使ってデータベースを生成します。

bundle exec rake db:create

問題なくデータベースが生成されたら下記のようなメッセージを確認することができます。

Created database 'study_rails'
Database 'study_rails' already exists

Modelを作る

データベースを作りましたので、データを保存するテーブルを作ってみましょう。Railsを使ってテーブルを作るためには、まず、Modelを生成する必要があります。

下記のコマンドを使ってModelを生成します。

# bundle exec rails generate model post
bundle exec rails g model post

このようにModelを生成すると、下記のようなファイルが生成されることが確認できます。

├── app
│   ├── models
│   │   ├── post.rb
├── db
│   ├── migrate
│   │   ├── 20200315053129_create_posts.rb
├── test
│   ├── fixtures
│   │   ├── posts.yml
│   ├── models
│   │   ├── post_test.rb
  • app/models/post.rb: 実際テーブルと連結されるModel
  • db/migrate/20200315053129_create_posts.rb: テーブルを生成するためのmigratoinファイル
  • test/fixtures/posts.yml: テストをするためDummyデータ
  • test/models/post_test.rb: Modelのユニットテストをするためのファイル

テーブル生成

実際データをデータベースへ保存するためテーブルを生成してみましょう。データベースへテーブルを生成するため、Migrationファイルを修正する必要があります。

postsテーブルを生成するため、db/migrate/20200315053129_create_posts.rbファイルを開いて下記のように修正します。

class CreatePosts < ActiveRecord::Migration[6.0]
  def change
    create_table :posts do |t|
      t.string :title
      t.text :content
      t.timestamps
    end
  end
end

このpostsテーブルは基本的Stringタイプのtitleと長い文字を保存するためTextタイプのcontentを持ってます。また、

bundle exec rake db:migrate

コマンドを実行するとテーブルが生成されてdb/schema.rbファイルが生成されることが確認できます。db/schema.rbファイルを開いてみると下記のような内容が確認できます。

ActiveRecord::Schema.define(version: 2020_03_15_053129) do

  create_table "posts", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
    t.string "title"
    t.text "content"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

end

また、データベースツールを使って実際テーブルが生成されたか、確認すると、下記のようにテーブルができてることが確認できます。

Ruby on Rails テーブル生成結果

Migrationを使ってテーブル生成した後、下記のコマンドでテーブル生成前に戻ることができます。

bundle exec rake db:rollback

CRUD

今から上で作ったテーブルへRailsを使ってCRUD(Create Read Update Delete)をしてみます。

Create

データを生成するため、まずapp/controllers/home_controller.rbファイルを開いて、下記のように修正します。

class HomeController < ApplicationController
    ...
    def form

    end
end

ユーザから入力して貰う画面を表示するformを生成しました。当該formのActionに関するViewを作成するため、app/views/home/form.erbファイルを生成して下記のように修正します。

<a href="/list">Go back</a><br/>
<form action="/create" method="POST">
  <input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>" />
  <label for="title">title:</label>
  <input type="text" name="title" />
  <label for="content">content:</label>
  <input type="text" name="content" />
  <input type="submit" />
</form>

ユーザがsubmitボタンを押すと、POST/createと言うURLへデータを送るように作りました。

そしてRouteへ当該URLを登録するため、config/routes.rbファイルを開いて下記のように修正します。

Rails.application.routes.draw do
  ...
  get '/form', to: 'home#form'
end

そして確認のため、下記のコマンドを実行してRailsサーバを起動します。

bundle exec rails s

実行が終わったら、http://127.0.0.1:3000/formへ移動したら、下記のような画面をみることができます。

Ruby on Rails, CRUD 데이터 생성 form

今から実際データを貰って処理する部分を作ってみましょう。app/controllers/home_controller.rbファイルを開いて下記のように修正します。

class HomeController < ApplicationController
    ...
    def create
        post = Post.new
        post.title = params[:title]
        post.content = params[:content]
        post.save

        redirect_to '/list'
    end

    def list

    end
end

上の内容を詳しくみると、

  • post = Post.new: 上で作ったPOSTモデルを使って新データを生成する準備をします。
  • post.title = params[:title]: 新く生成するPOSTデータのtitleへユーザが入力したtitleを入れます。
  • post.content = params[:content]: 新く生成するPOSTデータのcontentへユーザが入力したcontentデータを入力します。
  • post.save: 最後に当該データを保存することで、データベースへデータを生成(create)します。
  • redirect_to '/list': 生成が終わったら、/listと言うURLへRedirectさせます。
  • def list: 一旦Redirectする時、エラーが出ないようにするため、空のActionを追加します。今後、このActionへデータを表示する処理を入れる予定です。

上の内容をみるとわかりますが、createアクションはredirectさせますので、Viewが要らないです。しかし、後でデータを表示するlistアクションはViewが必要なので、app/views/home/list.erbファイルを生成しておきます。

このように追加したActionを使うためconfig/routes.rbファイルを開いて下記のように修正します。

Rails.application.routes.draw do
  ...
  post '/create', to: 'home#create'
  get '/list', to: 'home#list'
end

そしてhttp://127.0.0.1:3000/formへデータを入れてSubmitボタンを押してhttp://127.0.0.1:3000/listへ移動することが確認できます。また、データベースツールを使ってみると、下記のようにデータがうまく追加されたことが確認できます。

Ruby on Rails, CRUDデータ生成確認

Read

이제 위에서 생성한 데이터를 읽어와서(Read), 화면에 표시해 보도록 합시다. app/controllers/home_controller.rb 파일을 열고 아래와 같이 수정합니다.

class HomeController < ApplicationController
    ...
    def list
        @posts = Post.all
    end
end

上でPost.allを使ってPostテーブルへ保存した全てのデータを取ってきました。このように取ってきたデータをViewへ伝達するため@postsと言うインスタンス変数へ保存しました。

このように保存したデータを画面に表示するため、app/views/home/list.erbファイルを開いて下記のように修正します。

<style>
table, th, td {
  border: 1px solid black;
}
</style>
<a href="/form">Create New Post</a>
<table>
    <thead>
        <tr>
            <th>Title</th>
            <th>Content</th>
            <th>Action</th>
        </tr>
    </thead>
    <tbody>
        <% @posts.each do |post| %>
        <tr>
            <td><%= post.title %></td>
            <td><%= post.content %></td>
            <td></td>
        </tr>
        <% end %>
    </tbody>
</table>

ここで重要な部分は@postsのインスタンス変数を通じて持ってきたデータを下記のコードを使ってループしながら、1つづつpostの変数へ入れます。

<% @posts.each do |post| %>
...
<% end %>

このように割り当てられたpost変数からtitleとcontentを取ってきて画面に表示します。

<td><%= post.title %></td>
<td><%= post.content %></td>

このように作成して、また、http://127.0.0.1:3000/listへ接続してみると、下記のようにデータが表示されることが確認できます。

Ruby on Rails データベースから取ってきたデータを画面へ表示

Update

今から上で生成したデータを修正(Update)する方法について説明します。app/controllers/home_controller.rbファイルを開いて下記のように修正します。

class HomeController < ApplicationController
    ...
    def modify
        @post = Post.find(params[:id])
    end
end

上でmodifyはユーザへ修正するFormを提供するためのアクション(Action)です。ユーザから修正したいデータのidを受けて、受けて貰ったidで必要なデータを探して(Post.find)、探したデータをViewへ伝達するためインスタンス変数(@post)へ保存しました。

次は、追加されたデータを修正するためのFormをユーザへ提供するためapp/views/home/modify.erbファイルを生成して下記のように修正します。

<a href="/list">Go back</a><br/>
<form action="/update/<%= @post.id %>" method="POST">
  <input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>" />
  <label for="title">title:</label>
  <input type="text" name="title" value="<%= @post.title %>"/>
  <label for="content">content:</label>
  <input type="text" name="content" value="<%= @post.content %>" />
  <input type="submit" />
</form>

データを生成するため作ったapp/views/home/form.erbと似てます。違うところはInputタグのvalueへControllerから伝達して貰ったデータを表示してます。

<input type="text" name="title" value="<%= @post.title %>%"/>
<input type="text" name="content" value="<%= @post.content %>%" />

このように生成したページを表示するためRouteを設定してみましょう。config/routes.rbファイルを開いて下記のように修正します。

Rails.application.routes.draw do
  ...
  get '/modify/:id', to: 'home#modify'
end

データを修正するためのViewであるmodifyはURLへパラメーターを伝達する方法を使ってます。 このようにURLでidをもらって、Controllerは受けったidをデータを探して、画面へ表示する予定です。

次はmodifyページを開くためのリンクを追加するためapp/views/home/list.erbファイルを開いて下記のように修正します。

...
<table>
    <thead>
        ...
    </thead>
    <tbody>
        <% @posts.each do |post| %>
        <tr>
            <td><%= post.title %></td>
            <td><%= post.content %></td>
            <!-- add this line -->
            <td><a href="/modify/<%= post.id %>">modify</a></td>
        </tr>
        <% end %>
    </tbody>
</table>

このように作成して、またhttp://127.0.0.1:3000/listへ接続してみると、下記のようにデータが上手く表示されることが確認できます。

Ruby on Railsデータを修正するためのリンク追加

ここでmodifyリンクを押したら、下記のような画面を確認することができます。

Ruby on Railsデータを修正するページ

次はデータを実際更新するアクション(Action)を作ってみましょう。上のmodifyページでsubmitボタンを押すと、/update/:idへ遷移するように作りました。

<a href="/list">Go back</a><br/>
<form action="/update/<%= @post.id %>" method="POST">
  ...
</form>

このリンクに該当するアクションを作るため、app/controllers/home_controller.rbを開いて下記のように修正します。

class HomeController < ApplicationController
    ...
    def update
        post = Post.find(params[:id])
        post.title = params[:title]
        post.content = params[:content]
        post.save

        redirect_to '/list'
    end
end

パラメーターでもらったidで保存したデータを取ってきて、ユーザが入力したtitlecontentデータで保存したデータを更新した後、post.saveを使ってデータを更新しました。 最後にデータを更新したら、/listページへRedirectするように設定しました。

次はこのアクションを使えるようにするためRouteへURLを追加してみましょう。config/routes.rbファイルを開いて下記のように修正します。

Rails.application.routes.draw do
  ...
  post '/update/:id', to: 'home#update'
end

URLを通じてidパラメーターを受ける予定で、ユーザが入力したデータはPOST方式で貰う予定です。

この後、データの修正ページへ移動した後、

Ruby on Railsデータを修正するためリンク追加

下記のように既存データとは違う内容を入力してみます。

Ruby on Rails データ修正ページ - データ修正

そしてSubmitボタンを押すと下記のように、データが上手く更新されたことが確認できます。

Ruby on Railsデータリストページ - データ修正結果

Delete

次はCRUDの最後であるデータ削除(Delete)に関して説明します。データを削除するアクションを追加するためapp/controllers/home_controller.rbファイルを開いて下記のように修正します。

class HomeController < ApplicationController
    ...
    def delete
        Post.destroy(params[:id])

        redirect_to '/list'
    end
end

パラメーターでもらったidでPostモデルのデータを削除(Post.destroy)して/listページへRedirectするようにしました。

次はこのアクションをURLへ追加するためconfig/routes.rbファイルを開いて下記のように修正します。

Rails.application.routes.draw do
  ...
  get '/delete/:id', to: 'home#delete'
end

そしてこのページを呼び出せるようにlistページを修正します。app/views/home/list.erbファイルを開いて下記のように修正します。

...
<table>
    <thead>
        ...
    </thead>
    <tbody>
        <% @posts.each do |post| %>
        <tr>
            <td><%= post.title %></td>
            <td><%= post.content %></td>
            <td>
                <a href="/modify/<%= post.id %>">modify</a><br/>
                <a href="/delete/<%= post.id %>">delete</a><br/>
            </td>
        </tr>
        <% end %>
    </tbody>
</table>

またhttp://127.0.0.1:3000/listへ接続したら、下記のようにdeleteリンクが追加されたことが確認できます。

Ruby on Railsデータリストページ - 削除リンク

そしたら、deleteリンクを押してみましょう。deleteリンクを押すと、保存されたデータが上手く削除されて、下記のようにリストページにもデータが表示されないことが確認できます。

Ruby on Railsデータリストページ削除成功

完了

これで、Ruby on Railsでデータベースを生成してデータをCRUD(Create Read Update Delete)する方法についてみてみました。皆さんはもうRuby on Railsで基本的なウェブサービスを開発する準備ができました。

今後はウェブサービスを作って見ながら、Railsをもっと深く勉強してください。

参考

このブログポストはシリーズで作成されてます。詳しく内容は下記のリンクを参考してください。

ここで使ったソースコードはGithubで確認できます。

Posts