はじめに
第5回は、Modelを作って遊んでみます!
Modelはデータベースと密に関係していますので、メソッドをつかってCRUDを試してみます。
前回のソースコード
前回のソースコードはこちらに格納してます。今回のだけやりたい場合はこちらからダウンロードしてください。
Userモデルを作ろう
今回作るModelは以下の通り。

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のことはコマンドで定義していないところです。ここはあとで説明。
マイグレーションファイル
先ほどのコマンド実行でマイグレーションファイルが生成されています。
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がみやすくなるのでそうします。
...
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 ≦ 2を0..2、0 ≦ x < 2を0...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_byがWHEREで検索しているのに対して、firstはORDERで検索してます。
また、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さんのemailをtaro@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さんのemailをhanako@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できるのは本当に使いやすい。
次回はモデルにバリデーションをつけていこうと思います。今のままだとnameやemailに値がなくても保存できちゃうんですよね。
あと、Userモデルにセキュアなパスワードの属性を追加していきます。単にパスワードをカラム追加してしまったら万が一データが盗まれた時に大変な個人情報流出です。Railsではセキュアなパスワードを扱うためにhas_secure_passwordメソッドが用意されているのでその使い方を紹介します。
では、次回も乞うご期待!ここまでお読みいただきありがとうございました!
Next: コーディング未経験のPO/PdMのためのRails on Dockerハンズオン vol.6 - Model validation - - Qiita
本日のソースコード
Reference
- Ruby on Rails チュートリアル:実例を使って Rails を学ぼう
- Railsタイムゾーンまとめ - Qiita
- rails-i18n/ja.yml at master · svenfuchs/rails-i18n
- もう迷わない!CSS Flexboxの使い方を徹底解説 | Web Design Trends
- 【2019年版】Google Fontsの使い方:初心者向けに解説!