ysk91_engineer
@ysk91_engineer (.S 佑介)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

【Rails】minitestで新規投稿ができない

解決したいこと

Railsでお店情報の投稿アプリを開発しています。
ローカルサーバー上では投稿できるのですが、minitestではvalid?メソッドが通りません。

発生している問題・エラー

問題が発生しているテストコード

class InfoPostTest < ActionDispatch::IntegrationTest

  # fixturesで定義したユーザー
  def setup
    @michael = users(:michael)
  end

  # Green
  test "user valid?" do
    @michael.valid?
  end

  # Red
  test "@info valid?" do
    @info = @michael.infos.build(
      name: "Michael info name",
      url: "michael_info.com",
      address: "michael info address",
      point: "aaa",
      genre_id: 1,
    )
    assert @info.valid? # ここがRed
  end

出ているエラーメッセージ

FAIL["test_@info_valid?", #<Minitest::Reporters::Suite:0x000000012a251c20 @name="InfoPostTest">, 0.5968529999954626]
 test_@info_valid?#InfoPostTest (0.60s)
        Expected false to be truthy.

当アプリの設計

Infoモデルの設計

Infoはお店の情報を表します。
id, name, url, address, point, user_id, genre_id, created_at, updated_at
のカラムを持っています。
User, Genreモデルに紐付いています。

class Info < ApplicationRecord
  belongs_to :user
  belongs_to :genre

  validates :name, {presence: true}
  validates :address, {presence: true}
  validates :url, {presence: true}
  validates :genre_id, {presence: true}
  validates :point, {presence: true, length: {maximum: 140}}
end

UserとGenreのモデル設計

Infoの紐付け元のモデルではhas_many :infosを指定しています。

Userモデル

class User < ApplicationRecord
  has_many :infos, dependent: :destroy
end

Genreモデル

class Genre < ApplicationRecord
  has_many :infos, dependent: :destroy
end

Infosコントローラの設計

infos_controllerのcreateアクションは下記です。

def create
  @info = Info.new(info_params)
  if @info.save
    redirect_to info_path(@info)
  else
    render new_info_path
  end
end

private

  def info_params
    params.require(:info).permit(:name, :url, :address, :point, :genre_id ).merge(user_id: @current_user.id)
  end

ビューファイル

下記投稿画面を使用し、ローカルサーバーで立ち上げた画面上では正常に投稿することができます。

<%= form_with model: @info, local: true do |f| %>
  <%= f.label :name %>
  <%= f.text_field :name, required: true %>
  <%= f.label :url %>
  <%= f.text_field :url, required: true %>
  <%= f.label :address %>
  <%= f.text_field :address, required: true %>
  <%= f.label :genre_id %>
    <%= f.select :genre_id, { "ランチ": 1, "ディナー": 2, "カフェ": 3},
      { include_blank: '選択してください'}, { class: 'form-control' , required: true } %>
  <%= f.label :point %>
  <%= f.text_area :point, required: true %>
  <input type="submit" value="送信">
<% end %>

自分で試したこと

  • @infocreated_at: 2.hours.agoを追加 => 解決せず
  • @infouser_id: @michael.idを追加 => 解決せず
  • buildではなくnewに変更 => 解決せず
  • コンソールにて
$ user = User.first
=> 情報が表示される
$ info = user.infos.build(
$      name: "Michael info name",
$      url: "michael_info.com",
$      address: "michael info address",
$      point: "aaa",
$      genre_id: 1
$    )
=> #<Info:0x000000013988a308
 id: nil,
 name: "Michael info name",
 url: "michael_info.com",
 address: "michael info address",
 point: "aaa",
 user_id: 1,
 genre_id: 1,
 created_at: nil,
 updated_at: nil>
$ info.valid? 
=> true # ここでvalid?に対してtrueが返ってきているのにminitestだと通らないのが謎
$ info.user.name
=> "test" # 正しい値を返している

開発環境

ruby -v
=> ruby 2.6.10p210 (2022-04-12 revision 67958) [arm64-darwin21]

rails -v
=> Rails 5.2.8.1

私の知識レベル

  • ProgateにてRuby, Ruby on Rails5 一周完走済
  • Railsチュートリアル 一周完走済

初めての質問ですので不足している情報もあるかと思いますが、よろしくお願いします。

0

1Answer

デバッグを挟んでみるとどうでしょうか?

  # Red
  test "@info valid?" do
    @info = @michael.infos.build(
      name: "Michael info name",
      url: "michael_info.com",
      address: "michael info address",
      point: "aaa",
      genre_id: 1,
    )
    binding.pry # ここにデバッグを挟む
    assert @info.valid? # ここがRed

この状態で

@info.valid?
@info.errors.full_messages

などでエラーメッセージを取得したらエラーの詳細が分かるので確認してみてください。

あと、余談ですが、、、
RailsチュートリアルかProgateに合わせてRails5で作られているのかと思うのですが、今のタイミングであればRails6(もしくはRails7)で作った方が良いと思います!

1Like

Your answer might help someone💌