Ruby Samples

Essential Ruby code examples for web development, including Rails framework and modern Ruby features

Key Facts

Category
Programming Languages
Items
3
Format Families
sample

Sample Overview

Essential Ruby code examples for web development, including Rails framework and modern Ruby features This sample set belongs to Programming Languages and can be used to test related workflows inside Elysia Tools.

💻 Ruby Hello World ruby

🟢 simple

Basic Ruby Hello World program with dynamic typing and elegant syntax

⏱️ 12 min 🏷️ ruby, dynamic typing, object-oriented
Prerequisites: Basic programming concepts
# Ruby Hello World Examples

# 1. Basic Hello World
puts "Hello, World!"

# 2. Hello World with variable
message = "Hello, World!"
puts message

# 3. Hello World with method
def say_hello
  "Hello, World!"
end

puts say_hello

# 4. Hello World with parameters
def greet(name)
  "Hello, #{name}!"
end

puts greet("World")
puts greet("Ruby")

# 5. Hello World with class
class Greeter
  def initialize(message = "Hello, World!")
    @message = message
  end

  def greet
    puts @message
  end
end

greeter = Greeter.new
greeter.greet

# 6. Hello World with user input
print "Enter your name: "
name = gets.chomp
puts "Hello, #{name}!"

# 7. Hello World multiple times
5.times do |i|
  puts "Hello, World! #{i + 1}"
end

# 8. Hello World with array
greetings = ["Hello", "Bonjour", "Hola", "Ciao", "こんにちは"]
greetings.each do |greeting|
  puts "#{greeting}, World!"
end

# 9. Hello World with hash
greetings = {
  "en" => "Hello",
  "es" => "Hola",
  "fr" => "Bonjour",
  "de" => "Hallo",
  "ja" => "こんにちは"
}

greetings.each do |lang, greeting|
  puts "#{greeting}, World! (#{lang})"
end

# 10. Hello World with JSON
require 'json'

response = {
  message: "Hello, World!",
  timestamp: Time.now.to_s,
  success: true
}

puts JSON.pretty_generate(response)

# Basic data types examples
# Ruby is dynamically typed, so types are inferred

integer = 42
float = 3.14
string = "Hello, Ruby!"
boolean = true
array = [1, 2, 3, 4, 5]
hash = { name: "John Doe", age: 30, email: "[email protected]" }
symbol = :ruby_symbol
nil_value = nil

puts "Integer: #{integer}, Class: #{integer.class}"
puts "Float: #{float}, Class: #{float.class}"
puts "String: #{string}, Class: #{string.class}"
puts "Boolean: #{boolean}, Class: #{boolean.class}"
puts "Array: #{array}, Class: #{array.class}"
puts "Hash: #{hash}, Class: #{hash.class}"
puts "Symbol: #{symbol}, Class: #{symbol.class}"
puts "Nil: #{nil_value}, Class: #{nil_value.class}"

# Control flow examples
age = 18
if age >= 18
  puts "You are an adult"
else
  puts "You are a minor"
end

# Case statement
grade = 'A'
case grade
when 'A'
  puts "Excellent!"
when 'B'
  puts "Good job!"
when 'C'
  puts "Fair enough"
else
  puts "Need improvement"
end

# Loop examples
fruits = ["apple", "banana", "cherry"]
fruits.each do |fruit|
  puts "I like #{fruit}"
end

# Range operations
(1..10).each do |i|
  puts "Number: #{i}"
end

# Array methods examples
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = numbers.select { |n| n.even? }
squared_numbers = numbers.map { |n| n ** 2 }
sum = numbers.reduce(0, :+)

puts "Even numbers: #{even_numbers}"
puts "Squared numbers: #{squared_numbers}"
puts "Sum: #{sum}"

# String methods examples
text = "Hello, Ruby Programming!"
puts "Upcase: #{text.upcase}"
puts "Downcase: #{text.downcase}"
puts "Capitalized: #{text.capitalize}"
puts "Length: #{text.length}"
puts "Reverse: #{text.reverse}"

# Method chaining
numbers = [1, 2, 3, 4, 5]
result = numbers
  .select { |n| n.even? }
  .map { |n| n ** 2 }
  .reduce(0, :+)

