LoginSignup
1
0

More than 3 years have passed since last update.

コーディング未経験のPO/PdMのためのRails on Dockerハンズオン vol.5 - Model and CRUD -

Last updated at Posted at 2020-02-10

はじめに

第5回は、Modelを作って遊んでみます!
Modelはデータベースと密に関係していますので、メソッドをつかってCRUDを試してみます。

前回のソースコード

前回のソースコードはこちらに格納してます。今回のだけやりたい場合はこちらからダウンロードしてください。

Userモデルを作ろう

今回作るModelは以下の通り。
image.png
ER図を描くツールはdbdiagram.ioを使ってます。Entityしか書いてないから何ともですが、便利なツールです。

Userモデルがどんなモデルかといえば、Integer型のidをprimary keyとして、String型のname, email、Datetime型(年月日時分秒)のcreated_at(作成日時), updated_at(更新日時)を持っています。

rails generate model

モデルを作成するコマンドはrails generate modelです。Modelに必要なファイルとそのModelのデータをDBに登録するためにDB側にテーブルを作る必要があるのでマイグレーションファイルを作成してくれます。

rails generate model NAME [field:type field:type]が型ですね。
NAMEがモデルの名前です。fieldがモデルのattribute(属性)、typeが型です。

早速、ER図のモデルを作ってみましょう!

$ docker-compose up -d
$ docker-compose exec web ash
# rails generate model user name:string email:string

注目点はid, created_at, updated_atのことはコマンドで定義していないところです。ここはあとで説明。

マイグレーションファイル

先ほどのコマンド実行でマイグレーションファイルが生成されています。

db/migrate/YYYYMMDDhhmmss_create_user.rb
class CreateUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email
      t.timestamps
    end
  end
end

Scaffoldの時も実は同じようにファイルができていたんですが、中身を見るのは初めてですね。
rails db:migrateをするとRailsがこのファイルを読み込んでDBにSQLを発行してくれているんですね。
先ほどコマンドで定義したname, emailと一緒にtimestampsというものがあります。これがcreated_at, updated_atを作ってくれるやつでモデルを作成するときにRailsがデフォルトで付けてくれています。

また、create_tableはデフォルトでprimary keyとしてInteger型のidを付けてくれます。
なので、このままマイグレーションファイルをdb:migrateすれば先ほどのER図通りのテーブルを作成してくれます。

# rails db:migrate

Userモデルで遊んでみる

ここからは作成したUserモデルを使ってCRUDで遊んでみます。
CRUDとはデータを操作する上で基本となるCreate(作成)、Read(参照)、Update(更新)、Delete(削除)の頭文字をとったものです。Railsの場合はSQL文をコーディングするのではなく、モデルのメソッドを使うだけでCRUDができちゃうのでそれを体感しましょう!

ここからはRails consoleを使っていきます。これでRailsアプリケーションとコマンドラインで対話式にやりとりができます。
Rails consoleはそのままでもいいのですが、pryというツールをインストールすることでRails consoleがみやすくなるのでそうします。

Gemfile
...
group :development, :test do
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
+ gem 'pry-rails'
end
...

gemを追加でインストールする場合は、再度Docker imageをビルドします。今立っているコンテナは古いイメージをもとに作られたコンテナなので一回落として、新しくビルドしたイメージで再度コンテナを作ってあげましょう。

# exit
$ docker-compose down
$ docker-compose build
$ docker-compose up -d

コンテナを起動できたら、コンテナの中でrails consoleコマンドを使ってRails consoleを立ち上げましょう!

$ docker-compose exec web ash
# rails console
Running via Spring preloader in process 335
Loading development environment (Rails 6.0.2.1)
[1] pry(main)>

Rails console内では接頭に>がつくので、>がついている時はRails consoleの中でコマンドを実行しているんだなと思ってくださいね。

Create

モデルの作成の方法は大きく2種類あります。

  • newメソッドでモデルオブジェクトを作成し、saveメソッドでデータ保存する
  • createメソッドでオブジェクト作成とデータ保存を同時に行う

Create 1: new+save

例でtanaka@sample.comのメアドのTaro Tanakaさんを作ってみましょう!

