AI Rules for Ruby
Guide for effective AI interaction patterns when working with Ruby code.
Ruby Rules
.cusor/rules/ruby.mdc
---
description: Enforces best practices for Ruby development, focusing on context-aware code generation, modern patterns, and maintainable architecture. Provides comprehensive guidelines for writing clean, efficient, and secure Ruby code with proper context.
globs: **/*.{rb,rake}
---
# Ruby Best Practices
You are an expert in Ruby programming, Rails, Sinatra, and related Ruby technologies.
You understand modern Ruby development practices, architectural patterns, and the importance of providing complete context in code generation.
### Context-Aware Code Generation
- Always provide complete module context including requires, autoloads, and class definitions
- Include relevant configuration files (Gemfile, Rakefile, config.ru) when generating projects
- Generate complete method signatures with proper parameters, blocks, and keyword arguments
- Include comprehensive YARD documentation with examples and type information
- Provide context about the module's role in the larger system architecture
- Include proper namespace organization and module hierarchy
### Code Style and Structure
- Follow Ruby style guide and clean code principles
- Structure code in logical modules following domain-driven design
- Implement proper separation of concerns (models, controllers, services, concerns)
- Use modern Ruby features (pattern matching, endless methods, numbered parameters) appropriately
- Maintain consistent code formatting using RuboCop with custom rules
- Use proper module and class organization with clear responsibilities
- Implement proper error handling with custom exception classes
- Use proper logging with structured data
### Framework Best Practices
- Use Rails 7+ features and best practices
- Implement proper MVC architecture with service objects
- Configure proper routing with resourceful routes
- Use proper ActiveRecord patterns with concerns and scopes
- Implement proper database migrations with reversible changes
- Configure proper testing setup with RSpec and FactoryBot
- Use proper background job processing with ActiveJob
- Implement proper caching strategies with Redis
- Use proper asset pipeline with import maps
### Testing and Quality
- Write comprehensive unit tests with proper test context
- Include integration tests for critical paths
- Use proper mocking strategies with RSpec
- Implement E2E tests with Capybara
- Include performance tests for critical components
- Maintain high test coverage for core business logic
- Use proper test data factories with FactoryBot
- Implement proper test doubles with RSpec
- Use proper test organization with shared examples
### Security and Performance
- Implement proper input validation and sanitization
- Use secure authentication with Devise or custom solutions
- Configure proper CORS and CSRF protection
- Implement rate limiting and request validation
- Use proper caching strategies with Redis
- Optimize database queries with proper indexing
- Implement proper SQL injection prevention
- Use proper XSS protection
- Implement proper session management
### API Design
- Follow RESTful principles with proper HTTP methods
- Use proper status codes and error responses
- Implement proper versioning strategies
- Document APIs using OpenAPI/Swagger
- Include proper request/response validation
- Implement proper pagination and filtering
- Use proper serialization with ActiveModel::Serializers
- Implement proper rate limiting
- Use proper API authentication
### Database and Data Access
- Use proper ActiveRecord patterns
- Implement proper transaction management
- Use database migrations with reversible changes
- Optimize queries with proper indexing
- Implement proper connection pooling
- Use proper database isolation levels
- Implement proper data validation
- Use proper database constraints
- Implement proper data encryption
### Build and Deployment
- Use Bundler for dependency management
- Implement proper CI/CD pipelines
- Use Docker for containerization
- Configure proper environment variables
- Implement proper logging and monitoring
- Use proper deployment strategies
- Implement proper backup strategies
- Use proper monitoring with NewRelic
- Implement proper error tracking with Sentry
### Examples
```ruby
# frozen_string_literal: true
module Services
# UserService handles user-related operations.
# Provides methods for user management and authentication.
class UserService
include ActiveSupport::Callbacks
define_callbacks :user_found
def initialize(api_client:, cache:, logger: Rails.logger)
@api_client = api_client
@cache = cache
@logger = logger
end
# Finds a user by their email address.
#
# @param email [String] The email address to search for
# @return [User, nil] The user if found, nil otherwise
# @raise [ApiError] if the request fails
# @example
# service = UserService.new(api_client: client, cache: cache)
# user = service.find_user_by_email('[email protected]')
def find_user_by_email(email)
run_callbacks :user_found do
cached_user = @cache.get("user:#{email}")
return User.new(JSON.parse(cached_user)) if cached_user
user_data = @api_client.get("/users?email=#{email}")
return nil unless user_data
user = User.new(user_data)
@cache.set("user:#{email}", user_data.to_json)
user
end
rescue StandardError => e
@logger.error("Failed to find user by email: #{e.message}")
raise ApiError, "Failed to find user by email: #{e.message}"
end
end
end
# Tests for UserService functionality.
RSpec.describe Services::UserService do
subject(:service) { described_class.new(api_client: api_client, cache: cache) }
let(:api_client) { instance_double(ApiClient) }
let(:cache) { instance_double(Cache) }
let(:logger) { instance_double(Logger) }
describe '#find_user_by_email' do
context 'when user exists' do
let(:email) { '[email protected]' }
let(:user_data) { { id: 1, email: email } }
before do
allow(api_client).to receive(:get).with("/users?email=#{email}").and_return(user_data)
end
it 'returns the user' do
result = service.find_user_by_email(email)
expect(result).to be_a(User)
expect(result.email).to eq(email)
expect(api_client).to have_received(:get).with("/users?email=#{email}")
end
it 'triggers user_found callback' do
expect(service).to receive(:run_callbacks).with(:user_found)
service.find_user_by_email(email)
end
end
context 'when user not found' do
let(:email) { '[email protected]' }
before do
allow(api_client).to receive(:get).with("/users?email=#{email}").and_return(nil)
end
it 'returns nil' do
result = service.find_user_by_email(email)
expect(result).to be_nil
expect(api_client).to have_received(:get).with("/users?email=#{email}")
end
end
context 'when API request fails' do
let(:email) { '[email protected]' }
before do
allow(api_client).to receive(:get).with("/users?email=#{email}")
.and_raise(StandardError.new('API Error'))
end
it 'raises ApiError' do
expect { service.find_user_by_email(email) }
.to raise_error(ApiError, /Failed to find user by email/)
end
end
end
end