A Ruby gem that provides an adapter and utilities to work with data from bestchange.ru - a Russian currency exchange aggregator.
- Exchange Rate Loading - Loads exchange rates from BestChange API
- Commission Calculation - Determines commission rates of other exchanges relative to base rates
- Competitiveness Analysis - Determines if current rates are competitive in the market
- Rails Engine Integration - Full Rails Engine with API endpoints and background job support
- Background Processing - ActiveJob-based background jobs for rate processing
- Redis-based Storage - Fast data storage and caching with Redis
- RESTful API - Built-in API endpoints for accessing exchange rate data
Add this line to your application's Gemfile:
gem 'best_change'And then execute:
$ bundleRun the installation generator to set up the gem:
$ rails generate best_change:installThis will:
- Create
config/initializers/best_change.rb - Add engine routes to
config/routes.rb - Create
config/best_change.ymlconfiguration file - Configure ActiveJob queue adapter
If you prefer manual setup, add the gem and create the initializer manually:
# config/initializers/best_change.rb
BestChange.configure do |config|
config.redis = Redis.new(
host: ENV.fetch('REDIS_HOST', 'localhost'),
port: ENV.fetch('REDIS_PORT', 6379),
db: ENV.fetch('REDIS_DB', 0)
)
config.exchanger_id = ENV.fetch('BESTCHANGE_EXCHANGER_ID', 123)
config.logger = Rails.logger
endAdd the engine routes:
# config/routes.rb
mount BestChange::Engine => '/best_change'Required:
BESTCHANGE_EXCHANGER_ID- Your BestChange exchanger ID
Optional:
REDIS_HOST- Redis host (default: localhost)REDIS_PORT- Redis port (default: 6379)REDIS_DB- Redis database number (default: 0)REDIS_PASSWORD- Redis password if requiredBESTCHANGE_ACCESS_LOG- Path to access log file
BestChange.configure do |config|
config.redis = Redis.new(...) # Redis connection (required)
config.exchanger_id = 123 # Your exchanger ID (required)
config.valuta_access_log = 'log.txt' # Access log path (optional)
config.auto_start_jobs = true # Enable background jobs (default: true)
config.api_enabled = true # Enable API endpoints (default: true)
config.logger = Rails.logger # Logger instance (optional)
endOnce mounted, the engine provides the following API endpoints:
# Health check
GET /best_change/health
# Get all exchange rates
GET /best_change/api/v1/exchange_rates
# Get status summary
GET /best_change/api/v1/exchange_rates/status
# Get competitive rates only
GET /best_change/api/v1/exchange_rates/competitive
# Get available currency pairs
GET /best_change/api/v1/currency_pairs
GET /best_change/api/v1/currency_pairs/available# Load rates asynchronously (via ActiveJob)
$ rails best_change:load_rates
# Load rates synchronously (blocking)
$ rails best_change:load_rates_sync# Check your BestChange configuration
$ rails best_change:check_config
# Clear all BestChange data from Redis
$ rails best_change:clear_data# Initialize service
service = BestChange::Service.new
# Get all exchange rates
rates = service.get_all_rates
# Get competitive rates only
competitive_rates = service.get_competitive_rates
# Get status summary
status = service.get_status_summary
# Get available currency pairs
pairs = service.get_available_currency_pairsGenerate custom jobs:
$ rails generate best_change:job MyCustomJobThis creates:
app/jobs/best_change/my_custom_job.rbspec/jobs/best_change/my_custom_job_spec.rb
After checking out the repo, run:
$ bin/setup# Run all tests
$ bundle exec rake spec
# Run specific test file
$ rspec spec/best_change/service_spec.rb
# Run tests with coverage
$ COVERAGE=true bundle exec rake specThe gem includes a dummy Rails application in spec/dummy/ for testing:
# Run console with dummy app
$ cd spec/dummy && bin/rails console
# Run tests in dummy context
$ cd spec/dummy && bundle exec rake spec$ bin/console- ✅ Rails 6.0+
- ✅ Rails 6.1+
- ✅ Rails 7.0+
- ✅ Rails 7.1+
- ✅ Ruby 2.7+
- ✅ Ruby 3.0+
- ✅ Ruby 3.1+
- ✅ Ruby 3.2+
rails(>= 6.1)redis(~> 4.0)activejob(included in Rails)virtusgeragrapeojmoney-rails(~> 1.11)
rspec-railsfactory_bot_railsrubocopbyebug
- Redis Storage: Fast O(1) lookup for exchange rates
- Background Processing: Non-blocking rate processing with ActiveJob
- Batch Processing: Efficient batch processing of rate updates
- Caching: Built-in caching layer for frequently accessed data
-
Redis Connection Failed
$ rails best_change:check_config
Ensure Redis is running and accessible.
-
Exchanger ID Not Set
export BESTCHANGE_EXCHANGER_ID=123
Enable detailed logging:
BestChange.configure do |config|
config.logger = Logger.new(STDOUT, level: :debug)
endBug reports and pull requests are welcome on GitHub at https://github.com/dapi/best_change.
- Fork the repository
- Create a feature branch (
git checkout -b my-new-feature) - Run the test suite (
bundle exec rake spec) - Add tests for your changes
- Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create a Pull Request
This project uses:
The gem is available as open source under the terms of the MIT License.
Everyone interacting in the BestChange project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.