2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

アプリを作る Micropostモデル

Posted at

###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
2
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?