# Ruby

> Dynamic, interpreted programming language known for elegance and productivity with a focus on simplicity and programmer happiness.

- Skill: `ffsshhttiikk/ruby` (Agent Skill)
- Install (CLI): `npx skillmds@latest add ffsshhttiikk/ruby`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ffsshhttiikk/ruby/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: BSD 2-Clause "Simplified"
- Author: ffsshhttiikk (https://skillmd.com/u/ffsshhttiikk)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/ffsshhttiikk/ruby

---


# Ruby

## What I do

I am a dynamic, interpreted programming language created by Yukihiro Matsumoto in 1995. I emphasize programmer happiness and productivity with elegant, natural-feeling syntax. I am the language behind Ruby on Rails, one of the most popular web frameworks. I support multiple programming paradigms including procedural, object-oriented, and functional programming. I feature dynamic typing, duck typing, metaprogramming capabilities, and a "everything is an object" design where even primitive types are objects.

## When to use me

Use Ruby when building web applications with Ruby on Rails, rapid prototyping and MVP development, automation scripts and DevOps tooling, code generation and scaffolding tools, domain-specific languages (DSLs), or when developer happiness and productivity are top priorities.

## Core Concepts

- **Everything is an Object**: Even nil, true, false, and numbers are objects with methods.
- **Duck Typing**: If an object walks like a duck and quacks like a duck, treat it as a duck.
- **Dynamic Typing**: Variable types are determined at runtime, methods can be added to classes at runtime.
- **Blocks, Procs, and Lambdas**: First-class callable objects for iteration, callbacks, and functional patterns.
- **Mixins via Modules**: Composition pattern using modules for code reuse without multiple inheritance.
- **Metaprogramming**: Ability to modify classes and objects at runtime, defining methods dynamically.
- **Open Classes**: Can reopen and modify existing classes including built-in types (monkey patching).
- **Convention over Configuration**: Rails-style defaults reducing boilerplate configuration.
- **Garbage Collection**: Automatic memory management for objects.
- **Symbol Interning**: Symbols are immutable, cached strings used as identifiers and keys.

## Code Examples

**Blocks and Iterators:**
```ruby
numbers = [1, 2, 3, 4, 5]

squares = numbers.map { |n| n ** 2 }
evens = numbers.select(&:even?)
sum = numbers.reduce(0, :+)

puts "Squares: #{squares}"
puts "Evens: #{evens}"
puts "Sum: #{sum}"

hash = { a: 1, b: 2, c: 3 }
transformed = hash.transform_values { |v| v * 10 }
puts "Transformed: #{transformed}"

result = 10.times do |i|
  puts "Iteration #{i}"
end

[1, 2, 3].each_with_index do |num, index|
  puts "Element #{index}: #{num}"
end

class LazyProcessor
  def initialize
    @steps = []
  end
  
  def add_step(name, &block)
    @steps << [name, block]
    self
  end
  
  def process(input)
    @steps.reduce(input) do |data, (name, block)|
      puts "Running step: #{name}"
      block.call(data)
    end
  end
end

processor = LazyProcessor.new
processor
  .add_step("double") { |x| x * 2 }
  .add_step("add one") { |x| x + 1 }
  .add_step("square") { |x| x ** 2 }

result = processor.process(5)
puts "Result: #{result}"
```

**Modules and Mixins:**
```ruby
module Loggable
  def log(message)
    puts "[#{Time.now}] #{self.class}: #{message}"
  end
end

module Encryptable
  def encrypt(data)
    data.bytes.map { |b| b + 1 }.pack("C*")
  end
  
  def decrypt(data)
    data.bytes.map { |b| b - 1 }.pack("C*")
  end
end

class User
  include Loggable
  attr_accessor :name, :email
  
  def initialize(name, email)
    @name = name
    @email = email
  end
  
  def authenticate(password)
    log("Authentication attempt for #{email}")
    password == "secret"
  end
end

class SecureMessage
  include Loggable
  include Encryptable
  
  attr_accessor :content
  
  def initialize(content)
    @content = content
  end
  
  def send
    encrypted = encrypt(content)
    log("Message sent (encrypted): #{encrypted}")
    encrypted
  end
end

user = User.new("Alice", "alice@example.com")
user.authenticate("secret")

message = SecureMessage.new("Hello, World!")
encrypted = message.send
puts "Decrypted: #{message.decrypt(encrypted)}"
```

**Metaprogramming:**
```ruby
class ActiveRecord
  def self.attr_accessor_with_history(*names)
    names.each do |name|
      define_method(name) { instance_variable_get("@#{name}") }
      define_method("#{name}=") do |value|
        history = instance_variable_get("@#{name}_history") || []
        history << instance_variable_get("@#{name}")
        instance_variable_set("@#{name}_history", history)
        instance_variable_set("@#{name}", value)
      end
      define_method("#{name}_history") { instance_variable_get("@#{name}_history") }
    end
  end
  
  attr_accessor_with_history :name, :email
  
  def initialize(attributes = {})
    attributes.each do |key, value|
      send("#{key}=", value) if respond_to?("#{key}=")
    end
  end
end

class User < ActiveRecord
end

user = User.new
user.name = "Alice"
user.name = "Bob"
user.name = "Charlie"

puts user.name_history.inspect
puts user.email_history.inspect
```

**Blocks and Yield:**
```ruby
class DataProcessor
  def initialize(data)
    @data = data
  end
  
  def filter(&block)
    filtered = @data.select(&block)
    DataProcessor.new(filtered)
  end
  
  def map(&block)
    mapped = @data.map(&block)
    DataProcessor.new(mapped)
  end
  
  def reduce(initial = nil, &block)
    if block_given?
      @data.reduce(initial, &block)
    else
      @data.reduce
    end
  end
  
  def each(&block)
    @data.each(&block)
    self
  end
  
  def to_a
    @data
  end
end

processor = DataProcessor.new([1, 2, 3, 4, 5])

result = processor
  .filter { |n| n.even? }
  .map { |n| n * 10 }
  .each { |n| puts "Value: #{n}" }
  .reduce(0) { |sum, n| sum + n }

puts "Final result: #{result}"

def with_timing
  start = Time.now
  yield
  elapsed = Time.now - start
  puts "Elapsed time: #{elapsed.round(3)} seconds"
end

with_timing { sleep(0.1) }
```

## Best Practices

1. **Follow Ruby Style Guide**: Use consistent naming conventions (snake_case for variables/methods, PascalCase for classes/modules).
2. **Prefer Blocks Over Procs**: Use blocks for simple callbacks, procs/lambdas when you need to pass around callable objects.
3. **Use Symbol for Keys**: Use symbols as hash keys (symbol: value syntax) for better performance than strings.
4. **Avoid Monkey Patching Core Classes**: While possible, modifying built-in classes can lead to confusion and bugs.
5. **Use Hash.fetch for Missing Keys**: Use Hash#fetch with default values instead of || operator for missing keys.
6. **Prefer reduce Over Manual Accumulation**: Use inject/reduce for accumulating values in loops.
7. **Use Safe Navigation Operator (&.)**: Use &. for chaining methods that might return nil.
8. **Keep Methods Short**: Methods should do one thing; if you need "and" in the description, split it.
9. **Write Tests with RSpec/Minitest**: Use BDD-style tests with RSpec or simpler tests with Minitest.
10. **Use Bundle for Dependencies**: Always use Bundler (Gemfile) to manage dependencies for reproducibility.

