Module: Attributable

Included in:
Metadata::Base
Defined in:
app/models/attributable.rb,
app/models/attributable/attribute.rb,
app/models/attributable/association.rb,
app/models/attributable/custom_validator.rb

Overview

This module can be included into ActiveRecord::Base classes to get the ability to specify the attributes that are present. You can think of this as metadata being stored about the column in the table: it’s default value, whether it’s required, if it has a set of values that are acceptable, or if it’s numeric. Use the class method ‘attribute’ to define your attribute:

Attribute information can be retrieved from the class through ‘attributes’, and each one of the attributes you define can be converted to a FieldInfo instance using ‘to_field_info’.

Examples:

Some example attributes

custom_attribute(:foo, :required => true)
custom_attribute(:bar, :default => 'Something', :in => [ 'Something', 'Other thing' ])
custom_attribute(:numeric, :integer => true)

Defined Under Namespace

Modules: ClassMethods Classes: Association, Attribute, CustomValidator

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



16
17
18
19
20
21
22
23
24
25
# File 'app/models/attributable.rb', line 16

def self.included(base)
  base.extend(ClassMethods)
  base.class_eval do
    # NOTE: Do not use 'attributes' because that's an ActiveRecord internal name
    class_attribute :attribute_details, instance_writer: false
    self.attribute_details = []
    class_attribute :association_details, instance_writer: false
    self.association_details = []
  end
end

Instance Method Details

#association_value_pairs(details = association_details) ⇒ Object

If we’ve eager loaded metadata, then we may be using the base class, rather than subclass specific forms. We can override the details used here



45
46
47
# File 'app/models/attributable.rb', line 45

def association_value_pairs(details = association_details)
  details.index_with { |attribute| attribute.from(self) }
end

#attribute_details_forObject



27
28
29
# File 'app/models/attributable.rb', line 27

def attribute_details_for(*)
  self.class.attribute_details_for(*)
end

#attribute_value_pairs(details = attribute_details) ⇒ Object

If we’ve eager loaded metadata, then we may be using the base class, rather than subclass specific forms. We can override the details used here



39
40
41
# File 'app/models/attributable.rb', line 39

def attribute_value_pairs(details = attribute_details)
  details.index_with { |attribute| attribute.from(self) }
end

#field_infosObject



49
50
51
# File 'app/models/attributable.rb', line 49

def field_infos
  attribute_details.map { |detail| detail.to_field_info(self) }
end

#instance_defaultsObject



31
32
33
34
35
# File 'app/models/attributable.rb', line 31

def instance_defaults
  attribute_details.each_with_object({}) do |attribute, hash|
    hash[attribute.name] = attribute.default_from(self) if attribute.validator?
  end
end

#required?(field) ⇒ Boolean

Returns:

  • (Boolean)


53
54
55
56
57
58
# File 'app/models/attributable.rb', line 53

def required?(field)
  field_details =
    attribute_details.detect { |attribute| attribute.name == field } ||
      association_details.detect { |association| field == :"#{association.name}_id" }
  field_details.try(:required?)
end