質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.49%

ポーカー役判定アプリで正しい値を入力した時だけundefined method `+' for nil:NilClassが出る理由は?

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 612

score 4

前提・実現したいこと

rails初心者です。
Railsでポーカーの入力した値に対して役を返す判定アプリを作っています。
例えば"S10 S11 S12 S13 S1"と入力すると”ストレートフラッシュ”と返してくれます。
無効な入力をするとメッセージを返すバリデーションは正しく機能するようになりました。
しかし、逆にバリデーションに正しい値を入力すると以下のエラーが発生するようになりました。
"+"に問題があると書いてあるのですが、おかしな箇所が見当たらないため、ご教示いただけませんでしょうか?

発生している問題・エラーメッセージ

エラーメッセージ
NoMethodError in CardsController#check
undefined method `+' for nil:NilClass

validate :validate_card_set

        def validate_card_set
            if @card_set.blank?
                errors[:base] << "5つのカード指定文字を半角スペース区切りで入力してください。(例:'S1 H3 D9 C13 S11')"
            elsif @card_set.match(VALID_REGEX) == nil
                errors[:base] << " #{ @card_set.split.index(@card_set.split.reject{|r|r.match(/\A[SHDC]([1-9]|1[0-3])\z/)}[0])+1}番目のカード指定文字が不正です。(#{@card_set.split.reject{|r|r.match(/\A[SHDC]([1-9]|1[0-3])\z/)}[0]})  半角英字大文字のスート(S,H,D,C)と数字(1〜13)の組み合わせでカードを指定してください。"
            elsif @card_set.split.size > @card_set.split.uniq.size
                errors[:base] << "カードが重複しています。"
            end
        end

該当のソースコード

judge_service.rb

module JudgeService 

    class JudgeCards
        include ActiveModel::Model

        attr_accessor :card_set

        attr_reader :cards, :suits, :numbers, :number_set, :flush, :straight, :hand

        POKER_HANDS = ["ハイカード", "ワンぺア", "ツーペア", "スリー・オブ・ア・カインド", "ストレート", "フラッシュ", "フルハウス", "フォー・オブ・ア・カインド", "ストレートフラッシュ"]
        VALID_REGEX = /\A[SHDC]([1-9]|1[0-3]) [SHDC]([1-9]|1[0-3]) [SHDC]([1-9]|1[0-3]) [SHDC]([1-9]|1[0-3]) [SHDC]([1-9]|1[0-3])\z/

        validate :validate_card_set

        def validate_card_set
            if @card_set.blank?
                errors[:base] << "5つのカード指定文字を半角スペース区切りで入力してください。(例:'S1 H3 D9 C13 S11')"
            elsif @card_set.match(VALID_REGEX) == nil
                errors[:base] << " #{ @card_set.split.index(@card_set.split.reject{|r|r.match(/\A[SHDC]([1-9]|1[0-3])\z/)}[0])+1}番目のカード指定文字が不正です。(#{@card_set.split.reject{|r|r.match(/\A[SHDC]([1-9]|1[0-3])\z/)}[0]})  半角英字大文字のスート(S,H,D,C)と数字(1〜13)の組み合わせでカードを指定してください。"
            elsif @card_set.split.size > @card_set.split.uniq.size
                errors[:base] << "カードが重複しています。"
            end
        end

        def judge_role
            split_card_set
            count_same_number
            flush?
            straight?
            judge_hand
        end

        def split_card_set()
            @cards = @card_set.split(" ")

            @suits = []
            @numbers = []

            @cards.each do |card|
                @suits.push card[0]
                @numbers.push card[1..-1].to_i
            end
        end

        def count_same_number()
            @number_set = @numbers.group_by{|n|n}.map{|k,v|v.size}.sort.reverse
        end

        def straight?()
            steps = @numbers.sort.map{|n| n - @numbers[0]}
            if steps == [0,1,2,3,4] || steps == [0,9,10,11,12]
                @straight = true
            else
                @straight = false
            end
        end

        def flush?()
            suit_set = @suits.uniq.size
            if suit_set == 1
                @flush = true
            else
                @flush = false
            end
        end

        def judge_hand()
            if @straight == true && @flush == true
                @hand = POKER_HANDS[8]
            elsif @straight == false && @flush == true
                @hand = POKER_HANDS[5]
            elsif @straight == true && @flush == false
                @hand = POKER_HANDS[4]
            elsif @number_set == [4,1]
                @hand = POKER_HANDS[7]
            elsif @number_set == [3,2]
                @hand = POKER_HANDS[6]
            elsif @number_set == [3,1,1]
                @hand = POKER_HANDS[3]
            elsif @number_set == [2,2,1]
                @hand = POKER_HANDS[2]
            elsif @number_set == [2,1,1,1]
                @hand = POKER_HANDS[1]
            else
                @hand = POKER_HANDS[0]
            end
        end
    end
end


cards_controller.rb

class CardsController < ApplicationController
    include JudgeService

    def top
        @card = JudgeCards.new
    end

    def check
        @card = JudgeCards.new(card_set: params[:card_set])
        if @card.valid?
            @card.judge_role
            render :result
        else 
            render :error
        end
    end


    def result
    end

    def error 
    end

end


routes.rb

Rails.application.routes.draw do
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  get '/cards', to: 'cards#top'
  post 'cards/check', to: 'cards#check'
  get 'cards/check', to: 'cards#top'
  get 'cards/result', to: 'cards#result'
  get 'cards/error', to: 'cards#error'
end

試したこと

nilということで、どこがnilを返しているのか探しましたがわかりませんでした。
また、再起動等行いましたが、解決しておりません。

このようなバリデーションが機能しているのに正しい入力の時だけerrorが起きる場合どこがおかしいのでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

”undefined method `+' for nil:NilClass”が発生してしまったた原因はnilオブジェクトに対して '+'を用いたからでした。
そのため、要素.to_iとしてnilオブジェクトを0に変換することで解決しました!
nilをintegerに直すと0になるらしいです!

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • トップ
  • Rubyに関する質問
  • ポーカー役判定アプリで正しい値を入力した時だけundefined method `+' for nil:NilClassが出る理由は?