puts "Result of chained operations: #{result}"

# Blocks and Procs
def execute_twice
  yield
  yield
end

execute_twice { puts "Hello from block!" }

# Procs and Lambdas
greet_proc = Proc.new { |name| puts "Hello, #{name}!" }
greet_proc.call("Ruby")

greet_lambda = lambda { |name| "Hello, #{name}!" }
puts greet_lambda.call("Lambda")

# Symbols and their common uses
status = :active
puts status == :active ? "User is active" : "User is inactive"

# Using symbols as hash keys (Rubyist style)
user = {
  name: "Alice",
  age: 25,
  :email => "[email protected]"
}

puts user[:name]
puts user[:email]

# Constants
PI = 3.14159265359
MAX_USERS = 100

puts "PI: #{PI}"
puts "Max users: #{MAX_USERS}"

# Exception handling
begin
  result = 10 / 0
rescue ZeroDivisionError => e
  puts "Error: #{e.message}"
ensure
  puts "This always runs"
end

# Method return values
def add(a, b)
  # Ruby implicitly returns the last evaluated expression
  a + b
end

puts "Addition: #{add(5, 3)}"

# Splat arguments
def sum(*numbers)
  numbers.reduce(0, :+)
end

puts "Sum of 1, 2, 3, 4, 5: #{sum(1, 2, 3, 4, 5)}"

# Keyword arguments (Ruby 2.0+)
def create_user(name:, email:, age: nil, role: 'user')
  {
    name: name,
    email: email,
    age: age,
    role: role
  }
end

user = create_user(name: "Bob", email: "[email protected]", age: 30)
puts "Created user: #{user}"

# Class methods
class MathUtils
  def self.pi
    3.14159265359
  end

  def self.circle_area(radius)
    pi * radius ** 2
  end
end

puts "Pi: #{MathUtils.pi}"
puts "Circle area (radius 5): #{MathUtils.circle_area(5)}"

# Modules and mixins
module Greetable
  def greet
    puts "Hello, I'm #{name}"
  end
end

class Person
  include Greetable
  attr_reader :name

  def initialize(name)
    @name = name
  end
end

person = Person.new("Charlie")
person.greet

💻 Ruby on Rails Patterns ruby

🟡 intermediate ⭐⭐⭐⭐

Common Rails patterns, MVC architecture, and modern web development practices

⏱️ 45 min 🏷️ ruby, rails, web development, patterns
Prerequisites: Ruby basics, Web development concepts, MVC architecture
# Ruby on Rails Patterns Examples

# 1. Model with validations and associations
# app/models/user.rb
class User < ApplicationRecord
  # Validations
  validates :name, presence: true, length: { minimum: 2, maximum: 50 }
  validates :email, presence: true, uniqueness: { case_sensitive: false }
  validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }
  validates :age, numericality: { greater_than: 0, less_than: 120 }
  validates :terms_of_service, acceptance: true

  # Callbacks
  before_save :downcase_email
  after_create :send_welcome_email
  after_commit :log_user_creation

  # Associations
  has_many :posts, dependent: :destroy
  has_many :comments, through: :posts
  has_one :profile, dependent: :destroy
  has_and_belongs_to_many :roles
  has_many :followers, class_name: "Follow", foreign_key: "followed_id"
  has_many :followed, class_name: "Follow", foreign_key: "follower_id"

  # Scopes
  scope :active, -> { where(active: true) }
  scope :by_age, ->(min_age, max_age) { where(age: min_age..max_age) }
  scope :recent, -> { order(created_at: :desc) }
  scope :with_posts, -> { includes(:posts).where.not(posts: { id: nil }) }

  # Class methods
  def self.search(query)
    where("name ILIKE ? OR email ILIKE ?", "%#{query}%", "%#{query}%")
  end

  def self.by_role(role_name)
    joins(:roles).where(roles: { name: role_name })
  end

  # Instance methods
  def full_name
    profile&.full_name || name
  end

  def admin?
    roles.exists?(name: 'admin')
  end

  def can_post?
    active? && email_verified?
  end

  def follow(user)
    followed << user unless following?(user)
  end

  def unfollow(user)
    followed.delete(user) if following?(user)
  end

  def following?(user)
    followed.include?(user)
  end

  private

  def downcase_email
    email.downcase!
  end

  def send_welcome_email
    UserMailer.welcome_email(self).deliver_later
  end

  def log_user_creation
    Rails.logger.info "New user created: #{name} (#{email})"
  end
