# 📘 Ruby/Rails Specific Coding Rules

### 📘 Rule RB001 – Use snake_case for symbols, methods, and variables

- **Objective**: Follow Ruby community naming conventions for consistency and readability.
- **Details**:
    - Use `snake_case` (all lowercase with underscores) for symbols, methods, and variables.
    - Avoid camelCase or other naming styles for these elements.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Naming/VariableName`, `Naming/MethodName`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB002 – Use CamelCase for classes and modules

- **Objective**: Follow Ruby community naming conventions for classes and modules.
- **Details**:
    - Use `CamelCase` (also known as PascalCase) for class and module names.
    - Keep acronyms uppercase (e.g., `HTTPClient`, `XMLParser`).
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Naming/ClassName`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB003 – Use SCREAMING_SNAKE_CASE for constants

- **Objective**: Clearly distinguish constants from other identifiers.
- **Details**:
    - Use `SCREAMING_SNAKE_CASE` for constants that do not refer to classes or modules.
    - Example: `MAX_RETRY_COUNT`, `DEFAULT_TIMEOUT`.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Naming/ConstantName`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB004 – Predicate methods should end with ?

- **Objective**: Make boolean-returning methods immediately recognizable.
- **Details**:
    - Methods that return boolean values should end with a question mark (`?`).
    - Avoid prefixing with auxiliary verbs like `is_`, `does_`, or `can_`.
    - Example: `valid?`, `empty?`, `authenticated?` instead of `is_valid`, `is_empty`.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Naming/PredicateName`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB005 – Dangerous methods should end with !

- **Objective**: Clearly indicate methods that modify the receiver or can raise exceptions.
- **Details**:
    - Methods that modify the object in place or can raise exceptions should end with a bang (`!`).
    - Example: `save!`, `destroy!`, `sort!`, `update!`.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Style/BangPredicate`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB006 – Use 2 spaces for indentation

- **Objective**: Follow Ruby community standard for code formatting.
- **Details**:
    - Use 2 spaces for indentation, never tabs.
    - Ensure consistent indentation throughout the codebase.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Layout/IndentationWidth`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: minor

### 📘 Rule RB007 – Keep lines under 120 characters

- **Objective**: Improve code readability and prevent horizontal scrolling.
- **Details**:
    - Limit line length to 120 characters maximum.
    - Break long lines into multiple lines when necessary.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Layout/LineLength`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: minor

### 📘 Rule RB008 – Avoid rescuing the Exception class

- **Objective**: Prevent hiding critical system errors.
- **Details**:
    - Never rescue the generic `Exception` class as it catches system-level errors.
    - Rescue specific exception classes or `StandardError` instead.
    - Example: Rescue `ActiveRecord::RecordNotFound` instead of `Exception`.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Lint/RescueException`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: critical

### 📘 Rule RB009 – Use save! or handle return values

- **Objective**: Ensure database operations are properly validated and errors are not silently ignored.
- **Details**:
    - Use bang methods (`save!`, `create!`, `update!`, `destroy!`) to raise exceptions on failure.
    - If using non-bang methods, always check the return value.
    - Never ignore the return value of persistence methods.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Rails/SaveBang`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: critical

### 📘 Rule RB010 – Avoid N+1 queries with eager loading

- **Objective**: Prevent performance issues caused by N+1 query problems.
- **Details**:
    - Use `includes`, `preload`, or `eager_load` to load associations upfront.
    - Avoid iterating over collections and accessing associations without eager loading.
    - Example: `User.includes(:posts)` instead of `User.all` when accessing posts.
- **Applies to**: Ruby/Rails
- **Tool**: Bullet gem, RuboCop Rails (`Rails/FindEach`)
- **Principle**: CODE_QUALITY, PERFORMANCE
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB011 – Use find_each for large collections

- **Objective**: Reduce memory consumption when iterating over large datasets.
- **Details**:
    - Use `find_each` or `find_in_batches` instead of `each` for large ActiveRecord collections.
    - `find_each` loads records in batches (default 1000) to avoid loading all records into memory.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Rails/FindEach`)
- **Principle**: CODE_QUALITY, PERFORMANCE
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB012 – Avoid SQL injection with parameterized queries

- **Objective**: Prevent SQL injection vulnerabilities.
- **Details**:
    - Never use string interpolation in SQL queries.
    - Use parameterized queries with `?` or named placeholders (`:name`).
    - Use hash conditions for `where` clauses instead of SQL fragments.
- **Applies to**: Ruby/Rails
- **Tool**: Brakeman, RuboCop (`Rails/SquishedSQLHeredocs`)
- **Principle**: SECURITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: critical