> user = User.new(name: "Taro Tanaka", email: "tanaka@sample.com")
=> #<User:0x000056543a28cfa0
 id: nil,
 name: "Taro Tanaka",
 email: "tanaka@sample.com",
 created_at: nil,
 updated_at: nil>
> user.save
   (0.6ms)  BEGIN
  User Create (11.3ms)  INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["name", "Taro Tanaka"], ["email", "tanaka@sample.com"], ["created_at", "2020-03-09 13:02:13.882889"], ["updated_at", "2020-03-09 13:02:13.882889"]]
   (2.7ms)  COMMIT
=> true

まず、User.newで例の属性を持つUserモデルオブジェクトを作成し変数userに代入しています。

その後、saveメソッドを実行。実行後のコンソールからDBにINSERTしているのがわかると思います。
RailsではModelのメソッドを使うことでとても簡単にSQLの操作ができるようになります。
saveメソッドはデータ作成に成功したらtrueを失敗したらfalseを返却するメソッドです。

また、.の形で属性の情報を取得したり設定したりできるので、以下のようなやり方でもデータを作成することができます。
yamada@sample.comのメアドのHanako Yamadaさんを作ってみます!

> user = User.new
=> #<User:0x000056543a58a298
 id: nil,
 name: nil,
 email: nil,
 created_at: nil,
 updated_at: nil>
> user.name = "Hanako Yamada"
=> "Hanako Yamada"
> user.email = "yamada@sample.com"
=> "yamada@sample.com"
> user.save
   (0.8ms)  BEGIN
  User Create (1.6ms)  INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["name", "Hanako Yamada"], ["email", "yamada@sample.com"], ["created_at", "2020-03-09 13:06:00.252962"], ["updated_at", "2020-03-09 13:06:00.252962"]]
   (1.0ms)  COMMIT
=> true

Create 2: create

createメソッドはnewメソッドとsaveメソッドを同時に行うメソッドっす。
john@sample.comのメアドのJohn Smithを作ります。突然の外国人ですが、『John Smith』は日本でいう『名無しの権兵衛』です。

> User.create(name: "John Smith", email: "john@sample.com")
   (0.6ms)  BEGIN
  User Create (1.0ms)  INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["name", "John Smith"], ["email", "john@sample.com"], ["created_at", "2020-03-09 13:06:23.424103"], ["updated_at", "2020-03-09 13:06:23.424103"]]
   (2.2ms)  COMMIT
=> #<User:0x000056543a8b3320
 id: 3,
 name: "John Smith",
 email: "john@sample.com",
 created_at: Mon, 09 Mar 2020 13:06:23 JST +09:00,
 updated_at: Mon, 09 Mar 2020 13:06:23 JST +09:00>

createは基本的にはnew+saveなのですが、作成が成功した場合はそのモデルオブジェクト、失敗した場合はfalseを返却するところが大きく違うポイントです。

Read

データを確認するメソッドはかなりあります。ここでは特に利用頻度が高いであろうメソッドをご紹介します。

all

allメソッドはそのモデルの全てのレコードをオブジェクトの配列として取得します。

> User.all
  User Load (17.1ms)  SELECT "users".* FROM "users"
=> #<User:0x000056543a8b3320
 id: 3,
 name: "John Smith",
 email: "john@sample.com",
 created_at: Mon, 09 Mar 2020 13:06:23 JST +09:00,
 updated_at: Mon, 09 Mar 2020 13:06:23 JST +09:00>
[8] pry(main)> User.all
  User Load (2.8ms)  SELECT "users".* FROM "users"
=> [#<User:0x000056543a958320
  id: 1,
  name: "Taro Tanaka",
  email: "tanaka@sample.com",
  created_at: Mon, 09 Mar 2020 13:02:13 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:02:13 JST +09:00>,
 #<User:0x000056543a958140
  id: 2,
  name: "Hanako Yamada",
  email: "yamada@sample.com",
  created_at: Mon, 09 Mar 2020 13:06:00 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:06:00 JST +09:00>,
 #<User:0x000056543a958050
  id: 3,
  name: "John Smith",
  email: "john@sample.com",
  created_at: Mon, 09 Mar 2020 13:06:23 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:06:23 JST +09:00>]

find

findメソッドはprimary keyの値を指定して1件のオブジェクトを取得するメソッドです。

