This blog is part of our Rails 5.2 series.

When DHH introduced support for specifying a default value for class_attribute, Genadi Samokovarov brought to notice that the module and class attribute accessor macros also support specifying a default value but using a block and not with a default option.

To have consistent and symmetrical behaviour across all the attribute extensions, it was decided to support specifying a default value using default option for all the module and class attribute macros as well.

mattr_accessor , mattr_reader and mattr_writer macros generate getter and setter methods at the module level.

Similarly, cattr_accessor , cattr_reader , and cattr_writer macros generate getter and setter methods at the class level.

Before Rails 5.2

Before Rails 5.2, this is how we would set the default values for the module and class attribute accessor macros.

module ActivityLoggerHelper mattr_accessor :colorize_logs mattr_writer :log_ip { false } self . colorize_logs = true end class ActivityLogger include ActivityLoggerHelper cattr_writer :logger { Logger . new ( STDOUT ) } cattr_accessor :level cattr_accessor :settings cattr_reader :pid { Process . pid } @@level = Logger :: DEBUG self . settings = {} end

After Rails 5.2

We can still set a default value of a module or class attribute accessor by providing a block. In this pull request, support for specifying a default value using a new default option has been introduced.

So instead of

cattr_writer :logger { Logger . new ( STDOUT ) }

or

cattr_writer :logger self . logger = Logger . new ( STDOUT )

or

cattr_writer :logger @@logger = Logger . new ( STDOUT )

we can now easily write

cattr_writer :logger , default: Logger . new ( STDOUT )

Same applies to the other attribute accessor macros like mattr_accessor , mattr_reader , mattr_writer , cattr_accessor , and cattr_reader .

Note that, the old way of specifying a default value using the block syntax will work but will not be documented anywhere.

Also, note that if we try to set the default value by both ways i.e. by providing a block as well as by specifying a default option; the value provided by default option will always take the precedence.

mattr_accessor ( :colorize_logs , default: true ) { false }

Here, @@colorize_logs would be set with true as per the above precedence rule.

Here is a test which verifies this behavior.

Finally, here is simplified version using the new default option.