Dynamic Ruby defaults for ActiveRecord attributes. These defaults are evaluated just in time, allowing dynamic defaults to depend on attributes that are assigned after initialization, or on other dynamic defaults.
Example:
class User < ActiveRecord::Base attr_default :middle_name, '' attr_default :guid, lambda { GuidGenerator.new } attr_default :managed, lambda { organization.managed? } belongs_to :organization ... end
-
Ruby >= 2.6.1
-
Rails >= 4.2, < 7
Add this line to your application’s Gemfile:
gem 'attr_default'
And then execute:
$ bundle
Or install it yourself as:
$ gem install attr_default
require 'attr_default'
This makes the attr_default
macro available to all objects derived fromActiveRecord::Base.
The attr_default
macro takes 2 arguments:
- attr_name
-
The name of the attribute, given as a symbol or string.
- default
-
The default value to use, either as a simple value or a Proc. If a Proc, attr_default will call it in the context of the object. This makes it convenient for dynamic defaults to be computed based on other attributes or associations.
attr_default
can be used for persistent or non-persistent attributes.
Defaults are lazy computed, just in time, whenever the first of these happens:
-
The attribute is read.
-
The object’s before_validation callback is called.
-
The object’s before_save callback is called.
This allows dynamic defaults to depend on other attributes that may be assigned after the initializer, and even other dynamic defaults. For example:
class User < ActiveRecord::Base attr_default :first_name, 'First' attr_default :last_name, 'Last' attr_default :name_addr, lambda { "#{full_name} <#{email}>" } def full_name [first_name, middle_name, last_name].select { |name| !name.blank? } * ' ' end end user1 = User.create :email => '[email protected]', :first_name => 'Joe' user1.name_addr # => "Joe Last <[email protected]>" user2 = User.create :email => '[email protected]' user2.last_name = 'Doe' user2.name_addr # => "First Doe <[email protected]>"
With Hobofields, defaults can be set using the :ruby_default
option:
class User < ActiveRecord::Base fields do first_name :string, :ruby_default => 'First' last_name :string, :ruby_default => 'Last' email :string name_addr :string, :ruby_default => lambda { "#{full_name} <#{email}>" } ... end def full_name [first_name, middle_name, last_name].select { |name| name unless name.blank? } * ' ' end end
The :default
option controls the default in SQL, unless a Ruby Proc is given in which case it is treated as :ruby_default
.
Dynamic defaults work with clone
, following the same timing given above.
-
Fork it
-
Create your feature branch (‘git checkout -b my-new-feature`)
-
Commit your changes (‘git commit -am ’Added some feature’‘)
-
Push to the branch (‘git push origin my-new-feature`)
-
Create new Pull Request