###ユーザーオブジェクトを作成する
Railsコンソールを使ってデータモデルを調べてみましょう。
データベースを変更したくないので、コンソールをサンドボックスモードで起動します。
buntu:~/environment/sample_app (modeling-users) $ rails console --sandbox
Running via Spring preloader in process 13943
Loading development environment in sandbox (Rails 6.0.3)
Any modifications you make will be rolled back on exit
>>
コンソールをサンドボックスで起動すると、そのセッションで行ったデータベースへの変更をコンソールの終了時にすべて “ロールバック”(取り消し)
してくれます。
User.newで新しいユーザーオブジェクトを生成しましたが、リスト 4.17のexample_userファイルを明示的にrequireするまでこのオブジェクトにはアクセスできませんでした。
しかし、モデルを使うと状況は異なります。
Railsコンソールは起動時にRailsの環境を自動的に読み込み、その環境にはモデルも含まれます。つまり、新しいユーザーオブジェクトを作成するときに余分な作業を行わずに済む。
>> User.new
(0.1ms) begin transaction
=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil>
User.newを引数なしで呼んだ場合は、すべての属性がnilのオブジェクトを返します
オブジェクトの属性を設定するための初期化ハッシュ(hash)を引数に取るように、Userクラスの例(user_example.rb)を設計しました。
>> user = User.new(name: "Michael Hartl", email: "michael@example.com")
(0.1ms) begin transaction
=> #<User id: nil, name: "Michael Hartl", email: "michael@example.com", created_at: nil, updated_at: nil>
Active Recordを理解する上で、「有効性(Validity)」という概念も重要です
今はまず先ほどのuserオブジェクトが有効かどうか確認してみましょう。確認するためにはvalid?メソッドを使います
>> user.valid?
=> true
現時点ではまだデータベースにデータは格納されていません。
User.newはメモリ上でオブジェクトを作成しただけで、user.valid?という行はただオブジェクトが有効かどうかを確認しただけとなる
データベースにUserオブジェクトを保存するためには、userオブジェクトからsaveメソッドを呼び出す必要があります。
>> user.save
(0.1ms) SAVEPOINT active_record_1
User Create (4.4ms) INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "Michael Hartl"], ["email", "michael@example.com"], ["created_at", "2021-09-22 16:21:12.330460"], ["updated_at", "2021-09-22 16:21:12.330460"]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> true
saveメソッドは、成功すればtrueを、失敗すればfalse
を返します
Railsコンソール上ではuser.saveに対応するSQLコマンドやその結果(INSERT INTO "users"…)も表示
するようになっています。
作成した時点でのユーザーオブジェクトは、id属性、マジックカラムであるcreated_at属性とupdated_at属性の値がいずれもnil
であったことを思い出してください。
saveメソッドを実行した後に何が変更されたのか
を確認してみましょう。
>> user
=> #<User id: 1, name: "Michael Hartl", email: "michael@example.com", created_at: "2021-09-22 16:21:12", updated_at: "2021-09-22 16:21:12">
上の結果から、idには1という値が代入され、一方でマジックカラムには現在の日時が代入されているのがわかります。
現在、作成と更新のタイムスタンプは同一ですが、更新するようになると(6.1.5)これらの値が異なっていきます。
Userモデルのインスタンスはドット記法を用いてその属性にアクセスすることができます。
>> user.name
=> "Michael Hartl"
>> user.email
=> "michael@example.com"
>> user.updated_at
=> #############
上で見たようにモデルの生成と保存を2つのステップに分けておくと何かと便利
です
>> User.create
(0.1ms) SAVEPOINT active_record_1
User Create (0.1ms) INSERT INTO "users" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2021-09-22 16:27:20.172799"], ["updated_at", "2021-09-22 16:27:20.172799"]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> #<User id: 2, name: nil, email: nil, created_at: "2021-09-22 16:27:20", updated_at: "2021-09-22 16:27:20">
>> foo = User.create(name: "Foo", email: "foo@bar.com")
(0.1ms) SAVEPOINT active_record_1
User Create (0.1ms) INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "Foo"], ["email", "foo@bar.com"], ["created_at", "2021-09-22 16:30:23.066987"], ["updated_at", "2021-09-22 16:30:23.066987"]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> #<User id: 3, name: "Foo", email: "foo@bar.com", created_at: "2021-09-22 16:30:23", updated_at: "2021-09-22 16:30:23">
User.createは、trueかfalseを返す代わりに、ユーザーオブジェクト自身を返す
ことに注目してください。
返されたユーザーオブジェクトは変数に代入する
こともできます。
>> foo.destroy
(0.1ms) SAVEPOINT active_record_1
User Destroy (0.1ms) DELETE FROM "users" WHERE "users"."id" = ? [["id", 3]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> #<User id: 3, name: "Foo", email: "foo@bar.com", created_at: "2021-09-22 16:30:23", updated_at: "2021-09-22 16:30:23">
destroyはcreateの逆です。
createと同じようにdestroyはそのオブジェクト自身を返しますが、その戻り値を使ってもう一度destroyを呼ぶことはできません
>> foo.destroy
(0.1ms) SAVEPOINT active_record_1
User Destroy (0.1ms) DELETE FROM "users" WHERE "users"."id" = ? [["id", 3]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> #<User id: 3, name: "Foo", email: "foo@bar.com", created_at: "2021-09-22 16:30:23", updated_at: "2021-09-22 16:30:23">
>> foo
=> #<User id: 3, name: "Foo", email: "foo@bar.com", created_at: "2021-09-22 16:30:23", updated_at: "2021-09-22 16:30:23">
削除されたオブジェクトは次のようにまだメモリ上に残っています
。
オブジェクトが本当に削除されたかどうかをどのようにして知ればよい
のでしょうか
保存して削除されていないオブジェクト
の場合、どうやってデータベースからユーザーを取得する
のでしょうか
これらの問いに答えるためには、Active Recordを使ってUserオブジェクトを検索する方法について学ぶ必要があります。
###演習
1.user.nameとuser.emailが、どちらもStringクラスのインスタンスであることを確認してみてください。
>> foo = user.name
=> "Michael Hartl"
>> foo.class
=> String
>> user.email.class
=> String
2.created_atとupdated_atは、どのクラスのインスタンスでしょうか?
>> user.created_at.class
=> ActiveSupport::TimeWithZone
>> user.updated_at.class
=> ActiveSupport::TimeWithZone
ActiveSupport::TimeWithZoneクラスらしい。