Skip to content
This repository was archived by the owner on Jan 9, 2024. It is now read-only.

Commit 124ee7d

Browse files
committed
Refactor player enliting
1 parent 3278672 commit 124ee7d

File tree

6 files changed

+94
-43
lines changed

6 files changed

+94
-43
lines changed
Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
class GamesController < ApplicationController
2-
before_action :set_game, only: [:show]
3-
before_action :join_game, only: [:show], unless: :player_in_game?
2+
before_action :set_game, only: [:show]
43

54
def show
65
@opponent ||= @game.players.where.not(id: current_player&.id).first || NilPlayer.new
7-
return render FinishedGame.template_path if @game.state == 'finished'
6+
render game_template || :show
87
end
98

109
def create
@@ -14,14 +13,20 @@ def create
1413

1514
private
1615

17-
def join_game
18-
return if @game.state == 'finished'
19-
enlist = Players::Enlist.new(game: @game, player: current_player)
16+
def game_params
17+
params.require(:game).permit(:name)
18+
end
2019

21-
if enlist.game_full?
22-
return render FullGame.template_path
23-
else
24-
return render AwaitingOpponentGame.template_path
20+
def game_template
21+
case @game.state
22+
when 'awaiting_opponent'
23+
return if player_in_game?
24+
AwaitingOpponentGame.template_path
25+
when 'running'
26+
return if player_in_game?
27+
FullGame.template_path
28+
when 'finished'
29+
FinishedGame.template_path
2530
end
2631
end
2732

@@ -33,8 +38,4 @@ def set_game
3338
@game = Game.find_by(slug: params[:id].parameterize)
3439
redirect_to root_path unless @game
3540
end
36-
37-
def game_params
38-
params.require(:game).permit(:name)
39-
end
4041
end

app/controllers/opponent_controller.rb

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,22 @@ class OpponentController < ApplicationController
22
before_action :set_game, only: [:create]
33

44
def create
5-
enlist = Players::Enlist.new(game: @game, player: current_player)
6-
return redirect_to game_path(@game) if enlist.game_full?
7-
8-
payload = enlist.assign_game_to_player!
9-
set_current_player(enlist.player)
10-
ActionCable.server.broadcast "game_#{current_player.game_id}", payload
5+
@enlist = Players::Enlist.new(game: @game, player: current_player)
6+
enlist_player if @enlist.available?
117

128
redirect_to game_path(@game)
139
end
1410

1511
private
1612

13+
def enlist_player
14+
payload = @enlist.assign_game_to_player!
15+
set_current_player(@enlist.player)
16+
ActionCable.server.broadcast "game_#{current_player.game_id}", payload
17+
end
18+
1719
def set_game
1820
@game = Game.find_by(slug: params[:game_id].parameterize)
19-
return redirect_to root_path unless @game
20-
return redirect_to game_path(@game) if @game.state != 'awaiting_opponent'
21+
return redirect_to root_path unless @game
2122
end
2223
end

app/dispatches/players/enlist.rb

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
module Players
22
class Enlist
3-
MAX_PLAYERS = 2
4-
53
private
64
attr_reader :game
75

@@ -15,13 +13,13 @@ def initialize(game:, player:)
1513

1614
def assign_game_to_player!
1715
@player = Player.create!(nickname: nickname, game: game, life: Player::LIFE)
18-
@game.update(state: 'running')
16+
game.update(state: 'running')
1917

2018
return successful_payload
2119
end
2220

23-
def game_full?
24-
game.players.count >= MAX_PLAYERS
21+
def available?
22+
game.state == 'awaiting_opponent' && !game.full?
2523
end
2624

2725
private

app/models/game.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,18 @@
33
# - running: the game is started
44
# - finished: game over. A player has destroyed his ennemy mothership
55
class Game < ApplicationRecord
6+
MAX_PLAYERS = 2
7+
8+
has_one :loser, -> { where(won: false ) }, class_name: 'Player'
9+
has_one :winner, -> { where(won: true ) }, class_name: 'Player'
10+
611
has_many :players, dependent: :destroy
712
has_many :ships, through: :players
813
has_many :words, dependent: :destroy
914