### 📘 Rule RB013 – Prefer has_many :through over HABTM

- **Objective**: Allow for additional attributes and validations on join models.
- **Details**:
    - Use `has_many :through` instead of `has_and_belongs_to_many` for many-to-many relationships.
    - This provides more flexibility for adding attributes to the join table.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Rails/HasAndBelongsToMany`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB014 – Always define dependent option for associations

- **Objective**: Prevent orphaned records and ensure data integrity.
- **Details**:
    - Always specify the `dependent` option for `has_many` and `has_one` associations.
    - Options: `:destroy`, `:delete_all`, `:nullify`, `:restrict_with_exception`, `:restrict_with_error`.
- **Applies to**: Ruby/Rails
- **Tool**: Custom linter
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB015 – Use new-style validations

- **Objective**: Follow modern Rails conventions for model validations.
- **Details**:
    - Use new-style validations: `validates :email, presence: true, uniqueness: true`.
    - Avoid old-style validations like `validates_presence_of :email`.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Rails/Validation`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB016 – Keep controllers thin

- **Objective**: Maintain single responsibility and improve testability.
- **Details**:
    - Controllers should only handle HTTP requests and responses.
    - Extract complex business logic into service objects, models, or concerns.
    - Aim for controllers with 5-7 lines of code per action.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Metrics/MethodLength`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB017 – Avoid fat models

- **Objective**: Prevent models from becoming monolithic and hard to maintain.
- **Details**:
    - Keep models focused on associations, validations, and simple domain logic.
    - Extract complex workflows into service objects.
    - Use concerns for clearly reusable behavior only.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Metrics/ClassLength`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB018 – Use service objects for complex business logic

- **Objective**: Improve code organization and testability.
- **Details**:
    - Extract complex business logic (payments, onboarding, multi-step processes) into service objects.
    - Service objects should have a single public method (e.g., `call`, `execute`, `perform`).
    - Place service objects in `app/services/`.
- **Applies to**: Ruby/Rails
- **Tool**: Custom linter
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB019 – Avoid needless metaprogramming

- **Objective**: Maintain code clarity and debuggability.
- **Details**:
    - Avoid using metaprogramming (`define_method`, `method_missing`, `class_eval`) unless absolutely necessary.
    - Metaprogramming makes code harder to understand, debug, and maintain.
    - Prefer explicit code over clever metaprogramming.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Style/MethodMissingSuper`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB020 – Use pluck for selecting specific columns

- **Objective**: Improve query performance by selecting only needed columns.
- **Details**:
    - Use `pluck` to select specific columns from multiple records.
    - Use `pick` for a single value from a single record.
    - Prefer `ids` over `pluck(:id)` for getting an array of IDs.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Rails/Pluck`, `Rails/PluckId`)
- **Principle**: CODE_QUALITY, PERFORMANCE
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB021 – Use size over count or length

- **Objective**: Optimize performance by using the most efficient method.
- **Details**:
    - Use `size` instead of `count` or `length` for ActiveRecord collections.
    - `size` intelligently chooses between `count` (SQL query) and `length` (array size) based on whether the collection is loaded.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Rails/SkipsModelValidations`)
- **Principle**: CODE_QUALITY, PERFORMANCE
- **Version**: 1.0
- **Status**: activated
- **Severity**: minor

### 📘 Rule RB022 – Order by timestamp columns, not id

- **Objective**: Ensure consistent ordering across database systems.
- **Details**:
    - Order records chronologically by timestamp columns (`created_at`, `updated_at`) instead of `id`.
    - IDs may not be sequential in distributed systems or with UUID primary keys.
- **Applies to**: Ruby/Rails
- **Tool**: Custom linter
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB023 – Use where.missing for Rails 6.1+

- **Objective**: Use modern Rails APIs for finding records with missing associations.
- **Details**:
    - Use `where.missing(:association)` instead of left joins with null checks.
    - This is more readable and expressive.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Rails/WhereMissing`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: minor

### 📘 Rule RB024 – Keep methods under 10 lines

- **Objective**: Improve code readability and maintainability.
- **Details**:
    - Limit methods to 10 lines of code (excluding blank lines and comments).
    - Extract complex logic into smaller, well-named private methods.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Metrics/MethodLength`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB025 – Limit method parameters to 4

- **Objective**: Reduce method complexity and improve readability.
- **Details**:
    - Limit methods to 4 parameters maximum.
    - If more parameters are needed, consider using a hash or parameter object.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Metrics/ParameterLists`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB026 – Avoid deep nesting (max 3 levels)