> User.find(1)
  User Load (1.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
=> #<User:0x000056543afed488
 id: 1,
 name: "Taro Tanaka",
 email: "tanaka@sample.com",
 created_at: Mon, 09 Mar 2020 13:02:13 JST +09:00,
 updated_at: Mon, 09 Mar 2020 13:02:13 JST +09:00>

マッチするレコードがない場合は、ActiveRecord::RecordNotFound Exceptionを発生させます。

> User.find(5)
  User Load (3.8ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 5], ["LIMIT", 1]]
ActiveRecord::RecordNotFound: Couldn't find User with 'id'=5
from /usr/local/bundle/gems/activerecord-6.0.2.1/lib/active_record/core.rb:177:in `find'

find_by

find_byメソッドは指定したカラムの条件にマッチした1件のオブジェクトを取得するメソッドです。

> User.find_by(email: "john@sample.com")
  User Load (2.8ms)  SELECT "users".* FROM "users" WHERE "users"."email" = $1 LIMIT $2  [["email", "john@sample.com"], ["LIMIT", 1]]
=> #<User:0x00005654375fba40
 id: 3,
 name: "John Smith",
 email: "john@sample.com",
 created_at: Mon, 09 Mar 2020 13:06:23 JST +09:00,
 updated_at: Mon, 09 Mar 2020 13:06:23 JST +09:00>

マッチするレコードが存在しない場合はnilを返却します。

> User.find_by(email: "hoge@sample.com")
  User Load (2.7ms)  SELECT "users".* FROM "users" WHERE "users"."email" = $1 LIMIT $2  [["email", "hoge@sample.com"], ["LIMIT", 1]]
=> nil

また、find_byメソッドでは複数の条件全てにヒットする1レコードを取得する書き方もできます。

> User.find_by(name: "John Smith", email: "john@sample.com")
  User Load (2.2ms)  SELECT "users".* FROM "users" WHERE "users"."name" = $1 AND "users"."email" = $2 LIMIT $3  [["name", "John Smith"], ["email", "john@sample.com"], ["LIMIT", 1]]
=> #<User:0x00005654388b5b68
 id: 3,
 name: "John Smith",
 email: "john@sample.com",
 created_at: Mon, 09 Mar 2020 13:06:23 JST +09:00,
 updated_at: Mon, 09 Mar 2020 13:06:23 JST +09:00>

こんな感じでユーザーを特定することができます!

where

whereメソッドはSQLのWHERE句と同様、レコードの検索条件を指定し、条件にマッチしたレコードをオブジェクトの配列として取得します。
条件はハッシュ型で書くのがわかりやすくてオススメ。

等値条件

あるカラムが特定の値と同一であるレコードを取得する場合、単にkey: valueの形で条件を指定するだけです。

> User.where(id: 1)
  User Load (1.7ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1  [["id", 1]]
=> [#<User:0x0000565439591ee0
  id: 1,
  name: "Taro Tanaka",
  email: "tanaka@sample.com",
  created_at: Mon, 09 Mar 2020 13:02:13 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:02:13 JST +09:00>]

範囲条件

valueには範囲を指定することもできます。Rubyでは0 ≦ x ≦ 20..20 ≦ x < 20...2と表現します。

> User.where(id: 1..2)
  User Load (2.6ms)  SELECT "users".* FROM "users" WHERE "users"."id" BETWEEN $1 AND $2  [["id", 1], ["id", 2]]
=> [#<User:0x0000565439e6a940
  id: 1,
  name: "Taro Tanaka",
  email: "tanaka@sample.com",
  created_at: Mon, 09 Mar 2020 13:02:13 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:02:13 JST +09:00>,
 #<User:0x0000565439e6a7d8
  id: 2,
  name: "Hanako Yamada",
  email: "yamada@sample.com",
  created_at: Mon, 09 Mar 2020 13:06:00 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:06:00 JST +09:00>]

サブセット条件

valueには配列を指定することも可能です。

> User.where(id: [1, 3])
  User Load (2.8ms)  SELECT "users".* FROM "users" WHERE "users"."id" IN ($1, $2)  [["id", 1], ["id", 3]]
=> [#<User:0x000056543a0993b0
  id: 1,
  name: "Taro Tanaka",
  email: "tanaka@sample.com",
  created_at: Mon, 09 Mar 2020 13:02:13 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:02:13 JST +09:00>,
 #<User:0x000056543a0991a8
  id: 3,
  name: "John Smith",
  email: "john@sample.com",
  created_at: Mon, 09 Mar 2020 13:06:23 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:06:23 JST +09:00>]

NOT条件

where.notメソッドを使えば、条件にヒットしないものを検索することもできます。

> User.where.not(id: 1)
  User Load (2.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" != $1  [["id", 1]]
=> [#<User:0x000056543a2a82f0
  id: 2,
  name: "Hanako Yamada",
  email: "yamada@sample.com",
  created_at: Mon, 09 Mar 2020 13:06:00 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:06:00 JST +09:00>,
 #<User:0x000056543a2a8228
  id: 3,
  name: "John Smith",
  email: "john@sample.com",
  created_at: Mon, 09 Mar 2020 13:06:23 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:06:23 JST +09:00>]

AND条件

複数の条件にマッチするレコードを取得したい場合は、ハッシュの組み合わせを増やせばいいだけです。

> User.where(name: "Taro Tanaka", email: "tanaka@sample.com")
  User Load (1.4ms)  SELECT "users".* FROM "users" WHERE "users"."name" = $1 AND "users"."email" = $2  [["name", "Taro Tanaka"], ["email", "tanaka@sample.com"]]
=> [#<User:0x000056543a3f8330
  id: 1,
  name: "Taro Tanaka",
  email: "tanaka@sample.com",
  created_at: Mon, 09 Mar 2020 13:02:13 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:02:13 JST +09:00>]

OR条件

複数の条件のうち、どれか一つでも当てはまるレコードを取得したい場合はorメソッドを使います。これはやや面倒(直感的でない)っす。

> User.where(id: 1).or(User.where(email: "john@sample.com"))
  User Load (3.2ms)  SELECT "users".* FROM "users" WHERE ("users"."id" = $1 OR "users"."email" = $2)  [["id", 1], ["email", "john@sample.com"]]
=> [#<User:0x000056543a4c1230
  id: 1,
  name: "Taro Tanaka",
  email: "tanaka@sample.com",
  created_at: Mon, 09 Mar 2020 13:02:13 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:02:13 JST +09:00>,
 #<User:0x000056543a4c1000
  id: 3,
  name: "John Smith",
  email: "john@sample.com",
  created_at: Mon, 09 Mar 2020 13:06:23 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:06:23 JST +09:00>]

order

orderメソッドは並び順を指定してくれます。使い方は並び順の条件にしたいカラムを指定するだけで昇順で並び替えてくれます。

> User.order(:email)
  User Load (3.5ms)  SELECT "users".* FROM "users" ORDER BY "users"."email" ASC
=> [#<User:0x000056543a686728
  id: 3,
  name: "John Smith",
  email: "john@sample.com",
  created_at: Mon, 09 Mar 2020 13:06:23 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:06:23 JST +09:00>,
 #<User:0x000056543a686570
  id: 1,
  name: "Taro Tanaka",
  email: "tanaka@sample.com",
  created_at: Mon, 09 Mar 2020 13:02:13 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:02:13 JST +09:00>,
 #<User:0x000056543a6863b8
  id: 2,
  name: "Hanako Yamada",
  email: "yamada@sample.com",
  created_at: Mon, 09 Mar 2020 13:06:00 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:06:00 JST +09:00>]

メアド昇順に並び変わってますね。

降順に並べる場合はdescを使います。(昇順も同じようにascを指定して表現することもできます)

> User.order(email: :desc)
  User Load (2.5ms)  SELECT "users".* FROM "users" ORDER BY "users"."email" DESC
=> [#<User:0x000056543a8ddda0
  id: 2,
  name: "Hanako Yamada",
  email: "yamada@sample.com",
  created_at: Mon, 09 Mar 2020 13:06:00 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:06:00 JST +09:00>,
 #<User:0x000056543a8ddb98
  id: 1,
  name: "Taro Tanaka",
  email: "tanaka@sample.com",
  created_at: Mon, 09 Mar 2020 13:02:13 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:02:13 JST +09:00>,
 #<User:0x000056543a8dda58
  id: 3,
  name: "John Smith",
  email: "john@sample.com",
  created_at: Mon, 09 Mar 2020 13:06:23 JST +09:00,
  updated_at: Mon, 09 Mar 2020 13:06:23 JST +09:00>]

逆順になってる。

first

firstメソッドはprimary keyの順番で最初の1件のオブジェクトを取得するメソッドです。

> User.first
  User Load (2.1ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1]]
=> #<User:0x000056543aa14570
 id: 1,
 name: "Taro Tanaka",
 email: "tanaka@sample.com",
 created_at: Mon, 09 Mar 2020 13:02:13 JST +09:00,
 updated_at: Mon, 09 Mar 2020 13:02:13 JST +09:00>

結果は先ほどのfindメソッドと同じTaro Tanakaがヒットしていますが、SQL文に違いがあることがわかります。find_byWHEREで検索しているのに対して、firstORDERで検索してます。

また、orderメソッドと組み合わせることで、primary key以外の属性に対しても一番先頭のオブジェクトを取得することができます。こっちの方が便利な気がする。

> User.order(:email).first
  User Load (2.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."email" ASC LIMIT $1  [["LIMIT", 1]]
=> #<User:0x000056543aab5e98
 id: 3,
 name: "John Smith",
 email: "john@sample.com",
 created_at: Mon, 09 Mar 2020 13:06:23 JST +09:00,
 updated_at: Mon, 09 Mar 2020 13:06:23 JST +09:00>

last

なんとなくメソッド名からわかりますね。firstの逆、一番後ろのモデルオブジェクトを取得するメソッドです。

> User.last
  User Load (1.4ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1  [["LIMIT", 1]]
=> #<User:0x000056543ab34fb8
 id: 3,
 name: "John Smith",
 email: "john@sample.com",
 created_at: Mon, 09 Mar 2020 13:06:23 JST +09:00,
 updated_at: Mon, 09 Mar 2020 13:06:23 JST +09:00>

もちろんorderと組み合わせて使うことも可能!

> User.order(:email).last
  User Load (2.4ms)  SELECT "users".* FROM "users" ORDER BY "users"."email" DESC LIMIT $1  [["LIMIT", 1]]
=> #<User:0x000056543abc4a78
 id: 2,
 name: "Hanako Yamada",
 email: "yamada@sample.com",
 created_at: Mon, 09 Mar 2020 13:06:00 JST +09:00,
 updated_at: Mon, 09 Mar 2020 13:06:00 JST +09:00>

Update

データの更新の方法も大きく2つあります。どちらの場合もまずfindやfind_byを使って単一のオブジェクトを取得します。で属性のデータを変更したあとにsaveメソッドを使って更新するか、updateメソッドで更新するかです。

属性を更新してsave

一つ目の方法は取得したオブジェクトの属性の値を変更してCreateと同じようにsaveメソッドを使うことです。
Taro Tanakaさんのemailtaro@sample.comに変更してみましょう!

> user = User.find(1)
  User Load (2.9ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
=> #<User:0x000056543ac45060
 id: 1,
 name: "Taro Tanaka",
 email: "tanaka@sample.com",
 created_at: Mon, 09 Mar 2020 13:02:13 JST +09:00,
 updated_at: Mon, 09 Mar 2020 13:02:13 JST +09:00>
> user.email = "taro@sample.com"
=> "taro@sample.com"
> user.save
   (0.4ms)  BEGIN
  User Update (3.5ms)  UPDATE "users" SET "email" = $1, "updated_at" = $2 WHERE "users"."id" = $3  [["email", "taro@sample.com"], ["updated_at", "2020-03-09 13:17:32.314299"], ["id", 1]]
   (1.6ms)  COMMIT
=> true
> User.find(1)
  User Load (4.0ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
=> #<User:0x000056543adb0c38
 id: 1,
 name: "Taro Tanaka",
 email: "taro@sample.com",
 created_at: Mon, 09 Mar 2020 13:02:13 JST +09:00,
 updated_at: Mon, 09 Mar 2020 13:17:32 JST +09:00>

email変わってますね。updated_atも自動的に更新されてます!

updateメソッドを使う

もう一つの方法はupdateメソッドを使う方法です。
今度は、Hanako Yamadaさんのemailhanako@sample.comに変更してみます!

> user = User.find(2)
  User Load (2.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 2], ["LIMIT", 1]]
=> #<User:0x000056543ae6e990
 id: 2,
 name: "Hanako Yamada",
 email: "yamada@sample.com",
 created_at: Mon, 09 Mar 2020 13:06:00 JST +09:00,
 updated_at: Mon, 09 Mar 2020 13:06:00 JST +09:00>
> user.update(email: "hanako@sample.com")
   (0.5ms)  BEGIN
  User Update (1.3ms)  UPDATE "users" SET "email" = $1, "updated_at" = $2 WHERE "users"."id" = $3  [["email", "hanako@sample.com"], ["updated_at", "2020-03-09 13:18:46.735580"], ["id", 2]]
   (0.8ms)  COMMIT
=> true
> User.find(2)
  User Load (4.8ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 2], ["LIMIT", 1]]
=> #<User:0x000056543af50368
 id: 2,
 name: "Hanako Yamada",
 email: "hanako@sample.com",
 created_at: Mon, 09 Mar 2020 13:06:00 JST +09:00,
 updated_at: Mon, 09 Mar 2020 13:18:46 JST +09:00>

updateメソッドの場合は更新したい属性と値を括弧の中で指定します。
updateメソッドもcreateメソッドと同じで、データ保存に成功した場合はそのモデルオブジェクトが結果として返却されていますね。

Delete

データの削除にはdestroyメソッドを使います。今回はJohn Smithさんが退会した、みたいな感じでデータ削除してみましょう。

> user = User.find(3)
  User Load (0.9ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 3], ["LIMIT", 1]]
=> #<User:0x000056543b009660
 id: 3,
 name: "John Smith",
 email: "john@sample.com",
 created_at: Mon, 09 Mar 2020 13:06:23 JST +09:00,
 updated_at: Mon, 09 Mar 2020 13:06:23 JST +09:00>
> user.destroy
   (0.7ms)  BEGIN
  User Destroy (2.1ms)  DELETE FROM "users" WHERE "users"."id" = $1  [["id", 3]]
   (3.1ms)  COMMIT
=> #<User:0x000056543b009660
 id: 3,
 name: "John Smith",
 email: "john@sample.com",
 created_at: Mon, 09 Mar 2020 13:06:23 JST +09:00,
 updated_at: Mon, 09 Mar 2020 13:06:23 JST +09:00>
> User.find(3)
  User Load (1.6ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 3], ["LIMIT", 1]]
ActiveRecord::RecordNotFound: Couldn't find User with 'id'=3
from /usr/local/bundle/gems/activerecord-6.0.2.1/lib/active_record/core.rb:177:in `find'

