###user-micropostsにチェックアウト
git checkout -b user-microposts
###マイクロポストのモデルを作成
ubuntu:~/environment/my_app (user-microposts) $ rails generate model Micropost content:text user:references
user:references
自動的にインデックスと外部キー参照付きのuser_idカラムが追加され、UserとMicropostを関連付けする下準備をしてくれます。
Running via Spring preloader in process 4915
invoke active_record
create db/migrate/20220122135127_create_microposts.rb
create app/models/micropost.rb
invoke test_unit
create test/models/micropost_test.rb
create test/fixtures/microposts.yml
###app/models/micropost.rb
class Micropost < ApplicationRecord
belongs_to :user
# userモデルと関連付けがされる
# belongs_to関連付けを行なうと、他方のモデルとの間に「1対1」のつながりが設定されます。
default_scope -> { order(created_at: :desc) }
# アロー演算子は、ラムダを作成するための演算子です。
# ラムダとはproc.newメソッドのようにブロックを変数に代入をすることが出来るprocクラスのオブジェクトです。
#引数を受け取るブロック変数をXとした場合は、
# -> (x){
# (やりたい処理)
# }
# デフォルト値を与えることも可能
# --------------------------------
# 2.6.3 :001 > test = -> (x) {
# 2.6.3 :002 > p x
# 2.6.3 :003?> }
# = > #<Proc:0x0000555b4d7f3070@(irb):1 (lambda)>
# 2.6.3 :004 > test.call(1)
# 1
# => 1
# 2.6.3 :005 > test = -> (x = 0) {p x}
# => #<Proc:0x0000555b4d89b018@(irb):5 (lambda)>
# 2.6.3 :006 > test.call()
# 0
# => 0
# --------------------------------
# default_scope -> { order(created_at: :desc) }
# 作成時刻の降順に並び替えるらしい
# 変数はどうかわからないが
# 処理は{ order(created_at: :desc) }らしい
# order()
# モデル.order(引数..)
# 取得したレコードを特定のキーで並び替える
# DESC 大きい方から小さい方に並ぶ(降順)
validates :user_id, presence: true
# user_idの存在性を検証
validates :content, presence: true, length: { maximum: 140 }
# マイクロポストの内容の存在性が有り、最大長が140文字以内に検証する
end
###db/migrate/[timestamp]_create_microposts.rb
class CreateMicroposts < ActiveRecord::Migration[6.0]
def change
create_table :microposts do |t|
# create_table :micropostsから一つずつ取り出す
t.text :content
t.references :user, null: false, foreign_key: true
t.timestamps
end
add_index :microposts, [:user_id, :created_at]
# マイクロポストに新しく属性を追加する
end
end
マイクロポストの設定の追加 属性を追加したのでrails db:migrate
を行う。
###test/models/micropost_test.rb
require 'test_helper'
class MicropostTest < ActiveSupport::TestCase
def setup
@user = users(:michael)
# このコードは慣習的に正しくない
@micropost = @user.microposts.build(content: "Lorem ipsum")
end
test "should be valid" do
assert @micropost.valid?
# マイクロポスtのインスタンス変数は有効か?
end
test "user id should be present" do
@micropost.user_id = nil
# マイクロポストのuser_idが空にする
assert_not @micropost.valid?
# 無効か確認
end
test "content should be present" do
# マイクロポストの内容を検証する
@micropost.content = " "
assert_not @micropost.valid?
end
test "content should be at most 140 characters" do
# マイクロポストの文字数制限を検証する
@micropost.content = "a" * 141
assert_not @micropost.valid?
end
test "order should be most recent first" do
assert_equal microposts(:most_recent), Micropost.first
# 最近と最初のマイクロポストは同じか検証
end
end
rails test:models
###app/models/user.rb
class User < ApplicationRecord
# 継承させる
has_many :microposts, dependent: :destroy
# ユーザーを消すとそのマイクロポストも削除されるのかな?
# has_many
# 相手のモデルとの「1対多」のつながりを表す
# 多くの場合belongs_toの反対側で使われます
# dependent: :destroy
# 親モデルを削除する際に、その親モデルに紐づく「子モデル」も一緒に削除できる
attr_accessor :remember_token, :activation_token, :reset_token
before_save :downcase_email
before_create :create_activation_digest
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, presence: true, length: { minimum: 6 }, allow_nil: true
def User.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
BCrypt::Engine.cost
# コストパラメータはテストでは最小にする
BCrypt::Password.create(string, cost: cost)
end
# ランダムなトークンを返す
def User.new_token
SecureRandom.urlsafe_base64
end
# 永続セッションのためにユーザーをデータベースに記憶する
def remember
self.remember_token = User.new_token
update_attribute(:remember_digest, User.digest(remember_token))
end
# トークンがダイジェストと一致したらtrueを返す
def authenticated?(attribute, token)
digest = send("#{attribute}_digest")
return false if digest.nil?
BCrypt::Password.new(digest).is_password?(token)
end
# ユーザーのログイン情報を破棄する
def forget
update_attribute(:remember_digest, nil)
end
def activate
# # アカウントを有効にする
update_attribute(:activated, true)
update_attribute(:activated_at, Time.zone.now)
end
# 有効化用のメールを送信する
def send_activation_email
UserMailer.account_activation(self).deliver_now
end
# パスワード再設定の属性を設定する
def create_reset_digest
self.reset_token = User.new_token
update_attribute(:reset_digest, User.digest(reset_token))
update_attribute(:reset_sent_at, Time.zone.now)
end
# パスワード再設定のメールを送信する
def send_password_reset_email
UserMailer.password_reset(self).deliver_now
end
# パスワード再設定の期限が切れている場合はtrueを返す
def password_reset_expired?
reset_sent_at < 2.hours.ago
end
private
# メールアドレスをすべて小文字にする
def downcase_email
self.email = email.downcase
end
# 有効化トークンとダイジェストを作成および代入する
def create_activation_digest
self.activation_token = User.new_token
self.activation_digest = User.digest(activation_token)
end
end
###test/fixtures/microposts.yml
orange:
content: "I just ate an orange!"
created_at: <%= 10.minutes.ago %>
user: michael
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
テストユーザーを設定する
###テストをする
ubuntu:~/environment/my_app (user-microposts) $ rails test test/models/micropost_test.rb
Running via Spring preloader in process 6654
Run options: --seed 45896
# Running:
F
Failure:
MicropostTest#test_order_should_be_most_recent_first [/home/ubuntu/environment/my_app/test/models/micropost_test.rb:31]:
--- expected
+++ actual
@@ -1 +1 @@
-#<Micropost id: 941832919, content: "Writing a short test", user_id: 762146111, created_at: "2022-01-23 03:21:13", updated_at: "2022-01-23 03:21:13">
+#<Micropost id: 12348100, content: "Sad cats are sad: https://youtu.be/PKffm2uI4dk", user_id: 762146111, created_at: "2022-01-23 01:21:13", updated_at: "2022-01-23 03:21:13">
rails test test/models/micropost_test.rb:30
....
Finished in 0.530364s, 9.4275 runs/s, 9.4275 assertions/s.
5 runs, 5 assertions, 1 failures, 0 errors, 0 skips
test "order should be most recent first" do
assert_equal microposts(:most_recent), Micropost.first
end
ここで引っ掛かっているらしい。
多分マイクロポストの内容があっていないようだ。
テストをする マイクロポストの最初と最近
ubuntu:~/environment/my_app (user-microposts) $ rails tRunning via Spring preloader in process 9070
Run options: --seed 52634
# Running:
.......................................
Finished in 4.438422s, 8.7869 runs/s, 41.6815 assertions/s.
39 runs, 185 assertions, 0 failures, 0 errors, 0 skips
さっきマイクロポストが降順にしたからテストが通ったのだろう。
###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 "should be valid" do
assert @user.valid?
end
test "name should be present" do
@user.name = ""
assert_not @user.valid?
end
test "email should be present" do
@user.email = " "
assert_not @user.valid?
end
test "name should not be too long" do
@user.name = "a" * 51
assert_not @user.valid?
end
test "email should not be too long" do
@user.email = "a" * 244 + "@example.com"
assert_not @user.valid?
end
test "email validation should accept valid addresses" do
valid_addresses = %w[user@example.com USER@foo.COM A_US-ER@foo.bar.org
first.last@foo.jp alice+bob@baz.cn]
valid_addresses.each do |valid_address|
@user.email = valid_address
assert @user.valid?, "#{valid_address.inspect} should be valid"
end
end
test "email validation should reject invalid addresses" do
invalid_addresses = %w[user@example,com user_at_foo.org user.name@example.
foo@bar_baz.com foo@bar+baz.com]
invalid_addresses.each do |invalid_address|
@user.email = invalid_address
assert_not @user.valid?, "#{invalid_address.inspect} should be invalid"
end
end
test "email addresses should be unique" do
duplicate_user = @user.dup
duplicate_user.email = @user.email.upcase
@user.save
assert_not duplicate_user.valid?
end
test "password should be present (nonblank)" do
@user.password = @user.password_confirmation = " " * 6
assert_not @user.valid?
end
test "password should have a minimum length" do
@user.password = @user.password_confirmation = "a" * 5
assert_not @user.valid?
end
test "authenticated? should return false for a user with nil digest" do
assert_not @user.authenticated?(:remember, '')
end
test "associated microposts should be destroyed" do
@user.save
# dbに保存
@user.microposts.create!(content: "Lorem ipsum")
# マイクロポストを作成する。
# create!
# 失敗するとエラー画面が表示されるらしい。
assert_difference 'Micropost.count', -1 do
# マイクロポストの数が一つ減っているか?
@user.destroy
# ユーザーを削除
end
end
end
###テストをする ユーザーが削除されたらマクロポストも削除されるか?
ubuntu:~/environment/my_app (user-microposts) $ rails t
Running via Spring preloader in process 3785
Run options: --seed 54248
# Running:
........................................
Finished in 5.028572s, 7.9545 runs/s, 36.9886 assertions/s.
40 runs, 186 assertions, 0 failures, 0 errors, 0 skips