③Userモデルを追加してみよう

この章のゴール

・モデル、データベースの概念を理解する。

・MVCの概念を理解する。

・railsでよく使うメソッドについて理解する。

Userモデルの追加

モデルとは

まず始めに、モデルについて説明します。

Railsのモデル(Model)とは、「データベースとやり取りを行うクラス」です。

MVCモデルにおいて、モデルは、コントローラからの指示でデータベース(DB)にアクセスし、DBから必要なデータを取ってきて、コントローラに返すという責務を担います。

データベースとは

データベースとは、そのWebアプリケーションで扱うデータ(ユーザのログインIDやパスワード、名前や住所などの情報)を集め、操作できるようにしたものです。

データベースは様々なテーブル(以下の図を参照)の集まりであり、エクセルのように情報を縦横に並べたものです。

テーブルの行のことをレコードと呼び、列のことをカラムと呼びます。

ユーザーテーブルを例にすると、以下の通りです。

↑のようなテーブルを複数作り、それらの集合体をデータベースと呼びます。

また、データベースで利用する操作は、新規データの作成(Create)データの読み取り(Read)データの更新(Update)データの削除(Delete)の4つがあり、これらの頭文字を取りCRUD(クラッド)処理と呼びます。

migrationとは

本来、データベースを操作するためには、データベースへログインし、SQLという言語を使って、新規データベースやテーブルの作成などを行う必要があります。

しかし、テーブルを作成する度に、一連の作業を行うのは労力がかかるため、railsでは、それらを自動で行ってくれるための機構があり、どのようなデータベースを作成するかmigrationファイルに記述し、railsのコマンドを叩くことで、データベースが自動的に作成されるようになります。

Userモデルとmigrationファイルを作成

では早速、Userモデルmigrationファイルを作成していきます。

まず初めに、今回の作業用に新たなブランチを作成します。

$ git checkout -b feature/create_user_model
Switched to a new branch 'feature/create_user_model'

 

次に、Userモデルを作成します。rails gコマンドで、新しいモデルを作成できます。

$ rails g model User
Running via Spring preloader in process 5033
      invoke  active_record
      create    db/migrate/20190902015009_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml

 

上記の通り、必要なファイルが自動的に生成されます。

app/models/user.rbモデルファイル

db/migrate/20190902015009_create_users.rbmigrateファイル

次に、db/migrate/ディレクトリ配下の、「~_create_users.rb」を開きます。

そして、「email」、「password」、「name」の3カラムを追加します。

class CreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      t.string :email
      t.string :password
      t.string :name

      t.timestamps
    end
  end
end

 

では、マイグレートを行います。

$ rails db:migrate
== 20190902015009 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0019s
== 20190902015009 CreateUsers: migrated (0.0024s) =============================

rails db:rollbackと入力すると、先ほど行ったマイグレーションがキャンセルされ、元の状態に戻ります。

railsコンソールでCRUD操作してみる

ターミナル上で、rails cコマンドを実行することで、上記で作成したUserの実際に作成できます。

Gemfileを開き、gem ‘rb-readline’を追加してください。

・
・
・
group :development do
  gem 'rb-readline'
  # Access an interactive console on exception pages or by calling 'console' anywhere in the
・
・
・

 

そして、bundle installします。

