add game and player scaffolds

This commit is contained in:
Jesse C. Fisher 2015-01-25 01:57:49 -08:00
parent ada22b4ab7
commit 0c621d8f89
40 changed files with 500 additions and 3 deletions

View File

@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

View File

@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

View File

@ -0,0 +1,3 @@
// Place all the styles related to the Games controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View File

@ -0,0 +1,66 @@
class GamesController < ApplicationController
before_action :set_game, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
@games = Game.all
respond_with(@games)
end
def show
respond_with(@game)
end
def new
@game = Game.new
respond_with(@game)
end
def edit
end
def create
@game = Game.new(title: game_params[:title])
if game_params[:player_ids]
game_params[:player_ids].each do |user_id|
@game.players.new(user_id: user_id)
end
end
@game.save
respond_with(@game)
end
def update
@game.update(game_params)
respond_with(@game)
end
def destroy
@game.destroy
respond_with(@game)
end
def join
@game = Game.find(params[:game_id])
@game.add_player_from_user(current_user)
flash[:notice] = "Successfully joined game..."
redirect_to(@game)
end
def start
@game = Game.find(params[:game_id])
@status = 'Game Started' if @game.is_startable?
redirect_to(@game)
end
private
def set_game
@game = Game.find(params[:id])
end
def game_params
params.require(:game).permit(:title, player_ids: [])
end
end

View File

@ -0,0 +1,47 @@
class PlayersController < ApplicationController
before_action :set_player, only: [:show, :edit, :update, :destroy]
respond_to :html
def index
@players = Player.all
respond_with(@players)
end
def show
respond_with(@player)
end
def new
@player = Player.new
respond_with(@player)
end
def edit
end
def create
@player = Player.new(player_params)
@player.save
respond_with(@player)
end
def update
@player.update(player_params)
respond_with(@player)
end
def destroy
@player.destroy
respond_with(@player)
end
private
def set_player
@player = Player.find(params[:id])
end
def player_params
params.require(:player).permit(:game_id, :user_id)
end
end

View File

@ -0,0 +1,2 @@
module GamesHelper
end

View File

@ -0,0 +1,2 @@
module PlayersHelper
end

42
app/models/game.rb Normal file
View File

@ -0,0 +1,42 @@
# The game class
class Game < ActiveRecord::Base
has_many :players, :dependent => :destroy
has_many :users, through: :players
accepts_nested_attributes_for :players
validates :title, presence: true
def start
# Save the game to the database
save
# Start the game TODO
end
def validate_startable
@player_count = players.size
errors[:notice] = 'Must be at least 2 players.' if @player_count < 2
errors[:players] = 'Must be less than 5 players.' if @player_count > 4
end
def is_startable?
@player_count = players.size
@player_count.between?(2, 4)
end
def add_player_from_user(user)
if can_accomodate(user)
Player.create(user: user, game: self)
end
end
def can_accomodate(user)
!(already_has?(user) || full?)
end
def already_has?(user)
users.include?(user)
end
def full?
players.size >= 4
end
end

10
app/models/player.rb Normal file
View File

@ -0,0 +1,10 @@
# Associates users to games
class Player < ActiveRecord::Base
belongs_to :game
belongs_to :user
has_many :player_cards
validates_presence_of :user_id
validates_presence_of :game_id
end

View File

@ -0,0 +1,4 @@
class PlayerCard < ActiveRecord::Base
belongs_to :player
belongs_to :card
end

View File

@ -0,0 +1,9 @@
= simple_form_for(@game) do |f|
= f.error_notification
.form-inputs
= f.input :title
= f.association :players, as: :select, collection: User.all.map {|u| u.id}, include_blank: false, include_hidden: false
.form-actions
= f.button :submit

View File

@ -0,0 +1,7 @@
%h1 Editing game
= render 'form'
= link_to 'Show', @game
\|
= link_to 'Back', games_path

View File

@ -0,0 +1,21 @@
%h1 Listing games
%table
%thead
%tr
%th Title
%th
%th
%th
%tbody
- @games.each do |game|
%tr
%td= game.title
%td= link_to 'Show', game
%td= link_to 'Edit', edit_game_path(game)
%td= link_to 'Destroy', game, :method => :delete, :data => { :confirm => 'Are you sure?' }
%br
= link_to 'New Game', new_game_path