10-
has_one :loser, -> { where(won: false ) }, class_name: 'Player'
11-
has_one :winner, -> { where(won: true ) }, class_name: 'Player'
15+
def full?
16+
players.count >= MAX_PLAYERS
17+
end
1218

1319
def to_param
1420
slug

spec/models/game_spec.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,40 @@
55

66
it { is_expected.to have_one(:loser).class_name(Player).conditions(won: false) }
77
it { is_expected.to have_one(:winner).class_name(Player).conditions(won: true) }
8+
9+
it { is_expected.to have_many(:players) }
10+
it { is_expected.to have_many(:ships) }
11+
it { is_expected.to have_many(:words) }
12+
13+
describe '#full?' do
14+
before :each do
15+
game.save!
16+
end
17+
18+
context 'when there is no player' do
19+
it 'returns false' do
20+
expect(game.full?).to eq(false)
21+
end
22+
end
23+
24+
context 'when there is one player' do
25+
before :each do
26+
game.players.create!
27+
end
28+
29+
it 'returns false' do
30+
expect(game.full?).to eq(false)
31+
end
32+
end
33+
34+
context 'when there are two players' do
35+
before :each do
36+
2.times { game.players.create! }
37+
end
38+
39+
it 'returns true' do
40+
expect(game.full?).to eq(true)
41+
end
42+
end
43+
end
844
end

spec/requests/games_spec.rb

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,40 @@
44
let(:game) { Game.create!(name: 'Starship Battle', slug: 'starship-battle') }
55

66
describe "GET show" do
7-
context "url is not parameterized" do
8-
before :each do
9-
get URI::encode("/games/#{game.name}")
10-
end
11-
12-
it { expect(Game.count).to eq(1) }
13-
end
14-
157
context "player is signed in" do
168
let(:player) { Player.create! }
179

1810
before :each do
1911
allow_any_instance_of(ApplicationController).to receive(:current_player).and_return(player)
2012
end
2113

14+
context "url is not parameterized" do
15+
before :each do
16+
game.update(state: 'awaiting_opponent')
17+
allow_any_instance_of(ApplicationController).to receive(:current_player).and_return(player)
18+
get URI::encode("/games/#{game.name}")
19+
end
20+
21+
it { expect(Game.count).to eq(1) }
22+
end
23+
2224
context "game is full" do
23-
before { 2.times { Player.create(game: game) } }
25+
before :each do
26+
game.update(state: 'running')
27+
2.times { Player.create(game: game) }
28+
get "/games/#{game.to_param}"
29+
end
2430

25-
before { get "/games/#{game.to_param}" }
2631

2732
it { expect(response.body).to include("already full") }
2833
it { expect(player.reload.game).to_not eq(game) }
2934
end
3035

31-
context "player joined the game and refresh the page" do
36+
context "player joined the game and refresh the page" do
3237
let!(:opponent) { Player.create(game: game) }
3338

3439
before :each do
40+
game.update(state: 'running')
3541
player.update(game: game)
3642

3743
get "/games/#{game.to_param}"
@@ -45,6 +51,7 @@
4551
let(:other_game) { Game.create!(name: 'Other game', slug: 'other-game') }
4652

4753
before :each do
54+
other_game.update(state: 'awaiting_opponent')
4855
player.update(game: game, nickname: "Rico", life: 3)
4956
get "/games/#{other_game.to_param}"
5057
end
@@ -84,9 +91,11 @@
8491
end
8592

8693
context "game is already full" do
87-
before { 2.times { Player.create!(game: game) } }
88-
89-
before { get "/games/#{game.to_param}" }
94+
before :each do
95+
game.update(state: 'running')
96+
2.times { Player.create!(game: game) }
97+
get "/games/#{game.to_param}"
98+
end
9099

91100
it { expect(response).to have_http_status(200) }
92101
it { expect(Player.count).to eq(2) }

0 commit comments

Comments
 (0)