metaprogramming/advanced/aspect_oriented.rb

tests/_examples/metaprogramming/advanced/aspect_oriented.rb in the metorex repository.

# Aspect-Oriented Programming: Cross-cutting concerns via wrapping
# Demonstrates: blocks, closures, dynamic method definition

# A simple "before/after" aspect wrapper using blocks
def with_logging(name, &block)
  puts ">> entering #{name}"
  result = block.call
  puts "<< exiting #{name} => #{result}"
  result
end

puts "=== Before/After Aspects ==="
with_logging("calculation") do
  2 + 3
end

with_logging("string op") do
  "hello".upcase
end

# Timing aspect
def with_timing(name, &block)
  puts "Starting #{name}..."
  result = block.call
  puts "Finished #{name}"
  result
end

puts ""
puts "=== Timing Aspect ==="
with_timing("data processing") do
  total = 0
  for i in 1..100
    total += i
  end
  total
end

# Retry aspect
def with_retry(attempts, &block)
  tries = 0
  success = false
  final_result = nil
  while tries < attempts && !success
    tries += 1
    puts "Attempt #{tries}..."
    result = block.call(tries)
    if result
      puts "Success on attempt #{tries}"
      success = true
      final_result = result
    end
  end
  if !success
    puts "All #{attempts} attempts failed"
  end
  final_result
end

puts ""
puts "=== Retry Aspect ==="
with_retry(3) do |attempt|
  r = false
  if attempt >= 2
    r = "got it"
  end
  r
end

Output:

=== Before/After Aspects ===
>> entering calculation
<< exiting calculation => 5
>> entering string op
<< exiting string op => HELLO

=== Timing Aspect ===
Starting data processing...
Finished data processing

=== Retry Aspect ===
Attempt 1...
Attempt 2...
Success on attempt 2