View File

@ -0,0 +1,4 @@
json.array!(@games) do |game|
json.extract! game, :id, :title
json.url game_url(game, format: :json)
end

View File

@ -0,0 +1,5 @@
%h1 New game
= render 'form'
= link_to 'Back', games_path

View File

@ -0,0 +1,23 @@
%p
%b Status:
= @status
%p
%b Title:
= @game.title
- if @game.can_accomodate(current_user)
= link_to 'Join', game_join_path(@game)
- if @game.is_startable? && @game.already_has?(current_user)
= link_to 'Start', game_start_path(@game)
%p
%b Players:
%ol
- @game.players.each do |player|
%li= player
= link_to 'Edit', edit_game_path(@game)
\|
= link_to 'Back', games_path

View File

@ -0,0 +1 @@
json.extract! @game, :id, :title, :created_at, :updated_at

View File

@ -1,4 +1,5 @@
<%# add navigation links to this file %> <li><%= link_to 'Home', root_path %></li>
<li><%= link_to 'Quick Play', quick_play_path %></li>
<% if user_signed_in? %> <% if user_signed_in? %>
<li><%= link_to 'Edit account', edit_user_registration_path %></li> <li><%= link_to 'Edit account', edit_user_registration_path %></li>
<li><%= link_to 'Sign out', destroy_user_session_path, :method=>'delete' %></li> <li><%= link_to 'Sign out', destroy_user_session_path, :method=>'delete' %></li>

View File

@ -0,0 +1,9 @@
= simple_form_for(@player) do |f|
= f.error_notification
.form-inputs
= f.association :game
= f.association :user
.form-actions
= f.button :submit

View File

@ -0,0 +1,7 @@
%h1 Editing player
= render 'form'
= link_to 'Show', @player
\|
= link_to 'Back', players_path

View File

@ -0,0 +1,23 @@
%h1 Listing players
%table
%thead
%tr
%th Game
%th User
%th
%th
%th
%tbody
- @players.each do |player|
%tr
%td= player.game
%td= player.user
%td= link_to 'Show', player
%td= link_to 'Edit', edit_player_path(player)
%td= link_to 'Destroy', player, :method => :delete, :data => { :confirm => 'Are you sure?' }
%br
= link_to 'New Player', new_player_path

View File

@ -0,0 +1,4 @@
json.array!(@players) do |player|
json.extract! player, :id, :game_id, :user_id
json.url player_url(player, format: :json)
end

View File

@ -0,0 +1,5 @@
%h1 New player
= render 'form'
= link_to 'Back', players_path

View File

@ -0,0 +1,12 @@
%p#notice= notice
%p
%b Game:
= @player.game
%p
%b User:
= @player.user
= link_to 'Edit', edit_player_path(@player)
\|
= link_to 'Back', players_path

View File

@ -0,0 +1 @@
json.extract! @player, :id, :game_id, :user_id, :created_at, :updated_at

View File

@ -0,0 +1 @@
%h1 Joining a game

View File

@ -1,6 +1,14 @@
Rails.application.routes.draw do Rails.application.routes.draw do
resources :players
resources :games do
get 'start'
get 'join'
end
mount Upmin::Engine => '/admin' mount Upmin::Engine => '/admin'
root to: 'visitors#index' root to: 'visitors#index'
get '/quick-play', to: 'visitors#quick-play'
devise_for :users devise_for :users
resources :users resources :users
end end

View File

@ -0,0 +1,9 @@
class CreateGames < ActiveRecord::Migration
def change
create_table :games do |t|
t.string :title
t.timestamps
end
end
end

View File

@ -0,0 +1,10 @@
class CreatePlayers < ActiveRecord::Migration
def change
create_table :players do |t|
t.references :game, index: true
t.references :user, index: true
t.timestamps
end
end
end

View File

@ -0,0 +1,10 @@
class CreatePlayerCards < ActiveRecord::Migration
def change
create_table :player_cards do |t|
t.references :player, index: true
t.references :card, index: true
t.timestamps
end
end
end