end

# 2. Controller with RESTful actions and strong parameters
# app/controllers/users_controller.rb
class UsersController < ApplicationController
  before_action :authenticate_user!
  before_action :set_user, only: [:show, :edit, :update, :destroy]
  before_action :authorize_user, only: [:edit, :update, :destroy]

  # GET /users
  def index
    @users = User.includes(:profile)
                .active
                .recent
                .page(params[:page])
                .per(20)

    respond_to do |format|
      format.html
      format.json { render json: @users }
      format.csv { send_data User.to_csv(@users), filename: "users.csv" }
    end
  end

  # GET /users/1
  def show
    @posts = @user.posts.includes(:comments).published.recent.limit(10)

    respond_to do |format|
      format.html
      format.json { render json: @user }
    end
  end

  # GET /users/new
  def new
    @user = User.new
    @user.build_profile
  end

  # POST /users
  def create
    @user = User.new(user_params)

    respond_to do |format|
      if @user.save
        format.html { redirect_to @user, notice: 'User was successfully created.' }
        format.json { render json: @user, status: :created }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # GET /users/1/edit
  def edit
  end

  # PATCH/PUT /users/1
  def update
    respond_to do |format|
      if @user.update(user_params)
        format.html { redirect_to @user, notice: 'User was successfully updated.' }
        format.json { render json: @user }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /users/1
  def destroy
    @user.destroy

    respond_to do |format|
      format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private

  def set_user
    @user = User.includes(:profile, :posts).find(params[:id])
  end

  def authorize_user
    redirect_to root_path, alert: 'Not authorized' unless can?(:manage, @user)
  end

  def user_params
    params.require(:user).permit(
      :name,
      :email,
      :age,
      :bio,
      profile_attributes: [
        :id,
        :first_name,
        :last_name,
        :avatar,
        :website,
        :location,
        :bio
      ]
    )
  end
end

# 3. Service Object Pattern
# app/services/user_registration_service.rb
class UserRegistrationService
  include ActiveModel::Model
  include ActiveModel::Attributes

  attribute :email, :string
  attribute :password, :string
  attribute :password_confirmation, :string
  attribute :name, :string
  attribute :accept_terms, :boolean
  attribute :marketing_emails, :boolean, default: false

  validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
  validates :password, presence: true, length: { minimum: 8 }
  validates :password_confirmation, presence: true
  validates :name, presence: true, length: { minimum: 2 }
  validates :accept_terms, acceptance: true

  validate :passwords_match
  validate :email_uniqueness

  def call
    return false unless valid?

    ActiveRecord::Base.transaction do
      user = User.create!(user_attributes)
      Profile.create!(profile_attributes(user))
      send_welcome_email(user)
      subscribe_to_newsletter(user) if marketing_emails
      user
    end
  rescue ActiveRecord::RecordInvalid => e
    errors.add(:base, e.message)
    false
  end

  private

  def passwords_match
    return if password == password_confirmation
    errors.add(:password_confirmation, "doesn't match Password")
  end

  def email_uniqueness
    return unless User.exists?(email: email)
    errors.add(:email, "has already been taken")
  end

  def user_attributes
    {
      email: email.downcase,
      password: password,
      name: name,
      active: true,
      email_verified: false
    }
  end

  def profile_attributes(user)
    {
      user: user,
      first_name: name.split(' ').first,
      last_name: name.split(' ').last,
      avatar: generate_default_avatar,
      email_notifications: true
    }
  end

  def generate_default_avatar
    # Generate a default avatar using a service like Gravatar
    "https://ui-avatars.com/api/?name=#{URI.encode_www_form_component(name)}&background=random"
  end

  def send_welcome_email(user)
    UserMailer.welcome_email(user).deliver_later
  end

  def subscribe_to_newsletter(user)
    NewsletterSubscription.create!(user: user, active: true)
  end
end

