Matter AI | Code Reviewer Documentation home pagelight logodark logo
  • Contact
  • Github
  • Sign in
  • Sign in
  • Documentation
  • Blog
  • Discord
  • Github
  • Introduction
    • What is Matter AI?
    Getting Started
    • QuickStart
    Product
    • Security Analysis
    • Code Quality
    • Agentic Chat
    • RuleSets
    • Memories
    • Analytics
    • Command List
    • Configurations
    Patterns
    • Languages
      • Supported Languages
      • Python
      • Java
      • JavaScript
      • TypeScript
      • Node.js
      • React
      • Fastify
      • Next.js
      • Terraform
      • C#
      • C++
      • C
      • Go
      • Rust
      • Swift
      • React Native
      • Spring Boot
      • Kotlin
      • Flutter
      • Ruby
      • PHP
      • Scala
      • Perl
      • R
      • Dart
      • Elixir
      • Erlang
      • Haskell
      • Lua
      • Julia
      • Clojure
      • Groovy
      • Fortran
      • COBOL
      • Pascal
      • Assembly
      • Bash
      • PowerShell
      • SQL
      • PL/SQL
      • T-SQL
      • MATLAB
      • Objective-C
      • VBA
      • ABAP
      • Apex
      • Apache Camel
      • Crystal
      • D
      • Delphi
      • Elm
      • F#
      • Hack
      • Lisp
      • OCaml
      • Prolog
      • Racket
      • Scheme
      • Solidity
      • Verilog
      • VHDL
      • Zig
      • MongoDB
      • ClickHouse
      • MySQL
      • GraphQL
      • Redis
      • Cassandra
      • Elasticsearch
    • Security
    • Performance
    Integrations
    • Code Repositories
    • Team Messengers
    • Ticketing
    Enterprise
    • Enterprise Deployment Overview
    • Enterprise Configurations
    • Observability and Fallbacks
    • Create Your Own GitHub App
    • Self-Hosting Options
    • RBAC
    Patterns
    Languages

    Ruby

    Ruby is a dynamic, open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write.

    Ruby, despite its elegant design and focus on developer happiness, still has common anti-patterns that can lead to bugs, performance issues, and maintenance problems. Here are the most important anti-patterns to avoid when writing Ruby code.

    # Anti-pattern: Using eval
    def calculate(formula)
      eval(formula) # Security risk!
    end
    
    # Usage
    calculate("2 + 2") # Returns 4
    calculate("system('rm -rf /')") # Disaster!
    
    # Better approach: Use safer alternatives
    require 'dentaku'
    
    def calculate(formula)
      calculator = Dentaku::Calculator.new
      calculator.evaluate(formula)
    end

    Using eval can lead to serious security vulnerabilities. Use safer alternatives like parsing libraries or DSLs.

    # Anti-pattern: Not using blocks
    file = File.open('file.txt', 'r')
    content = file.read
    file.close # What if an exception occurs before this line?
    
    # Better approach: Use blocks
    content = File.open('file.txt', 'r') do |file|
      file.read
    end # File is automatically closed

    Ruby’s block syntax ensures resources are properly cleaned up, even if exceptions occur.

    # Anti-pattern: Using class variables
    class User
      @@count = 0
      
      def initialize
        @@count += 1
      end
      
      def self.count
        @@count
      end
    end
    
    class Admin < User
      # Inherits and modifies the same @@count variable
    end
    
    # Better approach: Use class instance variables
    class User
      def initialize
        self.class.count += 1
      end
      
      def self.count
        @count ||= 0
      end
      
      def self.count=(value)
        @count = value
      end
    end

    Class variables (@@var) are shared across the entire class hierarchy, which can lead to unexpected behavior. Use class instance variables (@var in class methods) instead.

    # Anti-pattern: Monkey patching core classes
    class String
      def to_boolean
        self == 'true'
      end
    end
    
    # Better approach: Use refinements (Ruby 2.0+)
    module StringExtensions
      refine String do
        def to_boolean
          self == 'true'
        end
      end
    end
    
    # Usage
    using StringExtensions
    
    # Or create utility methods
    module StringUtils
      def self.to_boolean(str)
        str == 'true'
      end
    end

    Monkey patching core classes can lead to conflicts with other libraries and unexpected behavior. Use refinements or utility modules instead.

    # Anti-pattern: method_missing without respond_to_missing?
    class DynamicFinder
      def method_missing(method_name, *args)
        if method_name.to_s.start_with?('find_by_')
          # Handle dynamic finder
        else
          super
        end
      end
    end
    
    # Better approach: Implement respond_to_missing?
    class DynamicFinder
      def method_missing(method_name, *args)
        if method_name.to_s.start_with?('find_by_')
          # Handle dynamic finder
        else
          super
        end
      end
      
      def respond_to_missing?(method_name, include_private = false)
        method_name.to_s.start_with?('find_by_') || super
      end
    end

    When using method_missing, always implement respond_to_missing? to ensure methods like respond_to? and method work correctly.

    # Anti-pattern: Manual iteration
    def find_adults(people)
      adults = []
      people.each do |person|
        adults << person if person.age >= 18
      end
      adults
    end
    
    # Better approach: Use Enumerable methods
    def find_adults(people)
      people.select { |person| person.age >= 18 }
    end
    
    # More examples
    people.map { |person| person.name } # Get all names
    people.any? { |person| person.age < 18 } # Check if any minors
    people.all? { |person| person.age >= 18 } # Check if all adults
    people.reduce(0) { |sum, person| sum + person.age } # Sum ages

    Ruby’s Enumerable module provides powerful methods for working with collections. Use them instead of manual iteration.

    # Anti-pattern: Using global variables
    $db_connection = Database.connect
    
    def fetch_user(id)
      $db_connection.query("SELECT * FROM users WHERE id = #{id}")
    end
    
    # Better approach: Dependency injection
    class UserRepository
      def initialize(db_connection)
        @db_connection = db_connection
      end
      
      def fetch_user(id)
        @db_connection.query("SELECT * FROM users WHERE id = #{id}")
      end
    end

    Global variables make code hard to test and reason about. Use dependency injection or configuration objects instead.

    # Anti-pattern: String concatenation
    def greeting(name)
      "Hello, " + name + "! Welcome to " + SITE_NAME + "."
    end
    
    # Better approach: String interpolation
    def greeting(name)
      "Hello, #{name}! Welcome to #{SITE_NAME}."
    end

    String interpolation is more readable and often more efficient than string concatenation.

    # Anti-pattern: Options hash
    def create_user(name, email, options = {})
      age = options[:age] || 18
      admin = options[:admin] || false
      # Create user
    end
    
    # Usage
    create_user("John", "john@example.com", { age: 25, admin: true })
    
    # Better approach: Keyword arguments
    def create_user(name, email, age: 18, admin: false)
      # Create user
    end
    
    # Usage
    create_user("John", "john@example.com", age: 25, admin: true)

    Keyword arguments are more explicit and provide better error messages than options hashes.

    # Anti-pattern: Raising generic exceptions
    def process_data(data)
      raise "Invalid data" if data.nil?
      # Process data
    end
    
    # Better approach: Use specific exceptions
    class InvalidDataError < StandardError; end
    
    def process_data(data)
      raise InvalidDataError, "Data cannot be nil" if data.nil?
      # Process data
    rescue JSON::ParserError => e
      raise InvalidDataError, "Could not parse JSON: #{e.message}"
    end

    Create a proper exception hierarchy and use specific exception types for better error handling.

    # Anti-pattern: Manual assignment
    def process_coordinates(coords)
      x = coords[0]
      y = coords[1]
      z = coords[2]
      # Process coordinates
    end
    
    # Better approach: Destructuring assignment
    def process_coordinates(coords)
      x, y, z = coords
      # Process coordinates
    end
    
    # Works with methods returning multiple values
    def get_dimensions
      [width, height, depth]
    end
    
    width, height, depth = get_dimensions

    Use destructuring assignment to extract values from arrays and other enumerable objects.

    # Anti-pattern: Nested if/elsif
    def describe_status(status)
      if status == :pending
        "Pending approval"
      elsif status == :approved
        "Approved"
      elsif status == :rejected
        "Rejected"
      else
        "Unknown status"
      end
    end
    
    # Better approach: Case expression
    def describe_status(status)
      case status
      when :pending then "Pending approval"
      when :approved then "Approved"
      when :rejected then "Rejected"
      else "Unknown status"
      end
    end

    Use case expressions for cleaner, more readable code when comparing a value against multiple options.

    # Anti-pattern: Nested nil checks
    def get_city(user)
      if user && user.address && user.address.city
        user.address.city.name
      else
        "Unknown"
      end
    end
    
    # Better approach: Safe navigation operator (Ruby 2.3+)
    def get_city(user)
      user&.address&.city&.name || "Unknown"
    end

    Use the safe navigation operator (&.) to simplify nil checks in method chains.

    # Anti-pattern: Mutable constants
    ALLOWED_ROLES = ['admin', 'editor', 'viewer']
    
    # Later in the code
    ALLOWED_ROLES << 'guest' # Modifies the constant!
    
    # Better approach: Freeze constants
    ALLOWED_ROLES = ['admin', 'editor', 'viewer'].freeze
    
    # Even better: Freeze nested objects too
    ALLOWED_ROLES = ['admin'.freeze, 'editor'.freeze, 'viewer'.freeze].freeze

    Use freeze to prevent accidental modification of constants and other objects that should be immutable.

    # Anti-pattern: Manual array handling
    def sum(numbers)
      total = 0
      numbers.each { |n| total += n }
      total
    end
    
    # Usage
    sum([1, 2, 3, 4, 5])
    
    # Better approach: Splat operator
    def sum(*numbers)
      numbers.sum
    end
    
    # Usage
    sum(1, 2, 3, 4, 5)
    
    # Double splat for keyword arguments
    def configure(base_url:, **options)
      # Use base_url and options
    end
    
    # Usage
    configure(base_url: "https://example.com", timeout: 30, retries: 3)

    Use splat operators (* and **) for more flexible method arguments.

    # Anti-pattern: Verbose blocks
    names = people.map { |person| person.name }
    valid_users = users.select { |user| user.valid? }
    
    # Better approach: Symbol to proc
    names = people.map(&:name)
    valid_users = users.select(&:valid?)

    Use the symbol to proc shorthand (&:method_name) for cleaner code when calling a single method in a block.

    # Anti-pattern: Temporary variables
    def create_user(attributes)
      user = User.new
      user.name = attributes[:name]
      user.email = attributes[:email]
      user.save
      user
    end
    
    # Better approach: Use tap
    def create_user(attributes)
      User.new.tap do |user|
        user.name = attributes[:name]
        user.email = attributes[:email]
        user.save
      end
    end

    Use tap to perform operations on an object and return the object itself, avoiding temporary variables.

    # Anti-pattern: Deep inheritance
    class Vehicle; end
    class LandVehicle < Vehicle; end
    class Car < LandVehicle; end
    class SportsCar < Car; end
    
    # Better approach: Composition with modules
    module Engine
      def start_engine
        # Start engine
      end
    end
    
    module Drivable
      def drive
        # Drive logic
      end
    end
    
    class Car
      include Engine
      include Drivable
      
      # Car-specific methods
    end
    
    class Boat
      include Engine
      
      # Boat-specific methods
    end

    Prefer composition over inheritance by using modules to share behavior across classes.

    # Anti-pattern: Manual value objects
    class Point
      attr_reader :x, :y
      
      def initialize(x, y)
        @x = x
        @y = y
      end
      
      def ==(other)
        x == other.x && y == other.y
      end
    end
    
    # Better approach: Use Struct
    Point = Struct.new(:x, :y) do
      def distance_from_origin
        Math.sqrt(x**2 + y**2)
      end
    end

    Use Struct for simple value objects to reduce boilerplate code.

    # Anti-pattern: Eager evaluation
    def process_large_file(file_path)
      lines = File.readlines(file_path) # Reads entire file into memory
      lines.each do |line|
        process_line(line)
      end
    end
    
    # Better approach: Lazy evaluation with Enumerator
    def process_large_file(file_path)
      File.open(file_path) do |file|
        file.each_line do |line|
          process_line(line)
        end
      end
    end
    
    # Or using lazy enumerator
    def find_first_match(file_path, pattern)
      File.open(file_path).lazy.each_line
        .map(&:chomp)
        .find { |line| line.match?(pattern) }
    end

    Use enumerators and lazy evaluation for more memory-efficient processing of large collections.

    # Anti-pattern: Repeated expensive calculations
    def fibonacci(n)
      return n if n <= 1
      fibonacci(n - 1) + fibonacci(n - 2)
    end
    
    # Better approach: Memoization
    def fibonacci(n)
      @fibonacci ||= {}
      @fibonacci[n] ||= begin
        return n if n <= 1
        fibonacci(n - 1) + fibonacci(n - 2)
      end
    end

    Use memoization to cache the results of expensive calculations.

    FlutterPHP
    websitexgithublinkedin
    Powered by Mintlify
    Assistant
    Responses are generated using AI and may contain mistakes.