- **Objective**: Improve code readability and reduce cyclomatic complexity.
- **Details**:
    - Limit nesting to 3 levels maximum.
    - Use guard clauses, early returns, or extract methods to flatten code.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Metrics/BlockNesting`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB027 – Use guard clauses for early returns

- **Objective**: Reduce nesting and improve code clarity.
- **Details**:
    - Use guard clauses to handle edge cases early and return.
    - This keeps the main logic at the top level of the method.
    - Example: `return unless condition` instead of wrapping everything in `if condition`.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Style/GuardClause`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB028 – Keep classes under 100 lines

- **Objective**: Maintain single responsibility and improve maintainability.
- **Details**:
    - Limit classes to 100 lines of code (excluding blank lines and comments).
    - Extract responsibilities into separate classes or modules if a class grows too large.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Metrics/ClassLength`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB029 – Use meaningful variable and method names

- **Objective**: Improve code self-documentation and readability.
- **Details**:
    - Use descriptive names that clearly convey purpose.
    - Avoid single-letter variables except for common iterators (i, j, k).
    - Avoid abbreviations unless they are widely understood.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Naming/VariableName`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB030 – Don't Repeat Yourself (DRY)

- **Objective**: Reduce code duplication and improve maintainability.
- **Details**:
    - Extract repeated code into methods, helpers, concerns, or partials.
    - Use inheritance, composition, or modules to share behavior.
    - Avoid copy-pasting code blocks.
- **Applies to**: Ruby/Rails
- **Tool**: Reek, RuboCop (`Style/IdenticalConditionalBranches`)
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB031 – Follow MVC architecture strictly

- **Objective**: Maintain clear separation of concerns.
- **Details**:
    - Models: Data, associations, validations, simple domain logic.
    - Views: Presentation only, no business logic.
    - Controllers: HTTP handling, delegate to models/services.
    - Avoid putting business logic in views or controllers.
- **Applies to**: Ruby/Rails
- **Tool**: Custom linter
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: critical

### 📘 Rule RB032 – Use concerns judiciously

- **Objective**: Prevent concerns from becoming dumping grounds for unrelated code.
- **Details**:
    - Only use concerns for clearly reusable behavior across multiple models/controllers.
    - Each concern should have a single, well-defined responsibility.
    - Avoid creating "god concerns" with mixed responsibilities.
- **Applies to**: Ruby/Rails
- **Tool**: Custom linter
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB033 – Document callbacks and use them sparingly

- **Objective**: Prevent hidden side effects and improve code clarity.
- **Details**:
    - Document all callbacks with comments explaining their purpose.
    - Use callbacks only when necessary (e.g., setting defaults, cleaning up).
    - Avoid complex business logic in callbacks.
    - Consider using service objects instead of callbacks for complex workflows.
- **Applies to**: Ruby/Rails
- **Tool**: Custom linter
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB034 – Use decorators for view logic

- **Objective**: Keep models and views clean by separating presentation logic.
- **Details**:
    - Use decorator pattern (e.g., Draper gem) to separate formatting logic from models.
    - Decorators handle presentation concerns like formatting dates, currency, or generating display strings.
    - Keep views focused on rendering, not logic.
- **Applies to**: Ruby/Rails
- **Tool**: Custom linter
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: major

### 📘 Rule RB035 – Write comprehensive tests

- **Objective**: Ensure code quality and prevent regressions.
- **Details**:
    - Write unit tests for models, services, and helpers.
    - Write integration tests for controllers and request flows.
    - Write system tests for critical user journeys.
    - Aim for high test coverage (>80%) for business-critical code.
- **Applies to**: Ruby/Rails
- **Tool**: RSpec, Minitest, SimpleCov
- **Principle**: CODE_QUALITY
- **Version**: 1.0
- **Status**: activated
- **Severity**: critical

### 📘 Rule RB036 – Use frozen_string_literal: true

- **Objective**: Improve memory efficiency and prepare for Ruby 4.0 string immutability.
- **Details**:
    - Add `# frozen_string_literal: true` magic comment at the top of every Ruby file.
    - This prevents accidental string mutations and allows the VM to optimize string allocations.
- **Applies to**: Ruby/Rails
- **Tool**: RuboCop (`Style/FrozenStringLiteralComment`)
- **Principle**: PERFORMANCE
- **Version**: 1.1
- **Status**: activated
- **Severity**: minor

### 📘 Rule RB037 – Use 'it' as a default block parameter (Ruby 3.4+)

- **Objective**: Enhance code readability for concise block operations.
- **Details**:
    - In Ruby 3.4+, use the implicit `it` keyword instead of explicit single-use block parameters like `|x|`.
    - Example: `users.map { it.name }` instead of `users.map { |u| u.name }`.