# 4. Decorator Pattern
# app/decorators/user_decorator.rb
class UserDecorator
  include ActionView::Helpers
  include Rails.application.routes.url_helpers

  def initialize(user)
    @user = user
  end

  delegate_missing_to :@user

  def display_name
    if profile&.first_name && profile&.last_name
      "#{profile.first_name} #{profile.last_name}"
    else
      name
    end
  end

  def avatar_url(size: :medium)
    if profile&.avatar.present?
      profile.avatar.variant(resize: avatar_size(size))
    else
      default_avatar_url
    end
  end

  def profile_completion_percentage
    completed_fields = 0
    total_fields = 5

    completed_fields += 1 if name.present?
    completed_fields += 1 if email.present?
    completed_fields += 1 if profile&.bio.present?
    completed_fields += 1 if profile&.location.present?
    completed_fields += 1 if profile&.website.present?

    (completed_fields.to_f / total_fields * 100).round
  end

  def join_date
    created_at.strftime("%B %d, %Y")
  end

  def status_badge
    case
    when admin?
      content_tag(:span, "Admin", class: "badge badge-danger")
    when active?
      content_tag(:span, "Active", class: "badge badge-success")
    else
      content_tag(:span, "Inactive", class: "badge badge-secondary")
    end
  end

  def stats
    {
      posts: posts.published.count,
      comments: comments.count,
      followers: followers.count,
      following: followed.count
    }
  end

  def action_buttons(current_user)
    buttons = []

    if current_user == self
      buttons << link_to("Edit Profile", edit_user_path(self), class: "btn btn-primary")
    else
      if current_user.following?(self)
        buttons << link_to("Unfollow", unfollow_user_path(self), method: :delete, class: "btn btn-secondary")
      else
        buttons << link_to("Follow", follow_user_path(self), method: :post, class: "btn btn-primary")
      end
    end

    buttons.join(" ").html_safe
  end

  private

  def avatar_size(size)
    case size
    when :small then "50x50"
    when :medium then "100x100"
    when :large then "200x200"
    else "100x100"
    end
  end

  def default_avatar_url
    "https://ui-avatars.com/api/?name=#{URI.encode_www_form_component(name)}&background=random&size=100"
  end
end

# 5. Query Object Pattern
# app/queries/post_search_query.rb
class PostSearchQuery
  def initialize(params = {})
    @params = params
  end

  def call
    posts = Post.published.includes(:user, :tags, :comments)
    posts = filter_by_user(posts)
    posts = filter_by_tags(posts)
    posts = filter_by_date_range(posts)
    posts = filter_by_status(posts)
    posts = search_by_content(posts)
    posts = sort_posts(posts)
    posts
  end

  private

  attr_reader :params

  def filter_by_user(posts)
    return posts unless params[:user_id].present?
    posts.where(user_id: params[:user_id])
  end

  def filter_by_tags(posts)
    return posts unless params[:tag_ids].present?
    posts.joins(:tags).where(tags: { id: params[:tag_ids] })
  end

  def filter_by_date_range(posts)
    if params[:date_from].present?
      posts = posts.where("posts.created_at >= ?", params[:date_from])
    end

    if params[:date_to].present?
      posts = posts.where("posts.created_at <= ?", params[:date_to])
    end

    posts
  end

  def filter_by_status(posts)
    return posts unless params[:status].present?
    posts.where(status: params[:status])
  end

  def search_by_content(posts)
    return posts unless params[:query].present?
    posts.where(
      "posts.title ILIKE ? OR posts.content ILIKE ?",
      "%#{params[:query]}%",
      "%#{params[:query]}%"
    )
  end

  def sort_posts(posts)
    sort_column = params[:sort] || 'created_at'
    sort_direction = params[:direction] || 'desc'

    if posts.column_names.include?(sort_column)
      posts.order("#{sort_column} #{sort_direction}")
    else
      posts.order(created_at: :desc)
    end
  end
end

