###マイクロポストを改良する
#####デフォルトのスコープ
新しい順にマイクロポストを表示させる。
そのためにdefault scopeというテクニックを使う。
####マイクロポストの順序付けをテストする
test/models/micropost_test.rb
require 'test_helper'
.
.
.
test "order should be most recent first" do
assert_equal microposts(:most_recent), Micropost.first
# microposts(:most_recent) データベース上の最初のマイクロポスト
# Micropost.first fixture内のマイクロポスト
# 上二つが等しいか?
# マイクロポストのfixtureがあるという前提に依存しています。
end
end
####マイクロポスト用のfixture
test/fixtures/microposts.yml
orange:
content: "I just ate an orange!"
created_at: <%= 10.minutes.ago %>
user:
# ユーザーfixtureにある対応ユーザーに関連付けることをRailsに指示できます。
tau_manifesto:
content: "Check out the @tauday site by @mhartl: https://tauday.com"
created_at: <%= 3.years.ago %>
user: michael
cat_video:
content: "Sad cats are sad: https://youtu.be/PKffm2uI4dk"
created_at: <%= 2.hours.ago %>
user: michael
most_recent:
content: "Writing a short test"
created_at: <%= Time.zone.now %>
user: michael
####default_scopeでマイクロポストを順序付ける
app/models/micropost.rb
class Micropost < ApplicationRecord
# ApplicationRecordを継承したモデルが作られます
belongs_to :user
# userモデルとの間に「1対1」のつながりが設定
# 割り当てる
default_scope -> { order(created_at: :desc) }
# データベースから要素を取得したときの、
# デフォルトの順序を指定するメソッドです。
# order(created_at:desc) でこのカラムの順序に指定する
# デフォルトで最も古い投稿が最初に投稿が表示されている。
# :desc 新しい投稿から古い投稿の順になります
# -> ラムダ式という。
validates :user_id, presence: true
# presence これは存在するか
# presenceメソッドはオブジェクトが存在すればそのオブジェクトを返し、
# オブジェクトが存在しなければnilを返すメソッドとなります
validates :content, presence: true, length: { maximum: 140 }
# 最大140文字まで
end
>> -> {puts "foo" }
=> #<Proc:0x000055622fc512c8@(irb):1 (lambda)>
>> -> {puts "foo" }.call
foo
=> nil
#####Dependent: destroy
####マイクロポストは、その所有者(ユーザー)と一緒に破棄されることを保証する
app/models/user.rb
class User < ApplicationRecord
has_many :microposts, dependent: :destroy
# 他のモデルとの間に「1対多」のつながり
# has_many関連付けが使われている場合、
# 「反対側」のモデルでは多くの場合belongs_toが使われます。
# dependent: :destroy
# ユーザーが破棄された場合
# 、ユーザーのマイクロポストも同様に破棄される。
.
.
.
end
####dependent: :destroyのテスト
test/models/user_test.rb
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
@user = User.new(name: "Example User", email: "user@example.com",
password: "foobar", password_confirmation: "foobar")
end
.
.
.
test "associated microposts should be destroyed" do
# マイクロポストがユーザーと一緒に破棄されたかテスト
@user.save
# 保存する
@user.microposts.create!(content: "Lorem ipsum")
# user.microposts.create!()
# userに紐付いたマイクロポストを作成する
assert_difference 'Micropost.count', -1 do
# 削除されてマイクロポストの数が一つ減っているかどうか?
@user.destroy
# ユーザーを削除
end
end
end
#####テスト
ubuntu:~/environment/sample_app (user-microposts) $ rails t
Running via Spring preloader in process 8038
Started with run options --seed 14565
53/53: [============================] 100% Time: 00:00:04, Time: 00:00:04
Finished in 4.22841s
53 tests, 221 assertions, 0 failures, 0 errors, 0 skips
###演習
1.
Micropost.first.created_atの実行結果と、Micropost.last.created_atの実行結果を比べてみましょう。
>> Micropost.first.created_at
(1.5ms) SELECT sqlite_version(*)
Micropost Load (0.8ms) SELECT "microposts".* FROM "microposts" ORDER BY "microposts"."created_at" DESC LIMIT ? [["LIMIT", 1]]
=> Fri, 22 Oct 2021 13:59:35 UTC +00:00
>> Micropost.last.created_at
Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" ORDER BY "microposts"."created_at" ASC LIMIT ? [["LIMIT", 1]]
=> Fri, 22 Oct 2021 06:31:48 UTC +00:00
時間が違う。
Micropost.firstを実行したときに発行されるSQL文はどうなっているでしょうか? 同様にして、Micropost.lastの場合はどうなっているでしょうか? ヒント: それぞれをコンソール上で実行したときに表示される文字列が、SQL文になります。
>> Micropost.first
Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" ORDER BY "microposts"."created_at" DESC LIMIT ? [["LIMIT", 1]]
=> #<Micropost id: 3, content: "Lorem ipsum", user_id: 1, created_at: "2021-10-22 13:59:35", updated_at: "2021-10-22 13:59:35">
>> Micropost.last
Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" ORDER BY "microposts"."created_at" ASC LIMIT ? [["LIMIT", 1]]
=> #<Micropost id: 1, content: "Lerem ipsum", user_id: 1, created_at: "2021-10-22 06:31:48", updated_at: "2021-10-22 06:31:48">
.firstが降順 .lastが昇順になっている。
データベース上の最初のユーザーを変数userに代入してください。そのuserオブジェクトが最初に投稿したマイクロポストのidはいくつでしょうか? 次に、destroyメソッドを使ってそのuserオブジェクトを削除してみてください。削除すると、そのuserに紐付いていたマイクロポストも削除されていることをMicropost.findで確認してみましょう。
>> user.microposts
Micropost Load (1.0ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."created_at" DESC LIMIT ? [["user_id", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Micropost id: 3, content: "Lorem ipsum", user_id: 1, created_at: "2021-10-22 13:59:35", updated_at: "2021-10-22 13:59:35">, #<Micropost id: 2, content: "Lorem ipsum", user_id: 1, created_at: "2021-10-22 13:53:49", updated_at: "2021-10-22 13:53:49">, #<Micropost id: 1, content: "Lerem ipsum", user_id: 1, created_at: "2021-10-22 06:31:48", updated_at: "2021-10-22 06:31:48">]>
>> user.destroy
(0.1ms) begin transaction
Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."created_at" DESC [["user_id", 1]]
Micropost Destroy (2.3ms) DELETE FROM "microposts" WHERE "microposts"."id" = ? [["id", 3]]
Micropost Destroy (0.1ms) DELETE FROM "microposts" WHERE "microposts"."id" = ? [["id", 2]]
Micropost Destroy (0.1ms) DELETE FROM "microposts" WHERE "microposts"."id" = ? [["id", 1]]
User Destroy (0.7ms) DELETE FROM "users" WHERE "users"."id" = ? [["id", 1]]
(7.4ms) commit transaction
=> #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2021-10-17 05:28:48", updated_at: "2021-10-20 14:25:39", password_digest: [FILTERED], remember_digest: nil, admin: true, activation_digest: "$2a$12$x4xVHmtrDFjVPFFWav31UebLY8r9sdT8ImzSXGSrnqt...", activated: true, activated_at: "2021-10-17 05:28:48", reset_digest: "$2a$12$FhfOA3Y7VPJ3TJJ5nNUEkuSH0hkGrrW15uyYE9EwbrC...", reset_sent_at: "2021-10-20 14:25:39">
>> Micropost.find
Traceback (most recent call last):
1: from (irb):15
ActiveRecord::RecordNotFound (Couldn't find Micropost without an ID)
###困ったこと
example_Userを削除してしまった。
調べて
rails db:migrate:reset
rails db:seed
をして治った。