Thank you for your interest in contributing to the exa-ai gem! This document provides guidelines and instructions for development.
- Ruby 3.0 or higher
- Bundler
- Clone the repository
git clone https://github.com/benjaminjackson/exa-ruby.git
cd exa-ruby- Install dependencies
bundle install- Set up your environment (optional)
export EXA_API_KEY="your-api-key"bundle exec rake testbundle exec ruby test/services/search_test.rbbundle exec rake test TEST="test/services/*_test.rb"bundle exec ruby test/services/search_test.rb -n test_search_returns_resultsbundle exec rake test TESTOPTS="-v"- Follow Ruby conventions and idioms
- Use Ruby 3.0+ features (keyword arguments, pattern matching, endless methods)
- Prefer self-documenting code over comments
- Reference CLAUDE.md for architecture patterns
- Write tests before implementation (red-green-refactor)
- Use descriptive test names:
test_search_raises_error_when_query_missing - Follow Arrange-Act-Assert structure
- One assertion per test (generally)
- Use minitest assertions:
assert_equal,assert_nil,assert_empty,assert_includesrefute_equal,refute_nil,refute_emptyassert_raisesfor error testingassert_instance_offor type checking
- Use conventional format:
<type>(<scope>): <subject> - Types:
feat,fix,docs,test,refactor,chore - Subject: 50 chars max, imperative mood ("add" not "added"), no period
- For complex changes: add body explaining what/why (72-char lines)
- Keep commits atomic (one logical change per commit)
- Add YARD docs for public methods (
@param,@return,@example) - Update README.md with usage examples for new features
- Reference the OpenAPI spec in spec/ when implementing new endpoints
-
Check the OpenAPI spec first
- Read
spec/endpoints/{endpoint_name}.yamlfor request/response structure - Check
spec/components.yamlfor schema definitions
- Read
-
Create resource object (if needed)
- Use frozen Struct or plain class for immutability
- Add helper methods for common operations
- Implement
#to_hfor serialization
-
Write tests first (
test/services/{endpoint}_test.rb)- Stub HTTP requests with WebMock
- Test success and error cases
- Verify correct API endpoint and parameters
-
Implement service object (
lib/exa/services/{endpoint}.rb)- Constructor takes connection and parameters
- Single public
#callmethod returns resource object - Minimal business logic
-
Add to Client class (
lib/exa/client.rb)- Add delegating method with YARD docs
- Follow existing method naming conventions
-
Add integration test (optional)
- Use VCR cassette for recorded HTTP interactions
- Test real API contract with response validation
-
Update README.md
- Add usage example in Ruby API section
- Add CLI command documentation if applicable
- Test single class in isolation
- Mock external dependencies (HTTP calls)
- Fast (<1ms per test)
- Location:
test/services/,test/root
- Test multiple components working together
- Stub HTTP responses with VCR cassettes
- Slower but verify contract between components
- Location:
test/integration/
- WebMock is configured to prevent real HTTP calls
- VCR records/replays HTTP interactions
- API keys are filtered from cassettes for security
- Test helper:
test/test_helper.rb
bundle exec rake buildbundle exec rake installbundle exec bundle-audit checkbundle exec yardoc- All tests passing
- No security vulnerabilities
- Documentation up to date
- CHANGELOG.md updated
-
Verify readiness
# Run all tests bundle exec rake test # Build locally bundle exec gem build exa-ai.gemspec # Security audit bundle exec bundle-audit check
-
Prepare release commit (if not already done)
# Update version in lib/exa/version.rb if needed # Update CHANGELOG.md with new version notes git add -A git commit -m "chore(release): Prepare vX.Y.Z"
-
Create GitHub release with gh CLI
# This creates git tag, GitHub release, and uploads gem artifact gh release create vX.Y.Z \ --title "vX.Y.Z - <Release Title>" \ --notes-file CHANGELOG.md \ exa-ai-X.Y.Z.gem
-
Publish to RubyGems
gem push exa-ai-X.Y.Z.gem
-
Verify release
# Verify on RubyGems.org gem list -r exa-ai # View GitHub release gh release view vX.Y.Z
Gem build fails
- Check that exa.gemspec files list includes all necessary files
- Verify no uncommitted changes in tracked files
- Run
bundle exec rake buildwith verbose output
GitHub release creation fails
- Verify
ghCLI is installed and authenticated:gh auth status - Check gem file exists:
ls -la exa-ai-*.gem - Ensure you have push access to repository
RubyGems publish fails
- Verify credentials:
gem signinor check~/.gem/credentials - Check version is not already published:
gem list -r exa-ai - Ensure gem builds locally first
- Check existing tests for patterns and examples
- Review CLAUDE.md for architecture decisions
- Read OpenAPI specs in
spec/for API details - Check README.md for usage examples
Contributors are expected to be respectful and constructive in all interactions.
Thank you for contributing to exa-ai! 🙏