# 6. Form Object Pattern
# app/forms/post_form.rb
class PostForm
  include ActiveModel::Model
  include ActiveModel::Attributes
  include ActiveModel::Validations::Callbacks

  attribute :title, :string
  attribute :content, :string
  attribute :excerpt, :string
  attribute :status, :string, default: 'draft'
  attribute :published_at, :datetime
  attribute :tag_names, :string, default: ''
  attribute :featured_image, :string
  attribute :user_id, :integer

  validates :title, presence: true, length: { maximum: 100 }
  validates :content, presence: true, length: { minimum: 50 }
  validates :status, inclusion: { in: %w[draft published archived] }
  validates :user_id, presence: true

  validate :published_at_presence_if_published
  validate :tag_names_validity

  before_validation :generate_excerpt_if_blank
  before_validation :set_published_at

  def initialize(post = nil, attributes = {})
    @post = post
    super(attributes)
    copy_post_attributes if @post
  end

  def save
    return false unless valid?

    ActiveRecord::Base.transaction do
      post = @post || user.posts.build
      post.assign_attributes(post_attributes)
      post.save!
      update_post_tags(post)
      @post = post
    end

    true
  rescue ActiveRecord::RecordInvalid => e
    errors.add(:base, e.message)
    false
  end

  def persisted?
    @post&.persisted?
  end

  private

  attr_reader :post

  def user
    User.find(user_id) if user_id.present?
  end

  def post_attributes
    {
      title: title,
      content: content,
      excerpt: excerpt,
      status: status,
      published_at: published_at,
      featured_image: featured_image
    }
  end

  def copy_post_attributes
    self.title = @post.title
    self.content = @post.content
    self.excerpt = @post.excerpt
    self.status = @post.status
    self.published_at = @post.published_at
    self.featured_image = @post.featured_image
    self.user_id = @post.user_id
    self.tag_names = @post.tags.map(&:name).join(', ')
  end

  def published_at_presence_if_published
    return unless status == 'published'
    errors.add(:published_at, "can't be blank when status is published") if published_at.blank?
  end

  def tag_names_validity
    return if tag_names.blank?

    invalid_tags = tag_names.split(',').map(&:strip).reject { |name| name.match?(/A[a-zA-Z0-9s-]+z/) }
    if invalid_tags.any?
      errors.add(:tag_names, "contain invalid tags: #{invalid_tags.join(', ')}")
    end
  end

  def generate_excerpt_if_blank
    return if excerpt.present?
    self.excerpt = content&.truncate(150, separator: ' ')
  end

  def set_published_at
    self.published_at = Time.current if status == 'published' && published_at.blank?
  end

  def update_post_tags(post)
    tag_names_array = tag_names.split(',').map(&:strip).map(&:downcase).uniq
    current_tag_names = post.tags.map(&:name)

    # Remove tags that are no longer present
    tags_to_remove = current_tag_names - tag_names_array
    post.tags.where(name: tags_to_remove).destroy_all if tags_to_remove.any?

    # Add new tags
    tag_names_array.each do |tag_name|
      next if current_tag_names.include?(tag_name)
      post.tags.find_or_create_by(name: tag_name)
    end
  end
end

# 7. Background Job Pattern
# app/jobs/email_notification_job.rb
class EmailNotificationJob < ApplicationJob
  queue_as :default

  rescue_from(StandardError) do |exception|
    Rails.logger.error "Email job failed: #{exception.message}"
    retry_job wait: 5.minutes, attempts: 3
  end

  def perform(user_id, template, **options)
    user = User.find(user_id)
    UserMailer.with(user: user, **options).send(template).deliver_now
  end
end

# 8. Policy Pattern for Authorization
# app/policies/post_policy.rb
class PostPolicy
  attr_reader :user, :post

  def initialize(user, post)
    @user = user
    @post = post
  end

  def index?
    true
  end

  def show?
    post.published? || (user && (user.admin? || user == post.user))
  end

  def create?
    user.present? && user.can_post?
  end

  def update?
    user.present? && (user.admin? || user == post.user)
  end

  def destroy?
    user.present? && (user.admin? || user == post.user)
  end

  def publish?
    user.present? && (user.admin? || (user == post.user && user.can_post?))
  end

  class Scope
    def initialize(user, scope)
      @user = user
      @scope = scope
    end

    def resolve
      if user&.admin?
        scope.all
      elsif user.present?
        scope.where("published = ? OR user_id = ?", true, user.id)
      else
        scope.where(published: true)
      end
    end

    private

    attr_reader :user, :scope
  end
end

