見出し画像

CRUD を作成⑧

CRUD を作成⑦ の続き。
ブラウザからデータを登録できるか確認する。


作成ボタンを押す。一覧ページを見てみる。


先ほど登録した名前で一覧ページに表示されていれば登録できたことを確認できる。
登録後にどこかのページにリダイレクトするように修正する。
app/controllers/books_controller.rb を以下のように修正する。

def create
  @book = Book.new(book_params)
  if @book.save
    redirect_to books_path
  end
end

コードを変更したのでテストを実行する。
レッドになる。

...F...

Failures:

  1) Books POST /books 正常系 204 を返す
     Failure/Error: expect(response).to have_http_status(:no_content)
       expected the response to have status code :no_content (204) but it was :found (302)
     # ./spec/requests/books_spec.rb:38:in `block (4 levels) in <main>'

Finished in 0.34714 seconds (files took 2.83 seconds to load)
7 examples, 1 failure

Failed examples:

rspec ./spec/requests/books_spec.rb:36 # Books POST /books 正常系 204 を返す

リダイレクトするように修正したのでテストの期待値を変更する。
spec/requests/books_spec.rb を以下のように変更する。

describe "POST /books" do
  let(:params) { { book: { title: } } }
  let(:title) { 'test' }

  context '正常系' do
    it '302 を返す' do
      post "/books", params: params
      expect(response).to have_http_status(:found)
    end
  end
end

テストを実行する。グリーンになる。

bundle e rspec spec/requests/books_spec.rb

.......

Finished in 0.36111 seconds (files took 2.83 seconds to load)
7 examples, 0 failures

ブラウザからも試してみる。


作成ボタンを押した後、一覧ページにリダイレクトされたら成功。
次に、何も入力しない状態で作成ボタンを押してみる。データが空文字で作成されてしまう。これは許容したくないのでバリデーションを追加する。
app/models/book.rb を修正する。

class Book < ApplicationRecord
  validates :title, presence: true
end

空文字ではデータを登録できないことを確認する。そのため、テストを追加する。

RSpec.describe Book, type: :model do
  describe 'validation' do
    subject { book.valid? }

    context 'title が空文字の場合' do
      let(:book) { build(:book) }

      before { book.title = '' }

      it { is_expected.to be false } 
    end
  end
end

テストを実行する。グリーンになる。

bundle e rspec spec/models/book_spec.rb

.

Finished in 0.06566 seconds (files took 2.85 seconds to load)
1 example, 0 failures

空文字ではデータが登録できないことを担保できた。
何も入力していない状態で作成ボタンを押す。ログを見てみるとデータが登録されていないことがわかる。
バリデーションに引っかかった場合の処理をコントローラに追加する。
app/controllers/books_controller.rb を以下のように修正する。

def create
  @book = Book.new(book_params)
  if @book.save
    redirect_to books_path
  else
    render :new
  end
end

保存に失敗した場合は引き続き新規作成ページが表示される。
試しにN文字以上という制限をつけてみる。
テストを以下のように修正する。spec/models/book_spec.rb を以下のように修正する。今回は3文字以下で保存ができないようにする。

context 'title が3文字以下の場合' do
  let(:book) { build(:book) }

  before { book.title = 'ab' }

  it { is_expected.to be false } 
end

テストを実行する。当然、3文字以下というバリデーションを追加していないのでテストはレッドとなる。

bundle e rspec spec/models/book_spec.rb

.F

Failures:

  1) Book validation title が3文字以下の場合 is expected to equal false
     Failure/Error: it { is_expected.to be false }

       expected false
            got true
     # ./spec/models/book_spec.rb:20:in `block (4 levels) in <main>'

Finished in 0.07983 seconds (files took 2.82 seconds to load)
2 examples, 1 failure

Failed examples:

rspec ./spec/models/book_spec.rb:20 # Book validation title が2文字以下の場合 is expected to equal false

3文字以下という制限を加えるため app/models/book.rb を修正する。

validates :title, presence: true, length: { minimum: 3 }

N文字以上のような制限を加える場合、境界値もテストしておきたい。3文字の場合もテストしてみる。

context 'title が3文字の場合' do
  let(:book) { build(:book) }

  before { book.title = 'abc' }

  it { is_expected.to be true } 
end

3文字の場合は許容される。テストコードが重複してきたのでリファクタを行う。

RSpec.describe Book, type: :model do
  describe 'validation' do
    subject { book.valid? }

    context 'title が空文字の場合' do
      let(:book) { build(:book) }

      before { book.title = '' }

      it { is_expected.to be false } 
    end

    context 'title が3文字より少ない場合' do
      let(:book) { build(:book) }

      before { book.title = 'ab' }

      it { is_expected.to be false } 
    end

    context 'title が3文字の場合' do
      let(:book) { build(:book) }

      before { book.title = 'abc' }

      it { is_expected.to be true } 
    end
  end
end

spec/models/book_spec.rb を以下のように修正する。book という変数を3回定義していたので、1回にまとめた。

RSpec.describe Book, type: :model do
  describe 'validation' do
    subject { book.valid? }

    let(:book) { build(:book) }

    context 'title が空文字の場合' do
      before { book.title = '' }

      it { is_expected.to be false } 
    end

    context 'title が3文字より少ない場合' do
      before { book.title = 'ab' }

      it { is_expected.to be false } 
    end

    context 'title が3文字の場合' do
      before { book.title = 'abc' }

      it { is_expected.to be true } 
    end
  end
end

これで3文字より少ない場合は保存に失敗するようになった。
実際に3文字より少ない場合で作成しようとすると保存されず、3文字以上の場合は作成される。
一覧ページから新規作成ページに遷移するためにリンクを追加する。
app/views/books/index.html.erb を以下のように修正。

<%= link_to '新規作成', new_book_path %><br />

ブラウザに表示をしてみて新規作成ページに遷移できることを確認する。
次は新規作成ページから一覧ページに戻れるよう、新規作成ページにリンクを追加する。
app/views/books/new.html.erb に以下のコードを追加する。

<%= link_to '一覧', books_path %>

これでスムーズに新規作成ページと一覧ページを行き来することができるようになった。
に続く。


この記事が気に入ったらサポートをしてみませんか?