Rails Reflects for you

A Brief on use of Reflection in Ruby on Rails codebase

Nar Srini
Level Up Coding

--

Reflection is the ability of a program to introspect itself, providing insight into its own structure and behavior at runtime. It enables inquiring about classes, methods, and attributes and also supports dynamic code manipulation.

There are methods in Ruby classes and objects that allow inspection of specific areas of code. In Ruby on Rails, reflection is primarily achieved through methods provided by the ActiveRecord::Reflection module.

Photo by Marc-Olivier Jodoin on Unsplash

Below are some of the methods provided in Ruby to explore more about the objects in runtime.

class Story
end

obj = Story.new
obj.class # Story
obj.is_a? Story # true

class method tells you the class of any object in Ruby. is_a? method lets us know if the given object is the instance of the class in the argument. It returns true for any subclass of the Class passed. If you want to check the direct instance alone, use instance_of?.

obj = Story.new
obj.methods
obj.instance_variables

SomeModule.constants

Story.define_method(:clap) do |count|
puts "Successfully clapped #{count} times"
end

methods return an array of symbols representing the available methods for an object or class and instance_variables returns an array of instance variable names for an object. Moreover, with Ruby’s metaprogramming, you can create methods on the fly with define_method.

Among the arsenal of reflective tools, the source_location method shines as a spotlight. It is part of the Method class and reveals the file path and line number where a method is defined.

obj = Story.new
method = obj.method(:clap)
method.source_location # returns path to file with the method clap

When debugging, source_location can be invaluable for tracking down the origin of methods. It helps you quickly identify where a particular method is defined (if you’re not using an IDE like RubyMine), aiding in identifying issues and optimizing code.

ActiveRecord internally uses reflection to interact with database tables and relationships. Associations like has_many and belongs_to leverage reflection to establish connections.

Rails API documentation notes, “Reflection enables the ability to examine the associations and aggregations of Active Record classes and objects.”

ActiveRecord’s Reflection lets us access table relationships. Consider the association between Story and its Comments. It can be fetched like below,

class Story < ApplicationRecord
has_many :comments
end

# Using reflection to fetch associations
associations = Story.reflect_on_all_associations
associations.each do |association|
puts "Story associated with: #{association.name}"
end

Many testing frameworks rely on reflection to identify and run test methods. The names of test methods often follow a specific convention, enabling dynamic test discovery and execution.

Reflection in Ruby empowers developers to bend the language to their will. This poses many challenges in security & maintenance as the code gets complex to understand. Striking a balance between flexibility and readability is essential for a robust and maintainable codebase.

If you’re interested in reading similar articles, follow me on Medium.

--

--

Experienced Software Professional | OpenSource Enthusiast | Writing on Tech, Productivity🌟