๐บ BrewQuest AI - Backend API
Rails 7.1 API backend for the BrewQuest AI beer discovery platform, providing RESTful endpoints for AI-powered recommendations, chat, ratings, and community features.
๐ฏ Overview
The BrewQuest AI backend is a robust Rails API that powers the beer discovery platform. It handles user authentication, beer data management, AI-powered recommendations, real-time chat, community forums, and gamification features. The API is designed to support the Next.js frontend while being flexible enough for future mobile applications.
โจ Features
๐ง AI Integration
- BrewMatch AI: Personalized beer recommendation engine
- BrewChat AI: Intelligent chatbot with beer knowledge
- Flavor Analysis: Taste profile generation from user ratings
- OpenAI Integration: Ready for production AI features (mock implementation for demo)
๐๏ธ Data Management
- Beer Database: 15+ craft beers with detailed profiles
- User Ratings: Rating system with notes and timestamps
- Recommendations: AI-generated beer suggestions with scoring
- Chat History: Conversation storage with encrypted messages
- Forum System: Community discussions with categories
๐ป๐ณ Vietnamese Content
- Local craft breweries (Pasteur Street, Heart of Darkness, Furbrew)
- Vietnamese beer styles and cultural context
- Food pairing suggestions for Vietnamese cuisine
- Localized responses in both Vietnamese and English
๐ฎ Gamification
- Points system for user activities
- Achievement badges based on behavior
- Progress tracking and statistics
- Leaderboard capabilities
๐ Security & Performance
- JWT-based authentication (Devise + JWT)
- CORS configured for frontend integration
- Redis for caching and background jobs
- PostgreSQL for robust data storage
- Rate limiting and input validation
๐ Tech Stack
- Framework: Ruby on Rails 7.1 (API-only mode)
- Ruby Version: 3.3.1
- Database: PostgreSQL 13+
- Cache/Queue: Redis 6+
- Authentication: Devise + JWT
- Background Jobs: Sidekiq
- AI Integration: OpenAI API (ruby-openai gem)
- File Storage: AWS S3 (with Active Storage)
- HTTP Client: HTTParty for external APIs
- Testing: RSpec + FactoryBot
๐ Prerequisites
- Ruby 3.3.1
- PostgreSQL 13+
- Redis 6+
- Bundler
- (Optional) OpenAI API key for production AI features
๐ Quick Start
1. Installation
# Install dependencies
bundle install
2. Environment Configuration
Create a .env file in the root directory:
# Database
DATABASE_URL=postgresql://localhost/brewquest_development
# Rails
RAILS_ENV=development
SECRET_KEY_BASE=your_secret_key_here
# Redis
REDIS_URL=redis://localhost:6379/0
# Frontend CORS
FRONTEND_URL=http://localhost:3000
# AI Integration (Optional - for production)
# OPENAI_API_KEY=your_openai_api_key_here
# AWS S3 (Optional - for file uploads)
# AWS_ACCESS_KEY_ID=your_aws_access_key
# AWS_SECRET_ACCESS_KEY=your_aws_secret_key
# AWS_REGION=us-east-1
# AWS_BUCKET=brewquest-ai
Copy the example environment file:
cp .env.example .env
3. Database Setup
# Create database
rails db:create
# Run migrations
rails db:migrate
# Seed with sample data (15 beers, test user, ratings, etc.)
rails db:seed
The seed file creates:
- Test user:
test@brewquest.ai/password123 - 15 craft beers (Vietnamese and international)
- 7 sample ratings
- 15 AI recommendations
- 2 chat messages
- Sample forum posts
4. Start the Server
# Start Rails server
rails server -p 3001
# Or with Puma directly
bundle exec puma -p 3001
# Start Sidekiq (in another terminal)
bundle exec sidekiq
The API will be available at http://localhost:3001
๐ Project Structure
backend/
โโโ app/
โ โโโ controllers/
โ โ โโโ api/
โ โ โโโ v1/ # API v1 endpoints
โ โ โโโ beers_controller.rb
โ โ โโโ ratings_controller.rb
โ โ โโโ recommendations_controller.rb
โ โ โโโ chat_messages_controller.rb
โ โ โโโ forum_posts_controller.rb
โ โ โโโ dashboard_controller.rb
โ โ โโโ notifications_controller.rb
โ โโโ models/ # ActiveRecord models
โ โ โโโ user.rb
โ โ โโโ beer.rb
โ โ โโโ rating.rb
โ โ โโโ recommendation.rb
โ โ โโโ chat_message.rb
โ โ โโโ forum_post.rb
โ โโโ services/ # Business logic
โ โ โโโ ai/
โ โ โ โโโ recommendation_service.rb
โ โ โ โโโ chat_service.rb
โ โ โ โโโ flavor_analyzer.rb
โ โ โโโ gamification/
โ โ โโโ points_service.rb
โ โโโ serializers/ # JSON serializers
โ โโโ beer_serializer.rb
โ โโโ rating_serializer.rb
โ โโโ ...
โโโ config/
โ โโโ database.yml # Database configuration
โ โโโ routes.rb # API routes
โ โโโ initializers/
โ โ โโโ cors.rb # CORS configuration
โ โ โโโ redis.rb # Redis configuration
โ โโโ environments/
โโโ db/
โ โโโ migrate/ # Database migrations
โ โโโ seeds.rb # Seed data
โ โโโ schema.rb # Database schema
โโโ spec/ # RSpec tests
โ โโโ models/
โ โโโ controllers/
โ โโโ services/
โโโ Gemfile # Ruby dependencies
โโโ .env # Environment variables
๐ API Endpoints
Base URL
http://localhost:3001/api/v1
Authentication
Currently disabled for demo purposes. To enable JWT authentication, uncomment the authentication code in controllers.
Endpoints Overview
Dashboard
GET /dashboard
Returns user statistics, recent activities, and achievement progress.
Response:
{
"data": {
"stats": {
"total_ratings": 7,
"total_recommendations": 15,
"total_chat_queries": 2,
"points": 595
},
"recent_activities": [...],
"achievements": [...]
}
}
Beers
GET /beers # List all beers
GET /beers/:id # Get beer details
GET /beers/search # Search beers
Query Parameters:
style: Filter by beer style (e.g., IPA, Stout)country: Filter by countrybrewery: Filter by brewery name
Response:
{
"data": {
"beers": [
{
"id": 1,
"name": "Pasteur Street Jasmine IPA",
"style": "IPA",
"abv": 6.5,
"brewery": "Pasteur Street Brewing",
"country": "Vietnam",
"description": "...",
"flavor_notes": ["floral", "hoppy", "jasmine"],
"average_rating": 4.5
}
]
}
}
Ratings
GET /ratings # List user's ratings
POST /ratings # Create a rating
GET /ratings/:id # Get rating details
PUT /ratings/:id # Update rating
DELETE /ratings/:id # Delete rating
Create Rating:
POST /ratings
{
"beer_id": 1,
"rating": {
"rating": 5,
"notes": "Excellent IPA with jasmine notes!"
}
}
Awards 5 points to the user.
Recommendations
GET /recommendations # Get user's recommendations
POST /recommendations # Generate new recommendations
Generate Recommendations:
POST /recommendations
{}
Generates 5 new personalized recommendations based on user's taste profile. Awards 25 points.
Response:
{
"data": {
"recommendations": [
{
"id": 1,
"beer": {...},
"match_score": 95,
"reason": "Based on your love for hoppy beers",
"created_at": "2025-01-15T10:00:00Z"
}
]
}
}
Chat (BrewChat AI)
GET /chat_messages # Get chat history
POST /chat_messages # Send a message
Send Message:
POST /chat_messages
{
"message": "What's the best Vietnamese IPA?"
}
Awards 10 points per query.
Response:
{
"data": {
"message": {
"id": 1,
"content": "What's the best Vietnamese IPA?",
"response": "Based on your taste profile, I recommend...",
"created_at": "2025-01-15T10:00:00Z"
}
}
}
Forum
GET /forum_posts # List forum posts
GET /forum_posts/:id # Get post with replies
POST /forum_posts # Create a post
PUT /forum_posts/:id # Update post
DELETE /forum_posts/:id # Delete post
POST /forum_posts/:id/like # Like a post
POST /forum_posts/:id/reply # Reply to post
Query Parameters:
category: Filter by categorysearch: Search in post content
Create Post:
POST /forum_posts
{
"forum_post": {
"title": "Best Vietnamese IPAs?",
"content": "Looking for recommendations...",
"category": "vietnamese_craft_beers"
}
}
Awards 10 points per post.
Notifications
GET /notifications # Get user notifications
GET /notifications/preferences # Get notification settings
PUT /notifications/preferences # Update preferences
POST /notifications/:id/read # Mark as read
๐๏ธ Database Schema
Key Models
Users
- Authentication credentials
- Taste preferences
- Points and achievements
- Activity tracking
Beers
- Name, style, ABV, brewery
- Country, description
- Flavor notes
- Average rating
Ratings
- User reference
- Beer reference
- Rating (1-5 stars)
- Notes
- Timestamps
Recommendations
- User reference
- Beer reference
- Match score (0-100)
- Reason for recommendation
- Status (viewed/dismissed)
ChatMessages
- User reference
- Message content
- AI response
- Encrypted storage
ForumPosts
- User reference
- Title, content, category
- Like count
- Parent post (for replies)
Sample Schema
create_table "beers" do |t|
t.string "name"
t.string "style"
t.decimal "abv"
t.string "brewery"
t.string "country"
t.text "description"
t.string "flavor_notes", array: true, default: []
t.timestamps
end
create_table "ratings" do |t|
t.references "user", foreign_key: true
t.references "beer", foreign_key: true
t.integer "rating"
t.text "notes"
t.timestamps
end
create_table "recommendations" do |t|
t.references "user", foreign_key: true
t.references "beer", foreign_key: true
t.integer "match_score"
t.text "reason"
t.string "status", default: "pending"
t.timestamps
end
๐ค AI Implementation
Current: Mock Implementation
The app currently uses smart pattern matching and mock AI responses:
# Mock recommendation logic
def generate_mock_recommendations
beers = Beer.where.not(id: user.rated_beer_ids)
.order("RANDOM()")
.limit(5)
beers.map do |beer|
Recommendation.create!(
user: user,
beer: beer,
match_score: rand(75..100),
reason: generate_reason(beer)
)
end
end
Production: OpenAI Integration
To enable real AI features:
Add API Key to
.env:OPENAI_API_KEY=sk-your-key-hereUncomment AI Code in controllers:
# app/controllers/api/v1/recommendations_controller.rb
def create
recommendations = AI::RecommendationService.new(current_user).generate
# Instead of mock data
end
# app/controllers/api/v1/chat_messages_controller.rb
def create
response = AI::ChatService.new(current_user).respond(params[:message])
# Instead of pattern matching
end
- AI Services (already implemented):
AI::RecommendationService- GPT-4 powered recommendationsAI::ChatService- Conversational AI with beer expertiseAI::FlavorAnalyzer- Taste profile analysis
๐ฎ Gamification System
Points Calculation
module Gamification
class PointsService
POINTS = {
rating: 5,
chat_query: 10,
recommendation: 25,
forum_post: 10,
forum_reply: 5
}
end
end
Achievement Badges
Automatically awarded based on user activity:
- Beer Novice: First rating
- Beer Explorer: 5 ratings
- Beer Connoisseur: 20 ratings
- IPA Enthusiast: 10 IPA ratings
- Community Contributor: 5 forum posts
- Chat Master: 20 chat queries
๐งช Testing
# Run all tests
bundle exec rspec
# Run specific test file
bundle exec rspec spec/models/beer_spec.rb
# Run with coverage
COVERAGE=true bundle exec rspec
Test Structure
spec/
โโโ models/ # Model unit tests
โโโ controllers/ # API endpoint tests
โโโ services/ # Service object tests
โโโ factories/ # Test data factories
๐ Deployment
Railway (Recommended)
Install Railway CLI:
npm install -g @railway/cliLogin and Initialize:
railway login railway initAdd Services:
railway add postgresql railway add redisDeploy:
railway upSet Environment Variables in Railway dashboard:
RAILS_ENV=production SECRET_KEY_BASE=$(rails secret) FRONTEND_URL=https://your-frontend.vercel.app OPENAI_API_KEY=your_key_hereRun Migrations:
railway run rails db:migrate db:seed
Heroku
# Create app
heroku create brewquest-api
# Add addons
heroku addons:create heroku-postgresql:mini
heroku addons:create heroku-redis:mini
# Deploy
git push heroku main
# Run migrations
heroku run rails db:migrate db:seed
# Set environment variables
heroku config:set SECRET_KEY_BASE=$(rails secret)
heroku config:set FRONTEND_URL=https://your-frontend.vercel.app
Docker
# Build image
docker build -t brewquest-api .
# Run container
docker run -p 3001:3001 \
-e DATABASE_URL=postgresql://... \
-e REDIS_URL=redis://... \
brewquest-api
๐ Environment Variables
| Variable | Description | Required |
|---|---|---|
DATABASE_URL |
PostgreSQL connection string | Yes |
REDIS_URL |
Redis connection string | Yes |
SECRET_KEY_BASE |
Rails secret key | Yes |
RAILS_ENV |
Environment (development/production) | Yes |
FRONTEND_URL |
Frontend URL for CORS | Yes |
OPENAI_API_KEY |
OpenAI API key | No (for production AI) |
AWS_ACCESS_KEY_ID |
AWS credentials | No (for file uploads) |
AWS_SECRET_ACCESS_KEY |
AWS credentials | No (for file uploads) |
AWS_REGION |
AWS region | No (for file uploads) |
AWS_BUCKET |
S3 bucket name | No (for file uploads) |
๐ Performance Optimization
Caching Strategy
# Cache beer list for 1 hour
Rails.cache.fetch("beers/list", expires_in: 1.hour) do
Beer.all.to_a
end
# Cache user recommendations
Rails.cache.fetch("recommendations/user_#{user.id}", expires_in: 5.minutes) do
user.recommendations.includes(:beer).to_a
end
Database Indexing
add_index :ratings, [:user_id, :beer_id]
add_index :recommendations, [:user_id, :created_at]
add_index :beers, :style
add_index :forum_posts, :category
Background Jobs
# Process AI recommendations asynchronously
RecommendationGeneratorJob.perform_later(user_id)
# Send notification emails
NotificationMailerJob.perform_later(user_id, notification_type)
๐ Security
- CORS: Configured to allow only frontend domain
- JWT Tokens: Secure authentication (disabled in demo)
- Input Validation: Strong parameters and model validations
- SQL Injection: Using ActiveRecord parameterized queries
- Rate Limiting: Rack::Attack for API throttling
- Encryption: Database encryption for sensitive data
๐ Additional Resources
- Rails API Documentation
- PostgreSQL Documentation
- Sidekiq Documentation
- OpenAI Ruby Gem
- Frontend Documentation
๐ค Contributing
- Follow Rails best practices
- Write tests for new features
- Use service objects for complex business logic
- Keep controllers thin
- Document API changes
- Run tests before committing
๐ License
This project is part of BrewQuest AI platform.
Powering the future of beer discovery with AI! ๐บ๐ค

Log in or sign up for Devpost to join the conversation.