$ bundle install
The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`.
Using rake 12.3.3
Using concurrent-ruby 1.1.5
Using i18n 1.6.0
・
・
・

 

そして、サーバを再起動(Control + Cでサーバを止めて、rails s)すると、rails cコマンドが利用できるようになります。

$ rails c
Running via Spring preloader in process 5684
Loading development environment (Rails 5.2.3)
2.6.3 :001 > 

 

newメソッド

新規モデルの作成にはnewメソッドを利用します。

また、newメソッドで新規作成されたモデルは、そのままの状態では、データベースに保存されません。

saveメソッド

データベースに保存する際は、必ず、saveメソッドを実行する必要があります。

> user = User.new(email: 'sample_a@gmail.com', password: 'password', name: '小池太郎')
=> #<User id: nil, email: "sample_a@gmail.com", password: "password", name: "小池太郎", created_at: nil, updated_at: nil>

> user.save
(0.1ms)  begin transaction
  User Create (1.2ms)  INSERT INTO "users" ("email", "password", "name", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?)  [["email", "sample_a@gmail.com"], ["password", "password"], ["name", "小池太 郎"], ["created_at", "2019-09-02 02:13:24.666984"], ["updated_at", "2019-09-02 02:13:24.666984"]]
   (5.1ms)  commit transaction
 => true 

↑saveメソッドでtrueとなっていれば、問題なくUserが作成されたことを意味します。

逆に、falseとなっている場合は、データベースへの保存に失敗したことを意味します。

createメソッド

このメソッドは、上記のnewとsaveを同時に行うためのメソッドです。

試しに、実行してみましょう。

> User.create(email: 'sample_b@gmail.com', password: 'password2', name: '山田花子')
 (0.1ms)  begin transaction
  User Create (1.3ms)  INSERT INTO "users" ("email", "password", "name", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?)  [["email", "sample_b@gmail.com"], ["password", "password2"], ["name", "山田花子"], ["created_at", "2019-09-02 02:21:30.394856"], ["updated_at", "2019-09-02 02:21:30.394856"]]
   (5.8ms)  commit transaction
 => #<User id: 2, email: "sample_b@gmail.com", password: "password2", name: "山田花子", created_at: "2019-09-02 02:21:30", updated_at: "2019-09-02 02:21:30"> 

allメソッド

モデルの全カラムを取得するメソッドです。

 > User.all
User Load (0.2ms)  SELECT  "users".* FROM "users" LIMIT ?  [["LIMIT", 11]]
 => #<ActiveRecord::Relation [#<User id: 1, email: "sample_a@gmail.com", password: "password", name: "小池太郎", created_at: "2019-09-02 02:13:24", updated_at: "2019-09-02 02:13:24">, #<User id: 2, email: "sample_b@gmail.com", password: "password2", name: "山田花子", created_at: "2019-09-02 02:21:30", updated_at: "2019-09-02 02:21:30">]> 

↑createメソッドで作成したユーザ(email: ‘sample_b@gmail.com’, password: ‘password2’, name: ‘山田花子’)も、登録されていることが確認できます。

findメソッド

idからモデルを検索するメソッドです。

> User.find(1)
 User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
 => #<User id: 1, email: "sample_a@gmail.com", password: "password", name: "小池太郎", created_at: "2019-09-02 02:13:24", updated_at: "2019-09-02 02:13:24">

id = 1のユーザが取得できていることが確認できます。

> User.find(2)
User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
 => #<User id: 2, email: "sample_b@gmail.com", password: "password2", name: "山田花子", created_at: "2019-09-02 02:21:30", updated_at: "2019-09-02 02:21:30"

id = 2のユーザが取得できていることが確認できます。

find_byメソッド

id以外のカラムを使って検索をかけたい場合に利用します。

> User.find_by(name: '小池太郎')
 User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."name" = ? LIMIT ?  [["name", "小池太郎"], ["LIMIT", 1]]
 => #<User id: 1, email: "sample_a@gmail.com", password: "password", name: "小池太郎", created_at: "2019-09-02 02:13:24", updated_at: "2019-09-02 02:13:24"> 

nameが「小池太郎」という条件で検索した結果

 > User.find_by(name: '山田花子')
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."name" = ? LIMIT ?  [["name", "山田花子"], ["LIMIT", 1]]
 => #<User id: 2, email: "sample_b@gmail.com", password: "password2", name: "山田花子", created_at: "2019-09-02 02:21:30", updated_at: "2019-09-02 02:21:30">

nameが「山田花子」という条件で検索した結果

updateメソッド

カラムの情報を更新するためのメソッドです。

nameが「山田花子」というユーザを取得して、nameを「田中 花子」に変更してみましょう。

> user = User.find_by(name: '山田花子')
User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."name" = ? LIMIT ?  [["name", "山田花子"], ["LIMIT", 1]]
 => #<User id: 2, email: "sample_b@gmail.com", password: "password2", name: "山田花子", created_at: "2019-09-02 02:21:30", updated_at: "2019-09-02 02:21:30">

↑まずは、nameが「山田花子」というユーザを検索してuserという変数に格納

> user.update(name: '田中 花子')
(0.1ms)  begin transaction
  User Update (0.9ms)  UPDATE "users" SET "name" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["name", "田中 花子"], ["updated_at", "2019-09-02 02:43:44.688224"], ["id", 2]]
   (5.2ms)  commit transaction
 => true 

↑updateメソッドでtrueとなっていれば、問題なくカラムが更新されたことを意味します。

逆に、falseとなっている場合は、カラムの更新に失敗したことを意味します。

destroyメソッド

データを削除するためのメソッドです。

では、idが「1」のユーザをデータベースから削除してみましょう。

> user = User.find(1)
 User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
 => #<User id: 1, email: "sample_a@gmail.com", password: "password", name: "小池太郎", created_at: "2019-09-02 02:13:24", updated_at: "2019-09-02 02:13:24"> 

id = 1のユーザを取得し、user変数に格納。

> user.destroy
   (0.1ms)  begin transaction
  User Destroy (0.9ms)  DELETE FROM "users" WHERE "users"."id" = ?  [["id", 1]]
   (4.6ms)  commit transaction
 => #<User id: 1, email: "sample_a@gmail.com", password: "password", name: "小池太郎", created_at: "2019-09-02 02:13:24", updated_at: "2019-09-02 02:13:24"> 

↑destroyメソッドで削除

実際に、削除されていることを確認します。

> User.all
User Load (0.1ms)  SELECT  "users".* FROM "users" LIMIT ?  [["LIMIT", 11]]
 => #<ActiveRecord::Relation [#<User id: 2, email: "sample_b@gmail.com", password: "password2", name: "田中 花子", created_at: "2019-09-02 02:21:30", updated_at: "2019-09-02 02:43:44">]

id = 2のユーザしか表示されていないので、id = 1のユーザは削除されたことが確認できます。

次に、id = 2のユーザも削除してみましょう。

> user = User.find(2)
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
 => #<User id: 2, email: "sample_b@gmail.com", password: "password2", name: "田中 花子", created_at: "2019-09-02 02:21:30", updated_at: "2019-09-02 02:43:44"> 

 > user.destroy
   (0.1ms)  begin transaction
  User Destroy (0.2ms)  DELETE FROM "users" WHERE "users"."id" = ?  [["id", 2]]
   (4.8ms)  commit transaction
 => #<User id: 2, email: "sample_b@gmail.com", password: "password2", name: "田中 花子", created_at: "2019-09-02 02:21:30", updated_at: "2019-09-02 02:43:44"> 

 

User.allで全ユーザを確認します。

 > User.all
  User Load (0.1ms)  SELECT  "users".* FROM "users" LIMIT ?  [["LIMIT", 11]]
 => #<ActiveRecord::Relation []> 

id = 2のユーザも削除されていることが確認できます。

プルリクエストの作成

このように、migrationファイルモデルファイルを作成することで、容易にデータベースを操作することができます。

では、ここまでの内容をコミットし、githubへプッシュします。

まずは、railsコンソールの中にいる状態になっているので、コンソールから抜けます。

> exit
$ 

↑「$」になっていればOK

> :railsコンソールの中

$:ターミナル上

まずは、gitのリポジトリのルートディレクトリに移動します。

$ cd ~/hello_world/

 

コミットします。

$ git add -A
$ git commit -m "Userモデルを作成"
[feature/create_user_model aa3d468] Userモデルを作成
 Committer: EC2 Default User <ec2-user@ip-172-31-18-105.us-east-2.compute.internal>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

    git config --global user.name "Your Name"
    git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

 5 files changed, 54 insertions(+)
 create mode 100644 hello_world_app/app/models/user.rb
 create mode 100644 hello_world_app/db/migrate/20190902015009_create_users.rb
 create mode 100644 hello_world_app/db/schema.rb
 create mode 100644 hello_world_app/test/fixtures/users.yml
 create mode 100644 hello_world_app/test/models/user_test.rb

 

pushします。

$ git push origin feature/create_user_model
Counting objects: 15, done.
Compressing objects: 100% (14/14), done.
Writing objects: 100% (15/15), 2.08 KiB | 532.00 KiB/s, done.
Total 15 (delta 3), reused 0 (delta 0)
remote: Resolving deltas: 100% (3/3), completed with 3 local objects.
remote: 
remote: Create a pull request for 'feature/create_user_model' on GitHub by visiting:
remote:      https://github.com/wakitakomure/hello_world/pull/new/feature/create_user_model
remote: 
To github.com:wakitakomure/hello_world.git
 * [new branch]      feature/create_user_model -> feature/create_user_model

 

次に、githubを開いて、「Compare & pull request」をクリックします。

これで、リモートのmasterブランチにマージされました。

最後に、ローカルのmasterブランチにもプルしておきましょう。

まず、ブランチをmasterに切り替えます。

$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

 

次に、プルします。

$ git pull origin master
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (1/1), done.
From github.com:wakitakomure/hello_world
 * branch            master     -> FETCH_HEAD
   16b1834..6ca97e1  master     -> origin/master
Updating 16b1834..6ca97e1
Fast-forward
 hello_world_app/app/models/user.rb                        |  2 ++
 hello_world_app/db/migrate/20190902015009_create_users.rb | 11 +++++++++++
 hello_world_app/db/schema.rb                              | 23 +++++++++++++++++++++++
 hello_world_app/test/fixtures/users.yml                   | 11 +++++++++++
 hello_world_app/test/models/user_test.rb                  |  7 +++++++
 5 files changed, 54 insertions(+)
 create mode 100644 hello_world_app/app/models/user.rb
 create mode 100644 hello_world_app/db/migrate/20190902015009_create_users.rb
 create mode 100644 hello_world_app/db/schema.rb
 create mode 100644 hello_world_app/test/fixtures/users.yml
 create mode 100644 hello_world_app/test/models/user_test.rb

 

最後に、feature/create_user_modelブランチを削除しておきましょう。

$ git branch -D feature/create_user_model
Deleted branch feature/create_user_model (was aa3d468).

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA