EverythingRB

Gem Version Ruby Version Tests

Super handy extensions to Ruby core classes that make your code more expressive, readable, and fun to write.

users = [{ name: "Alice", role: "admin" }, { name: "Bob", role: "user" }]

# Instead of this:
admin_names = users.select { |u| u[:role] == "admin" }.map { |u| u[:name] }.join(", ")

# Write this:
users.join_map(", ") { |u| u[:name] if u[:role] == "admin" }

Installation

# In your Gemfile
gem "everythingrb"

# Or install manually
gem install everythingrb

Usage

There are two ways to use EverythingRB:

Load Everything (Default)

The simplest approach - just require and go:

require "everythingrb"

# Now you have access to all extensions!
users = [{name: "Alice"}, {name: "Bob"}]
users.key_map(:name).join(", ")  # => "Alice, Bob"

config = {server: {port: 443}}.to_ostruct
config.server.port  # => 443

Cherry-Pick Extensions

If you only need specific extensions, you can load just what you want:

require "everythingrb/prelude"  # Required base module
require "everythingrb/array"    # Just Array extensions
require "everythingrb/string"   # Just String extensions

# Now you have access to only the extensions you loaded
["a", "b"].join_map(" | ") { |s| s.upcase }  # => "A | B"
'{"name": "Alice"}'.to_ostruct.name   # => "Alice"

# But Hash extensions aren't loaded yet
{}.to_ostruct  # => NoMethodError

Available modules:

  • array: Array extensions (join_map, key_map, etc.)
  • boolean: Boolean extensions (in_quotes, with_quotes)
  • data: Data extensions (to_deep_h, in_quotes)
  • date: Date and DateTime extensions (in_quotes)
  • enumerable: Enumerable extensions (join_map, group_by_key)
  • hash: Hash extensions (to_ostruct, deep_freeze, etc.)
  • kernel: Kernel extensions (morph alias for then)
  • module: Extensions like attr_predicate
  • nil: NilClass extensions (in_quotes)
  • numeric: Numeric extensions (in_quotes)
  • ostruct: OpenStruct extensions (map, join_map, etc.)
  • range: Range extensions (in_quotes)
  • regexp: Regexp extensions (in_quotes)
  • string: String extensions (to_h, to_ostruct, etc.)
  • struct: Struct extensions (to_deep_h, in_quotes)
  • symbol: Symbol extensions (with_quotes)
  • time: Time extensions (in_quotes)

What's Included

EverythingRB extends Ruby's core classes with intuitive methods that simplify common patterns.

Data Structure Conversions

Convert between data structures with ease:

# Convert hashes to more convenient structures
config = { server: { host: "example.com", port: 443 } }.to_ostruct
config.server.host  # => "example.com"

# Parse JSON directly to your preferred structure
'{"user":{"name":"Alice"}}'.to_istruct.user.name  # => "Alice"

# Deep conversion to plain hashes
data = OpenStruct.new(user: Data.define(:name).new(name: "Bob"))
data.to_deep_h  # => {user: {name: "Bob"}}

Extensions: to_struct, to_ostruct, to_istruct, to_h, to_deep_h

Collection Processing

Extract and transform data elegantly:

# Extract data from arrays of hashes in one step
users = [{ name: "Alice", roles: ["admin"] }, { name: "Bob", roles: ["user"] }]
users.key_map(:name)  # => ["Alice", "Bob"]
users.dig_map(:roles, 0)  # => ["admin", "user"]

# Filter, map, and join in a single operation
[1, 2, nil, 3, 4].join_map(" | ") { |n| "Item #{n}" if n&.odd? }
# => "Item 1 | Item 3"

# Group elements by key or nested keys
users.group_by_key(:roles, 0)
# => {"admin" => [{name: "Alice", roles: ["admin"]}], "user" => [{name: "Bob", roles: ["user"]}]}

# With ActiveSupport loaded, join arrays in natural language with "or"
["red", "blue", "green"].to_or_sentence  # => "red, blue, or green"

