Class-level accessors in Ruby on Rails

Ruby on Rails offers a powerful and flexible way to manage attributes at both the instance and class levels. Understanding class-level accessors is crucial for designing modular and maintainable Rails applications. In this Answer, we’ll explore three key tools for handling class-level attributes: attr_accessor and cattr_accessor.

Instance-level accessor: attr_accessor

Before discussing class-level accessors, let’s briefly review attr_accessor, which is used to create instance-level accessors in Ruby.

Note: attr_accessor is a core feature of Ruby, not specific to Rails. It’s part of Ruby’s standard library in the Object class, the superclass of all Ruby classes.

Here’s a quick example:

# Using attr_accessor (instance-level)
class AppConfig
attr_accessor :api_key
def initialize(api_key)
@api_key = api_key
end
end
# Child class
class ModuleConfig < AppConfig
end
app_config = AppConfig.new('default_key')
puts app_config.api_key # Output: default_key
module_config = ModuleConfig.new('default_key')
puts module_config.api_key # Output: default_key
# Update instance-level attribute
app_config.api_key = 'new_key'
puts app_config.api_key # Output: new_key
puts module_config.api_key # Output: default_key

Code explanation

Let's go through the code above line by line.

  • Line 3: This attr_accessor :api_key attribute creates getter and setter methods for the api_key instance variable in the AppConfig class.

  • Lines 11–12: Instances of AppConfig and its child class ModuleConfig both inherit these getter and setter methods.

  • Lines 14–15: We create an app_config instance of AppConfig with 'default_key' value set to api_key to 'default_key'.

  • Lines 17–18: We create another module_config instance of ModuleConfig and sets api_key to 'default_key'.

  • Lines 21–22: We updated the api_key value of app_config instance to 'new_key'.

  • Line 24: However, the api_key value of module_config instance remains 'default_key' as it has its own separate api_key instance variable.

Class-level accessor: cattr_accessor

The cattr_accessor attribute extends the concept of accessors to the class level, allowing attributes to be shared among all instances of a class.

Note: cattr_accessor is specific to Rails and not a part of plain Ruby. It is a method provided by Active Support, which is a Ruby library that comes bundled with Rails.

Let's look at an example:

# Using cattr_accessor (class-level)
class AppConfig
cattr_accessor :api_key
end
# Child class
class ModuleConfig < AppConfig
end
AppConfig.api_key = 'default_key'
puts AppConfig.api_key # Output: default_key
puts ModuleConfig.api_key # Output: default_key
# Update class-level attribute
AppConfig.api_key = 'new_key'
puts AppConfig.api_key # Output: new_key
puts ModuleConfig.api_key # Output: new_key

Code explanation

Let's go through the code above line by line.

  • Line 2: This cattr_accessor :api_key attribute creates class-level getter and setter methods for the api_key attribute in the AppConfig class.

  • Lines 7–8: Instances of AppConfig and its child class ModuleConfig both inherit these class-level getter and setter methods.

  • Line 10: AppConfig.api_key = 'default_key' sets the class-level api_key for the AppConfig class to 'default_key'.

  • Line 11: puts AppConfig.api_key outputs 'default_key' as it retrieves the class-level api_key for AppConfig.

  • Line 12: puts ModuleConfig.api_key also outputs 'default_key' because ModuleConfig inherits the class-level api_key from AppConfig.

Note: We do not need reinstantiate the value for ModuleConfig when using cattr_accessor.

  • Line 15: AppConfig.api_key = 'new_key' updates the class-level api_key for the AppConfig class to 'new_key'.

  • Line 16: puts AppConfig.api_key now outputs 'new_key' as it retrieves the updated class-level api_key for AppConfig.

  • Line 18: puts ModuleConfig.api_key also outputs 'new_key' because ModuleConfig shares the updated class-level api_key from AppConfig.

Note: In the case of cattr_accessor, changes made to api_key are reflected across all instances of the AppConfig class. This is particularly useful for managing global settings, configuration options, or shared resources.

Use cases for class-level accessors

Class-level accessors are preferred over instance-level accessors in the following cases:

1. Configuration settings

Class-level accessors are ideal for managing configuration settings that need to be shared across the entire application. This could include API keys, default values, or global behavior.

2. Global state management

When there’s a need to maintain global state information that affects multiple components, class-level accessors offer a convenient way to manage and access shared data.

3. Shared resources

In scenarios where multiple instances of a class need to share a common resource, class-level accessors provide a central point for managing that resource.

Conclusion

Understanding class-level accessors is essential for effective Ruby on Rails development. Whether we choose the Rails-specific cattr_accessor or attr_accessor, these tools empower us to design flexible, modular, and maintainable applications. By leveraging class-level accessors, we can efficiently share and manage attributes across our classes, contributing to cleaner and more scalable code.

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved