- Simple Game Server
A simple game server built with Ruby on Rails, designed to handle multiplayer game sessions. This server provides a flexible API for managing game sessions, players, and game state, while remaining agnostic to the specific game logic.
- Player authentication and management
- Game session creation and management
- Flexible game state storage with JSON schema validation
- Turn-based game support
- Example Tic Tac Toe implementation
- Decoupled User and Player models (Player created via separate API endpoint)
- UUID-based identifiers for Player and Token models
- Role-based access (admin vs player)
- JSON API with consistent error handling
- Fully RESTful API for managing game resources (sessions, players, turns)
- Custom member routes for domain-specific actions (
start,join,leave) with semantic HTTP verbs
The server supports configurable game types through the Game model. Each game type defines:
- Minimum and maximum players
- Game state schema for validation
- Game-specific rules and logic
To create the first admin user, make a POST request to /api/admin/users with a username and password. This only works when no users exist.
- Start the Rails console:
rails console- Create a new game with its configuration:
# Create the game with state schema
game = Game.create!(
name: "YourGameName",
description: "Description of your game",
min_players: 2,
max_players: 4,
state_schema: {
type: "object",
properties: {
board: {
type: "array",
items: {
type: "integer"
}
},
scores: {
type: "object",
additionalProperties: {
type: "integer"
}
},
current_player: {
type: "integer"
},
game_status: {
type: "string"
}
}
}
)The state schema uses JSON Schema format and supports the following types:
array: For lists like game boards or move historyobject: For key-value pairs like scores or player datainteger: For numeric values like player indices or scoresstring: For text values like game status or messagesboolean: For true/false values
game = Game.create!(
name: "Tic Tac Toe",
description: "A classic game of X's and O's",
min_players: 2,
max_players: 2,
state_schema: {
type: "object",
properties: {
board: {
type: "array",
items: {
type: "integer"
},
minItems: 9,
maxItems: 9
}
}
}
)- Ruby 3.2.2
- Rails 7.1.3
- PostgreSQL 15
- Node.js (for asset compilation)
- Yarn (for JavaScript dependencies)
- Clone the repository:
git clone https://github.com/yourusername/simple_game_server.git
cd simple_game_server- Install Ruby dependencies:
bundle install- Install JavaScript dependencies:
yarn install- Set up the database:
rails db:create db:migrate- Configure environment variables:
cp .env.example .envEdit .env with your configuration (database credentials, JWT secret, etc.)
Start the Rails server:
rails serverThe server will be available at http://localhost:3000
The server uses JWT-based authentication for API requests. CSRF protection is disabled by default for API usage since token-based authentication is used instead of session-based authentication.
By default, CSRF (Cross-Site Request Forgery) protection is disabled for API requests. This is because the API uses token-based authentication (JWT) instead of session-based authentication, which is the typical use case for CSRF protection.
You can control CSRF protection through the ENABLE_CSRF_PROTECTION environment variable:
# Enable CSRF protection
ENABLE_CSRF_PROTECTION=true rails server
# Disable CSRF protection (default)
ENABLE_CSRF_PROTECTION=false rails serverNote for Local Development and Testing:
- CSRF protection is disabled by default to simplify local development and testing
- When deploying to production, consider enabling CSRF protection if your API will be accessed from web browsers
- For API-only applications accessed by mobile apps or other services, CSRF protection is typically not needed
The server adheres to REST principles for clarity and consistency. Resources are exposed via standard HTTP methods:
GET /api/games: List available gamesGET /api/games/:id: Get game detailsPOST /api/games/:game_id/sessions: Create a new game sessionGET /api/games/:game_id/sessions/:id: Show a specific sessionPUT /api/games/:game_id/sessions/:id: Update a session's statePOST /api/games/:game_id/sessions/:id/start: Start the sessionPOST /api/games/:game_id/sessions/:id/join: Join the session as a playerDELETE /api/games/:game_id/sessions/:id/leave: Leave the session
These member routes allow domain-specific state transitions (e.g., starting or joining a session) while maintaining a RESTful structure.
spec/ # Main test directory
├── spec_helper.rb # Core RSpec configuration
├── rails_helper.rb # Rails-specific test setup
├── controllers/ # Controller tests
│ └── api/ # API controller tests
│ ├── tokens_controller_spec.rb # Authentication tests
│ ├── users_controller_spec.rb # User management tests
│ ├── players_controller_spec.rb # Player management tests
│ ├── games_controller_spec.rb # Game management tests
│ └── game_sessions_controller_spec.rb # Game session tests
├── models/ # Model tests
├── factories/ # Factory definitions
│ ├── users.rb # User factory
│ ├── games.rb # Game factory
│ ├── game_sessions.rb # Game session factory
│ ├── players.rb # Player factory
│ └── tokens.rb # Token factory
└── support/ # Test support files
├── controller_macros.rb # Controller authentication helpers
├── authentication_helper.rb # Authentication utilities
├── database_cleaner.rb # Database cleaning configuration
├── factory_bot.rb # FactoryBot setup
├── helpers/ # Test helper modules
│ ├── authentication_helper.rb # Authentication test helpers
│ └── json_helper.rb # JSON response helpers
└── shared_contexts/ # Shared test contexts
-
Configuration Files:
spec_helper.rb: Core RSpec configurationrails_helper.rb: Rails-specific test setup.rspec: RSpec command-line options.rubocop.yml: Code style configuration
-
Controller Tests:
tokens_controller_spec.rb: Tests for authentication endpointsusers_controller_spec.rb: Tests for user managementplayers_controller_spec.rb: Tests for player managementgames_controller_spec.rb: Tests for game managementgame_sessions_controller_spec.rb: Tests for game session management
-
Support Files:
controller_macros.rb: Authentication helpers for controller testsauthentication_helper.rb: JWT token management utilitiesdatabase_cleaner.rb: Database cleaning configurationfactory_bot.rb: FactoryBot setup and configuration
-
Helper Modules:
authentication_helper.rb: Authentication test utilitiesjson_helper.rb: JSON response parsing helpers
-
Factories:
users.rb: User model factorygames.rb: Game model factorygame_sessions.rb: Game session factoryplayers.rb: Player model factorytokens.rb: Token model factory
Our test suite is built on RSpec and follows a comprehensive testing strategy:
-
Framework & Tools:
- RSpec for test framework
- FactoryBot for test data generation
- Database Cleaner for test database management
- Custom authentication helpers for API testing
-
Configuration:
spec_helper.rb: Core RSpec configuration- Custom matcher descriptions enabled
- Partial double verification enabled
- Shared context metadata behavior configured
rails_helper.rb: Rails-specific configuration- Transactional fixtures enabled
- Automatic spec type inference
- FactoryBot integration
- Support file autoloading
-
Test Organization:
- Models: Unit tests for ActiveRecord models
- Controllers: API endpoint testing
- Factories: Test data definitions
- Support: Shared test utilities and helpers
-
Custom Test Infrastructure:
ControllerMacros: Authentication helpers for controller testsAuthenticationHelper: JWT token management for API testsJSONHelper: Response parsing utilitiesDatabaseCleaner: Ensures clean test state
-
UUID Usage:
- Player and Token records use UUIDs as identifiers
- Player must be explicitly created for a user before they can join or create game sessions
- Specs rely on
create_user_with_player!helper to set up users with associated players
-
CI Integration:
- GitHub Actions workflow
- PostgreSQL test database
- Automated schema loading
- Security scanning (Brakeman, importmap audit)
-
Running Tests:
- Local development:
bundle exec rspec - CI environment:
script/test_ci- Matches GitHub Actions environment
- Uses fresh database for each run
- Cleans up after tests
- Supports all RSpec options
- Local development:
The test suite emphasizes:
- API authentication and authorization
- Data integrity and validation
- Clean test isolation
- Comprehensive coverage of business logic
- Automated security checks
The repository includes a Tic Tac Toe example implementation in the /examples/tic_tac_toe directory. This example demonstrates:
- Game session management
- Turn-based gameplay
- State management with JSON schema validation
- Client-server communication
- Error handling and game state validation
See the Tic Tac Toe README for implementation details.
This project has been developed with the assistance of generative AI to accelerate development and ensure best practices. AI has been used to:
- Configure RuboCop for code style enforcement
- Set up GitHub Actions for CI/CD
- Configure branch protection rules
- Generate initial project structure
- Design and implement RESTful API endpoints
- Create database migrations and models
- Implement authentication and authorization
- Write comprehensive test suites
- Generate API documentation
- Design the Tic Tac Toe game client
- Implement game logic and state management
- Create test cases for game functionality
- Generate client-side documentation
The AI assistance has helped maintain consistent code quality, follow Rails best practices, and ensure comprehensive test coverage while allowing for rapid development and iteration.
# Start server in development mode
rails server
# or
bin/rails server
# Start server with debug logging
RAILS_LOG_LEVEL=debug bin/rails server
# Start server on specific port
rails server -p 3001
# Start server in production mode
RAILS_ENV=production rails server# Create database
rails db:create
# Run migrations
rails db:migrate
# Rollback last migration
rails db:rollback
# Reset database (drop, create, migrate)
rails db:reset
# Seed database
rails db:seed
# View database schema
rails db:schema:dump
# Rebuild database with UUIDs
rails db:drop db:create db:migrate# Run all tests
bundle exec rspec
# Run specific test file
bundle exec rspec spec/models/game_session_spec.rb
# Run specific test method
bundle exec rspec spec/models/game_session_spec.rb:123
# Run tests with coverage
COVERAGE=true bundle exec rspec# Run RuboCop
bundle exec rubocop
# Run RuboCop with auto-correct
bundle exec rubocop -a
# Run RuboCop with auto-correct and unsafe changes
bundle exec rubocop -A
# Check specific file
bundle exec rubocop app/models/game_session.rb# Start Rails console
rails console
# Start Rails console in sandbox mode (rollback changes)
rails console --sandbox
# Generate new migration
rails generate migration AddColumnToTable
# Generate new model
rails generate model ModelName
# Generate new controller
rails generate controller ControllerNameThis project is currently in its early stages as a learning exercise and to support multiplayer functionality in some mobile games. While the focus is on personal development, I'm open to:
- Feedback and suggestions
- Questions about implementation
- Potential contributions that align with the project's goals
If you're interested in contributing, please:
- Fork the repository
- Create a feature branch
- Submit a pull request with a clear description of your changes
Note: This project uses UUIDs for certain tables. If modifying schema, ensure proper UUID handling.
- Improve game session cleanup/removal
- Enhanced handling of joining/leaving/rejoining games
- Better error handling and validation
- Documentation improvements
- Real-time updates using WebSockets
- Push notifications for game events
- Enhanced player presence tracking
- Game session persistence and recovery
- Support for different game types
- Game analytics and statistics
- Player management dashboard
- Custom game type configuration
This project is licensed under the MIT License - see the LICENSE file for details.