Extensions: join_map, key_map, dig_map, to_or_sentence, group_by_key

Object Protection

Prevent unwanted modifications with a single call:

config = {
  api: {
    key: "secret",
    endpoints: ["v1", "v2"]
  }
}.deep_freeze

# Everything is frozen!
config.frozen?  # => true
config[:api][:endpoints][0].frozen?  # => true

Extensions: deep_freeze

Hash Convenience

Work with hashes more intuitively:

# Create deeply nested structures without initialization
stats = Hash.new_nested_hash
stats[:server][:region][:us_east][:errors] << "Connection timeout"
# No need to initialize each level first!

# Transform values with access to keys
users.transform_values(with_key: true) { |v, k| "User #{k}: #{v[:name]}" }

# Find values based on conditions
users.value_where { |_k, v| v[:role] == "admin" }  # Returns first admin
users.values_where { |_k, v| v[:role] == "admin" } # Returns all admins

# Rename keys while preserving order
config = {api_key: "secret", timeout: 30}
config.rename_keys(api_key: :key, timeout: :request_timeout)
# => {key: "secret", request_timeout: 30}

# Filter hash by values
{a: 1, b: nil, c: 2}.select_values { |v| v.is_a?(Integer) && v > 1 }
# => {c: 2}

Extensions: new_nested_hash, with_key, value_where, values_where, rename_key(s), select_values, reject_values

Array Cleaning

Clean up array boundaries while preserving internal structure:

# Remove nil values from the beginning/end
[nil, nil, 1, nil, 2, nil, nil].trim_nils  # => [1, nil, 2]

# With ActiveSupport, remove blank values
[nil, "", 1, "", 2, nil, ""].trim_blanks  # => [1, "", 2]

Extensions: trim_nils, compact_prefix, compact_suffix, trim_blanks (with ActiveSupport)

String Formatting

Add quotation marks to any value with a consistent interface - useful for user messages, formatting, and more:

# Wrap any value in quotes - works on ALL types!
"hello".in_quotes      # => "\"hello\""
42.in_quotes           # => "\"42\""
nil.in_quotes          # => "\"nil\""
:symbol.in_quotes      # => "\"symbol\""
[1, 2].in_quotes       # => "\"[1, 2]\""
Time.now.in_quotes     # => "\"2025-05-04 12:34:56 +0000\""

# Perfect for user-facing messages with mixed types
puts "You selected #{selection.in_quotes}"
puts "Item #{id.in_quotes} was added to category #{category.in_quotes}"

# Great for formatting responses
response = "Command #{command.in_quotes} completed successfully"

# Ideal for error messages and logging
log.info "Received values: #{values.join_map(", ", &:in_quotes)}"
raise "Expected #{expected.in_quotes} but got #{actual.in_quotes}"

# CLI argument descriptions
puts "Valid modes are: #{MODES.join_map(", ", &:in_quotes)}"

Extensions: in_quotes, with_quotes (alias)

Boolean Methods

Create predicate methods with minimal code:

class User
  attr_accessor :admin
  attr_predicate :admin
end

user = User.new
user.admin = true
user.admin?  # => true

# Works with Data objects too!
Person = Data.define(:active)
Person.attr_predicate(:active)

person = Person.new(active: false)
person.active? # => false

Extensions: attr_predicate

Value Transformation

Chain transformations with a more descriptive syntax:

# Instead of this:
result = value.then { |v| transform_it(v) }

# Write this:
result = value.morph { |v| transform_it(v) }

Extensions: morph (alias for then/yield_self)

Full Documentation

For complete method listings, examples, and detailed usage, see the API Documentation.

Requirements

  • Ruby 3.2 or higher

Contributing

Bug reports and pull requests are welcome! This project is intended to be a safe, welcoming space for collaboration.

License

MIT License

Looking for a Software Engineer?

I'm currently looking for opportunities where I can tackle meaningful problems and help build reliable software while mentoring the next generation of developers. If you're looking for a senior engineer with full-stack Rails expertise and a passion for clean, maintainable code, let's talk!

bryan@itsthedevman.com