あっけないですね。
最終的にもともとJohn Smithさんに割り当てられていたID=3で検索してみたところ、ActiveRecord::RecordNotFoundの例外が発生していることからJohn Smithさんがちゃんと削除されていることがわかります。

後片付け

今日のデータをきれいにしておきましょう。今回もDBの再作成で。

> quit

quitコマンドでRails consoleから抜け出せます。

# exit

exitコンテナからぬけまして、

$ docker-compose down
$ docker-compose run --rm web rails db:migrate:reset

コンテナを停止して、rails db:migrate:resetを実行っと。

まとめ

今回は、Modelの作成と基本的なモデル(データ)の操作をやってみました。
ここは僕の中でRailsの使いやすいところだなーと思っているのですが、SQLを隠してくれているんですよね。モデルのメソッドって形でデータのCRUDできるのは本当に使いやすい。

次回はモデルにバリデーションをつけていこうと思います。今のままだとnameemailに値がなくても保存できちゃうんですよね。
あと、Userモデルにセキュアなパスワードの属性を追加していきます。単にパスワードをカラム追加してしまったら万が一データが盗まれた時に大変な個人情報流出です。Railsではセキュアなパスワードを扱うためにhas_secure_passwordメソッドが用意されているのでその使い方を紹介します。

では、次回も乞うご期待!ここまでお読みいただきありがとうございました!

Next: コーディング未経験のPO/PdMのためのRails on Dockerハンズオン vol.6 - Model validation - - Qiita

本日のソースコード

Reference

Other Hands-on Links

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0