A Ruby on Rails weather forecasting application that delivers current and extended weather data based on user-provided addresses, optimized with caching for performance and scalability
- Overview
- Features
- Tech Stack
- Architecture
- Design Patterns
- Scalability Considerations
- Future Enhancements
- Getting Started
- Running Tests
- Deployment
WeatherCast is a robust, maintainable Ruby on Rails application designed to fetch and display weather forecasts for any given address. It prioritizes clean code, modularity, and performance through effective caching strategies. The app supports current temperature display, optional high/low and extended forecasts, and includes a user-friendly interface with cache-hit indicators
This project was developed as part of a coding assessment, emphasizing enterprise-grade practices such as unit testing, detailed documentation, and adherence to design patterns
- Address Input: Accepts full addresses (e.g., "1 Infinite Loop, Cupertino, CA 95014") or partial inputs (e.g., city/state)
- Weather Data: Retrieves current temperature, with optional high/low and 5-day extended forecasts
- Caching: Stores forecast data by zip code for 30 minutes to reduce API calls, with a cache-hit indicator in the UI
- Responsive UI: Simple, intuitive front-end for seamless user interaction
- Error Handling: Graceful handling of invalid inputs or API failures with user-friendly messages
- Framework: Ruby on Rails (v8.0.2)
- Language: Ruby (v3.4.4)
- Database: SQLite (development/test), PostgreSQL (production)
- Caching: Redis (production)
- External APIs:
- Geocoding: Geoapify
- Weather: OpenWeatherMap
- Testing: RSpec, FactoryBot
- CI/CD: GitHub Actions
- Deployment: Render.com
The application follows a modular, service-oriented architecture to ensure maintainability and testability:
- Controllers:
ForecastsController: Manages HTTP requests and renders forecast views
- Models:
Address: Validates and processes user-provided address inputsForecast: Stores and formats weather data for display
- Services:
Forecasts::FetchService: Orchestrates the workflow from address to weather resultGeocoding::ForwardService: Converts addresses to coordinates with fallback supportWeather::FetchService: Fetches weather data for given coordinatesCacheService: Handles caching with TTL using Rails cache
- Modules:
Geocoding: Abstracts geocoding logic with provider-agnostic interfacesWeather: Abstracts weather data retrieval with provider-agnostic interfaces
This decomposition ensures encapsulation, reusability, and ease of swapping external providers
- Service Pattern: Encapsulates complex business logic (e.g., geocoding, weather fetching) in dedicated service classes for modularity and testability.
- Adapter Pattern: Normalizes external API responses (Geoapify, Nominatim, OpenWeatherMap, Open-Meteo) to a consistent internal format, decoupling the app from specific providers
- Strategy Pattern: Supports interchangeable algorithms (e.g., temperature units, caching policies) for flexibility
- Caching: Redis-backed caching reduces API calls and supports horizontal scaling. Zip code-based caching optimizes performance but may miss hits for partial address inputs (e.g., city-only)
- Geocoding: Fallback mechanisms handle API failures or missing zip codes, ensuring reliability
- Future Improvements:
- Rate Limiting / Throttling
- Geospatial caching (e.g., radius-based) to improve cache hit rates
- Load balancing for high-traffic scenarios
- Implementing more Rails caching strategies, see: Ruby on Rails Caching Guide
- Monitoring: Integrate Sentry or DataDog for real-time error tracking and performance monitoring
- API Adapters: Support additional weather providers (e.g., Open-Meteo, Apple WeatherKit REST API)
- Rate Limiting / Throttling
- UI/UX:
- Address autocomplete
- Shareable/bookmarkable forecast URLs
- Enhanced accessibility (ARIA labels, keyboard navigation)
- Error Handling: More granular user feedback for edge cases (e.g., ambiguous addresses)
- Install Docker (e.g., Docker Desktop, Podman, or OrbStack)
- Install the Dev Containers extension for VS Code
- Open the project in VS Code and select "Reopen in Container" when prompted
This setup ensures a consistent development environment with all dependencies pre-configured
-
Prerequisites:
- Ruby: 3.4.4
- SQLite (development/test)
- Redis (production caching)
-
Clone the Repository:
git clone https://github.com/artkirienko/weathercast.git cd weathercast -
Install Dependencies:
bundle install- Configure Environment Variables:
RAILS_MASTER_KEY=<your-master-key>
GEOCODER_DEFAULT_EMAIL=<your-email>
GEOCODER_GEOAPIFY_API_KEY=<geoapify-api-key>
OPENWEATHERMAP_API_KEY=<openweathermap-api-key>- Set Up Database:
bin/rails db:create db:setup- Start the Server:
bin/rails serverVisit http://localhost:3000 in your browser.
RAILS_ENV=test bin/rspecThe application is deployed on Render: https://weather-di4k.onrender.com
Built with ❤️ by Artem Kirienko. *100% Human-made, No AI involved © 2025