# Example usage in controller:
# def index
#   @posts = policy_scope(Post)
#   @posts = PostSearchQuery.new(params).call
# end

# def show
#   authorize @post
# end

💻 Ruby Metaprogramming ruby

🔴 complex ⭐⭐⭐⭐⭐

Advanced metaprogramming techniques, dynamic methods, and Ruby's magic methods

⏱️ 50 min 🏷️ ruby, metaprogramming, advanced, dynamic
Prerequisites: Advanced Ruby, Object-oriented Ruby, Ruby introspection
# Ruby Metaprogramming Examples

# 1. Dynamic method definition
class DynamicMethods
  def self.create_methods(*method_names)
    method_names.each do |name|
      define_method(name) do |arg|
        "Called method #{name} with argument: #{arg}"
      end
    end
  end
end

DynamicMethods.create_methods(:foo, :bar, :baz)

obj = DynamicMethods.new
puts obj.foo("hello")
puts obj.bar("world")
puts obj.baz("ruby")

# 2. method_missing for dynamic method calls
class DynamicAccessor
  def initialize(data = {})
    @data = data
  end

  def method_missing(method_name, *args, &block)
    if method_name.to_s.end_with?('=')
      # Setter method
      key = method_name.to_s.chomp('=').to_sym
      @data[key] = args.first
    else
      # Getter method
      key = method_name.to_sym
      if @data.key?(key)
        @data[key]
      else
        super
      end
    end
  end

  def respond_to_missing?(method_name, include_private = false)
    method_name.to_s.end_with?('=') || @data.key?(method_name.to_sym) || super
  end
end

accessor = DynamicAccessor.new
accessor.name = "John"
accessor.age = 30

puts accessor.name
puts accessor.age

# 3. Class-level metaprogramming
class ActiveRecord
  @@attributes = {}

  def self.attribute(name, type = :string)
    @@attributes[name] = type

    define_method(name) do
      @attributes[name]
    end

    define_method("#{name}=") do |value|
      @attributes[name] = cast_type(value, type)
    end
  end

  def self.attributes
    @@attributes
  end

  def initialize
    @attributes = {}
  end

  private

  def cast_type(value, type)
    case type
    when :string
      value.to_s
    when :integer
      value.to_i
    when :float
      value.to_f
    when :boolean
      !!value
    else
      value
    end
  end
end

class User < ActiveRecord
  attribute :name, :string
  attribute :age, :integer
  attribute :email, :string
  attribute :active, :boolean
end

user = User.new
user.name = "Alice"
user.age = 25
user.email = "[email protected]"
user.active = true

puts "Name: #{user.name}, Age: #{user.age}, Active: #{user.active}"

# 4. Module metaprogramming
class MacroModule
  def self.delegated_methods(*methods, to:)
    methods.each do |method|
      define_method(method) do |*args, &block|
        send(to).send(method, *args, &block)
      end
    end
  end
end

class Person
  MacroModule.delegated_methods :name, :email, to: :@contact_info

  def initialize
    @contact_info = OpenStruct.new
  end
end

require 'ostruct'

person = Person.new
person.name = "Bob"
person.email = "[email protected]"

puts person.name
puts person.email

# 5. Singleton methods and eigenclass
obj = Object.new

# Define singleton method
def obj.special_method
  "This is a singleton method!"
end

puts obj.special_method

# Define singleton methods using eigenclass
class << obj
  def another_special_method
    "Another singleton method!"
  end
end

puts obj.another_special_method

# 6. Class methods as singleton methods
class MyClass
  # This creates a singleton method on the class object
  def self.class_method
    "This is a class method"
  end

  # Using eigenclass for class methods
  class << self
    def another_class_method
      "Another class method"
    end
  end
end

puts MyClass.class_method
puts MyClass.another_class_method

# 7. Dynamic class creation
dynamic_class = Class.new do
  def initialize(name)
    @name = name
  end

  def greet
    "Hello, #{@name}!"
  end
end

instance = dynamic_class.new("Dynamic Class")
puts instance.greet

# 8. Method introspection
class IntrospectionExample
  def public_method; end

  protected

  def protected_method; end

  private

  def private_method; end

  def self.class_method; end
end