View File

@ -11,11 +11,37 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150102000743) do ActiveRecord::Schema.define(version: 20150104203850) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
create_table "games", force: true do |t|
t.string "title"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "player_cards", force: true do |t|
t.integer "player_id"
t.integer "card_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "player_cards", ["card_id"], name: "index_player_cards_on_card_id", using: :btree
add_index "player_cards", ["player_id"], name: "index_player_cards_on_player_id", using: :btree
create_table "players", force: true do |t|
t.integer "game_id"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "players", ["game_id"], name: "index_players_on_game_id", using: :btree
add_index "players", ["user_id"], name: "index_players_on_user_id", using: :btree
create_table "users", force: true do |t| create_table "users", force: true do |t|
t.string "email", default: "", null: false t.string "email", default: "", null: false
t.string "encrypted_password", default: "" t.string "encrypted_password", default: ""

6
spec/factories/games.rb Normal file
View File

@ -0,0 +1,6 @@
FactoryGirl.define do
factory :game do
title "MyString"
end
end

View File

@ -0,0 +1,7 @@
FactoryGirl.define do
factory :player_card do
player nil
card nil
end
end

View File

@ -0,0 +1,7 @@
FactoryGirl.define do
factory :player do
game nil
user nil
end
end

View File

@ -2,7 +2,7 @@ FactoryGirl.define do
factory :user do factory :user do
confirmed_at Time.now confirmed_at Time.now
name "Test User" name "Test User"
email "test@example.com" sequence(:email) { |n| "test#{n}@example.com" }
password "please123" password "please123"
trait :admin do trait :admin do

View File

@ -0,0 +1,23 @@
include Warden::Test::Helpers
Warden.test_mode!
# Feature: Quick play
# As a user
# I want to play a quick game
# So I can have fun as fast as possible
feature 'Quick play', :devise do
# Scenario: User can join a game using the quick play link
# Given I am signed in
# When I click the Quick Play link
# Then I join a game
scenario 'user can join a quick play game' do
pending("#EXPECT USER TO JOIN FIRST OPEN QUICK PLAY GAME")
user = FactoryGirl.create(:user)
signin(user.email, user.password)
click_link 'Quick Play'
#EXPECT VISITOR TO JOIN FIRST OPEN QUICK PLAY TABLE
expect(fail)
end
end

View File

@ -0,0 +1,19 @@
# Feature: Quick play
# As a visitor
# I want to play a game
# So I can have fun without signing up
feature 'Quick play', :devise do
# Scenario: Visitor can join a game using the quick play link
# Given I am not signed in
# When I click the Quick Play link
# Then I join a game
scenario 'visitor can join a quick play game' do
pending("#EXPECT VISITOR TO JOIN FIRST OPEN QUICK PLAY GAME")
visit root_path
click_link 'Quick Play'
#EXPECT VISITOR TO JOIN FIRST OPEN QUICK PLAY TABLE
expect(fail)
end
end

47
spec/models/game_spec.rb Normal file
View File

@ -0,0 +1,47 @@
require 'rails_helper'
RSpec.describe Game, type: :model do
before(:each) { @game = Game.new(title: 'Test Game') }
subject { @game }
it { should respond_to(:title) }
it '#title returns a string' do
expect(@game.title).to match 'Test Game'
end
describe 'validations' do
describe 'player_count' do
context 'when there are between 2 and 4 players' do
it 'is valid' do
@game.players.new
@game.players.new
expect(@game).to be_valid
end
end
context 'when there are less than 2 players' do
it 'fails validation with too few players' do
expect(@game).to_not be_valid
expect(@game.errors[:players])
.to include 'Must be at least 2 players.'
end
end
context 'when there are more than 4 players' do
it 'fails validation with too many players' do
5.times do
@game.players.new
end
expect(@game).to_not be_valid
expect(@game.errors[:players])
.to include 'Must be less than 5 players.'
end
end
end
end
it 'Can not be started if game is invalid' do
expect(@game.start).to eq false
end
end

View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe PlayerCard, :type => :model do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe Player, :type => :model do
pending "add some examples to (or delete) #{__FILE__}"
end