Table of contents
1.
Introduction
2.
What is the use of AOP?
3.
How to Fix the Code using AOP?
4.
Frequently Asked Questions
4.1.
What is the use of AOP?
4.2.
What are some of the cross-cutting concerns?
4.3.
What are scattered codes?
4.4.
What are tangled codes?
4.5.
What is a joint-point model?
5.
Conclusion
Last Updated: Aug 13, 2025
Hard

Aspect-Oriented Programming in Ruby

Author Lucifer go
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

AOP (Aspect-Oriented Programming) is a technique for modularising cross-cutting concerns such as profiling, persistence, transactions, access control lists, and exception handling.
We can split an app into two parts, aspects and components. Components are parts we can easily encapsulate into code abstraction - methods, objects, or procedures. The application’s logic is an excellent example of a component. 

Aspects, on the other hand, cannot be isolated in code. Aspects cross-cut the application when we use some persistence (e.g., a database) or network communication (such as ZMQ sockets). Our components need to know about it.

What is the use of AOP?

Imagine an application that stores code snippets. You can start one of the use cases in the following manner:

class Snip_Use_Case
 attr_reader :repo, :log, :snippets
 def set_values(snippets_repository = SnippetsRepository.new, log = Logger.new)
   @repo = snippets_repository
   @log = log
   @snippets = []
 end
 def user_pushes(snip)
   snippets << snip
   repo.push(snip, 
                   success: self.method(:user_pushed),
                   failure: self.method(:user_not_pushed))
 end
 def user_pushed(snip)
   log.info "Pushed successfully: #{snip.name} (#{snip.language})"
 end
 def user_not_pushed(snip, push)
   snippets.delete(snip)
   log.error "Failed to push: #{push.error}."
 end
end
You can also try this code with Online Ruby Compiler
Run Code


Here we have a use case of inserting snippets into the application. To perform some SRP checks, we can see what the responsibility of this object is? It is an SRP-conformant object if it's responsible for pushing the snippets scenario.

A repository is an object which provides persistence to our snippets. Logger helps us track activity. The use case is a kind of a class that belongs to our logic. But it knows about aspects of our app - and we have to get rid of it to ease our pain!

How to Fix the Code using AOP?

The first step is to remove dependencies from our use case. We'll refactor the code to embrace aspect-oriented programming techniques. So, we delete constructor arguments, and our use case code after the change looks like this:

class SnippetsUseCase
 attr_reader :snippets
 def initialize
   @snippets = []
 end
 def user_pushes(snippet)
   snippets << snippet
 end
 def user_pushed(snippet); end
 def user_fails_to_push(snippet, pushing)
   snippets.delete(snippet)
 end
end
You can also try this code with Online Ruby Compiler
Run Code


We're maintaining the user_pushed method only to provide a join point for the solution. There will be many empty methods in code written in the AOP paradigm. Afterwards, we have to provide aspect code to link with our use case. So, we create the SnippetsUseCaseGlue class:

SnippetsUseCaseGlue class:
require 'aquarium'
class SnippetsUseCaseGlue
 attr_reader :usecase, :repo, :log
 include Aquarium::Aspects
 def initialize(usecase, repo, log)
   @usecase = usecase
   @repo = repo
   @log = log
 end
 Def inject!
   Aspect.new(:after, obj: usecase, calls_to: :user_pushes) do |j, obj, snip|
     repo.push(snip, 
                     success: usecase.method(:user_pushed),
                     failure: usecase.method(:user_push_failed))
   end
   Aspect.new(:after, obj: usecase, calls_to: :user_pushed) do |j, obj, snip|
     log.info("Successfully pushed: #{snip.name} (#{snip.language})")
   end
   Aspect.new(:after, obj: usecase, calls_to: :user_push_failed) do |j, obj, snip, pushing|
     log.error "Failed to push our snip: #{pushing.error}"
   end
 end
end
You can also try this code with Online Ruby Compiler
Run Code


Inside the advice block, there is a lot of info - including very general info about join point context (j), called obj, and all arguments of the invoked method.

class application
 def initialize
   @snippets = SnippetsUseCase.new
   @snippets_repository = SnippetsRepository.new
   @log = Logger.new
   @snippets_glue = SnippetsUseCaseGlue.new(@snippets, 
                                                 @snippets_repository, 
                                                 @log)
   @snippets_glue.inject!
   # rest of logic
 end
end
You can also try this code with Online Ruby Compiler
Run Code


Here the use case is a pure domain object without knowing it's connected with some persistence and logging layer. We've eliminated aspects of knowledge from this object.

Frequently Asked Questions

What is the use of AOP?

  • AOP provides a new level of abstraction.
  • It helps in the modularisation of behavior.
  • It provides a clear syntax for describing points for injecting the code into the application.

What are some of the cross-cutting concerns?

Some of the concerns are listed below: -

  • Profiling
  • Persistence
  • Transactions
  • Access Control Lists
  • Exception Handling

What are scattered codes?

Aspects are scattered because a function, like logging, may be used in various unrelated functions, potentially in separate systems, in several source languages, etc. That implies that altering logging may necessitate changing all impacted modules.

What are tangled codes?

Aspects tangle not just with one another but also with the primary purpose of the systems in which they are manifested. This implies that altering one issue necessitates comprehending all related concerns or having a method for determining how alterations will affect things.

What is a joint-point model?

The join point model is the foundation of AOP. It consists of two components: pointcuts, a system for choosing join points, and join points, the places at which an application is executed.

Conclusion

In this article, we have extensively discussed Aspect-Oriented Programming in Ruby and its implementation

You can also check our previous blogs on Ruby ProgrammingRuby Essentials, and Passing Arguments in Ruby. If you are eager to learn advanced front-end web development, Coding Ninjas is here with one of the best courses available, which you can find here.

Happy Learning!

Live masterclass