obj = IntrospectionExample.new

puts "Public methods: #{obj.public_methods(false).sort}"
puts "Protected methods: #{obj.protected_methods(false).sort}"
puts "Private methods: #{obj.private_methods(false).sort}"
puts "Class methods: #{IntrospectionExample.methods(false).sort}"

# Method information
if obj.respond_to?(:public_method)
  puts "Object responds to :public_method"
  puts "Method arity: #{obj.method(:public_method).arity}"
end

# 9. Using const_missing for dynamic constants
module DynamicConstants
  def self.const_missing(name)
    if name.to_s.start_with?('CONFIG_')
      # Load configuration dynamically
      config_key = name.to_s.sub('CONFIG_', '').downcase
      "Configuration for #{config_key}"
    else
      super
    end
  end
end

puts DynamicConstants::CONFIG_DATABASE
puts DynamicConstants::CONFIG_API

# 10. Advanced metaprogramming with modules
class AdvancedMetaprogramming
  def self.add_validator(attr_name, validator_proc)
    define_method("#{attr_name}_valid?") do
      value = instance_variable_get("@#{attr_name}")
      validator_proc.call(value)
    end
  end

  def self.attr_accessor_with_validation(attr_name, validator_proc)
    attr_writer attr_name

    define_method(attr_name) do
      instance_variable_get("@#{attr_name}")
    end

    add_validator(attr_name, validator_proc)
  end
end

class ValidatedUser
  extend AdvancedMetaprogramming

  attr_accessor_with_validation :email, ->(value) { value.match?(/A[^@s]+@[^@s]+z/) }
  attr_accessor_with_validation :age, ->(value) { value.is_a?(Integer) && value > 0 }

  def initialize
    @validations = {}
  end

  def valid?
    email_valid? && age_valid?
  end
end

user = ValidatedUser.new
user.email = "[email protected]"
user.age = 25

puts "User valid: #{user.valid?}"

# 11. Method chaining with self
class MethodChaining
  def initialize
    @operations = []
  end

  def add(value)
    @operations << [:add, value]
    self
  end

  def multiply(value)
    @operations << [:multiply, value]
    self
  end

  def result
    @operations.reduce(0) do |acc, (op, value)|
      case op
      when :add then acc + value
      when :multiply then acc * value
      end
    end
  end
end

result = MethodChaining.new.add(5).multiply(2).add(3).result
puts "Method chaining result: #{result}"

# 12. Using define_method with blocks
class DynamicBlockMethods
  def self.create_math_operation(name, operation)
    define_method(name) do |*args|
      args.reduce(&operation)
    end
  end
end

DynamicBlockMethods.create_math_operation(:sum, :+)
DynamicBlockMethods.create_math_operation(:product, :*)

math_ops = DynamicBlockMethods.new
puts "Sum of 1, 2, 3, 4: #{math_ops.sum(1, 2, 3, 4)}"
puts "Product of 2, 3, 4: #{math_ops.product(2, 3, 4)}"

# 13. Instance_eval and class_eval
class EvalExample
  def initialize
    @value = 10
  end

  def demonstrate_instance_eval
    instance_eval do
      puts "Inside instance_eval, @value = #{@value}"
      @value = 20
    end
    puts "After instance_eval, @value = #{@value}"
  end
end

class << EvalExample
  def demonstrate_class_eval
    class_eval do
      def class_level_method
        "I was added with class_eval"
      end
    end
  end
end

EvalExample.demonstrate_class_eval

obj = EvalExample.new
obj.demonstrate_instance_eval
puts obj.class_level_method

# 14. Method tracing with alias_method
class MethodTracer
  def self.trace_methods(*method_names)
    method_names.each do |method_name|
      original_method = instance_method(method_name)

      define_method(method_name) do |*args, &block|
        puts "Calling #{method_name} with args: #{args}"
        result = original_method.bind(self).call(*args, &block)
        puts "#{method_name} returned: #{result}"
        result
      end
    end
  end

  def add(a, b)
    a + b
  end

  def multiply(a, b)
    a * b
  end
end

MethodTracer.trace_methods(:add, :multiply)

tracer = MethodTracer.new
puts tracer.add(5, 3)
puts tracer.multiply(4, 6)