- **Applies to**: Ruby 3.4+
- **Tool**: RuboCop (`Style/ItAssignment`)
- **Principle**: CODE_QUALITY
- **Version**: 1.1
- **Status**: activated
- **Severity**: minor

### 📘 Rule RB038 – Use modern hash-based enum syntax

- **Objective**: Use the more readable and explicit enum configuration in ActiveRecord.
- **Details**:
    - Prefer `enum :status, { pending: 0, active: 1 }` over the older `enum status: [:pending, :active]`.
    - Using a hash explicitly maps values to database integers, preventing accidental shifts if elements are reordered.
- **Applies to**: Rails 7+
- **Tool**: RuboCop (`Rails/EnumSyntax`)
- **Principle**: CODE_QUALITY
- **Version**: 1.1
- **Status**: activated
- **Severity**: major

### 📘 Rule RB039 – Prefer Solid Adapters for Infrastructure (Rails 8+)

- **Objective**: Simplify deployment and reduce external dependencies.
- **Details**:
    - For Rails 8 projects, prefer `Solid Queue`, `Solid Cache`, and `Solid Cable` over Redis-based solutions when high-performance external scaling isn't strictly required.
    - This keeps the stack "lean" by using the database for jobs and caching.
- **Applies to**: Rails 8+
- **Tool**: Manual Review
- **Principle**: ARCHITECTURE
- **Version**: 1.1
- **Status**: activated
- **Severity**: major

### 📘 Rule RB040 – Use built-in Rails 8 Authentication for greenfield projects

- **Objective**: Use the native, lightweight authentication system to reduce dependency on Devise.
- **Details**:
    - Use the `bin/rails generate authentication` command for new projects.
    - Only opt for `Devise` if complex features like OmniAuth, lockable, or confirmable are required and cannot be easily implemented.
- **Applies to**: Rails 8+
- **Tool**: Manual Review
- **Principle**: ARCHITECTURE
- **Version**: 1.1
- **Status**: activated
- **Severity**: major

### 📘 Rule RB041 – Use Async Query Loading for slow interactions

- **Objective**: Improve web performance by loading database data concurrently with view rendering.
- **Details**:
    - Use `.load_async` on ActiveRecord relations when multiple independent queries are needed for a single page.
    - Example: `@posts = Post.all.load_async` followed by `@users = User.all.load_async`.
- **Applies to**: Rails 7.1+
- **Tool**: Manual Review
- **Principle**: PERFORMANCE
- **Version**: 1.1
- **Status**: activated
- **Severity**: major

### 📘 Rule RB042 – Minimize custom JavaScript with Hotwire/Turbo 2.0

- **Objective**: Focus on the Rails "Majestic Monolith" approach for better maintainability.
- **Details**:
    - Prefer `Turbo Frames` and `Turbo Streams` for interaction.
    - Use `Stimulus` for small client-side behaviors.
    - Avoid full-blown SPA frameworks (React/Vue) unless the UI specifically requires complex client-side state management.
- **Applies to**: Rails 7+
- **Tool**: Manual Review
- **Principle**: ARCHITECTURE
- **Version**: 1.1
- **Status**: activated
- **Severity**: major

### 📘 Rule RB043 – Use Propshaft as the default asset pipeline

- **Objective**: Use the modern, simplified asset pipeline instead of Sprockets.
- **Details**:
    - For new Rails 7+ projects, use `Propshaft` to handle asset digests and paths without the complexity of Sprockets' transpilation.
- **Applies to**: Rails 7+
- **Tool**: Manual Review
- **Principle**: ARCHITECTURE
- **Version**: 1.1
- **Status**: activated
- **Severity**: minor

### 📘 Rule RB044 – Use Structured Logging for Observability

- **Objective**: Improve log parsing and searching in production environments.
- **Details**:
    - Configure `config.log_formatter = JSONFormatter.new` (or similar) in production.
    - Include request IDs and user context in logs to facilitate tracing.
- **Applies to**: Ruby/Rails
- **Tool**: Lograge gem
- **Principle**: MAINTAINABILITY
- **Version**: 1.1
- **Status**: activated
- **Severity**: major

### 📘 Rule RB045 – Use Prism as the default parser for tooling

- **Objective**: Leverage the faster, more accurate Ruby parser.
- **Details**:
    - Configure tools like `RuboCop` or `SyntaxTree` to use `Prism` for parsing where supported in Ruby 3.4+.
- **Applies to**: Ruby 3.4+
- **Tool**: RuboCop (`ParserEngine: prism`)
- **Principle**: TOOLING
- **Version**: 1.1
- **Status**: activated
- **Severity**: minor

