-1

ボウリングスコア計算機を書いていて、RSpec テストをセットアップしようとしていますが、何らかの理由でテストが正しく動作しません。

player_controller_spec.rb:

require 'spec_helper'

describe PlayersController do
  let(:player_names) { ["player1",
                        "player2",
                        "player3",
                    "player4"] }

  describe "POST bowl" do
    before(:each) do
      @game = Game.create!
      player_names.each do |name|
        Player.create!(:name => name)
      end
      @game.players = Player.all
      Player.all.each do |player|
        (0..9).each do |number|
          player.frames << Frame.create(:number => number)
        end
      end
    end
    describe "for the player's third bowl" do
      before(:each) do
        @game.players[@game.current_player].frames[9].update_attributes({:number => 9, :first_bowl => "X", :second_bowl => "X", :score => 20})
        @game.update_attributes({:current_player => 0, :current_frame => 9})
      end

      describe "if the bowl is a number score" do
        before(:each) do
          post :bowl, {:score => "5", :id => @game.id}
        end

        it "should update the player's score" do
          @game.players[@game.current_player].frames[@game.current_frame].score.should == 25
        end
      end
    end
  end
end

player_controller.rb

def bowl
    @game = Game.find(params[:id])
    @score = params[:score]

    @current_player = @game.current_player
    @current_frame = @game.current_frame
    @player = @game.players[@current_player]

    @frame = @player.frames[@current_frame]

    if @frame.first_bowl.nil?
      @frame.first_bowl = @score
      if @score == "/"
        raise "Error"
      end
      if @score == "X" && @frame.number == 9
        @frame.bonus = 2
      end
      @frame.score = (/\A[0-9]\z/ === @score ? @score.to_i : 10)
    elsif @frame.second_bowl.nil?
      @frame.second_bowl = @score
      if @frame.score + @score.to_i > 10
        raise "Error"
      end
      if @score == "X"
        if @frame.number != 9 || (@frame.number == 9 && @frame.first_bowl != "X") # can't be a spare has to be number or strike
          raise "Error"
        end
      end
      if @score == "/" && @frame.number == 9
        @frame.bonus = 1
      end
      if /\A[0-9]\z/ === @score
        @frame.score += @score.to_i
      elsif @score == "/"
        @frame.score = 10
      elsif @score == "X"
        @frame.score = 20
      end
    elsif @frame.third_bowl.nil?
      @frame.third_bowl = @score
      if @frame.number != 9
        raise "Error"
      end
      @frame.bonus = nil
      @frame.update_attributes({:score => (/\A[0-9]\z/ === @score ? @frame.score + @score.to_i : @frame.score + 10)})
    else
      raise "Error"
    end
    @frame.save

    if @game.current_frame > 0
      @prev_frame = @player.frames[@frame.number-1]

      if @prev_frame.nil?
        @prev_frame = Frame.create(:number => @game.current_frame-1)
        @player.frames << @prev_frame
        @player.frames = @player.frames.sort_by { |f| f.number }
      end

      update_scores
    end

問題の仕様はplayers_controller_spec.rbであり、テストの開始時に、4人のプレーヤーと各プレーヤーが10フレームの新しいゲームを作成しています。各テストの前に、テストしようとしているものに合うように特定のフレームの値を設定しています。上記のテストは、最後のフレームの 3 番目のボウルでスコア 5 をボウリングすると、スコアが正しく更新されることを確認する例です。しかし、デバッガーではフレーム内でスコアが更新されていることがわかりますが (コントローラーメソッドでデバッグすると)、Rspec テストに戻ると機能しません。25 を期待していますが、ゼロになります。インスタンス変数がスペックとコントローラーの間で転送される方法について、私が見逃しているものはありますか?

4

1 に答える 1

0

したがって、まず「転送」はありません。コントローラーとサンプルは 2 つの完全に独立したオブジェクトであり、それぞれに独自のインスタンス変数があります ( assignsspec ヘルパーを使用して、コントローラー インスタンス変数の値を取得できます)。

それはあなたの問題の根本的な原因ではありません。コントローラーが実行される前であっても、@game関心のあるゲームであるインスタンス変数があります。ただし、activerecord を使用すると、実行するたびにGame.find(同じデータベース行に対応する) 個別の ruby​​ オブジェクトを受け取ります。行がデータベースからロードされると、背後でデータベースに加えられた変更を認識しません。

オブジェクトをリロードできます@game.reload

補足として、この種のものは、そのロジックのほとんどがコントローラーに座っているのではなく、モデルの 1 つにプッシュダウンされている場合に、より簡単に操作できます。

于 2013-05-02T10:53:00.157 に答える