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


20
21
22
23
24
25
26
27
28
29
# File 'app/models/attributable.rb', line 20

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


51
52
53
54
55
# File 'app/models/attributable.rb', line 51

def association_value_pairs(details = association_details)
  details.each_with_object({}) do |attribute, hash|
    hash[attribute] = attribute.from(self)
  end
end

#attribute_details_for(*args) ⇒ Object


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

def attribute_details_for(*args)
  self.class.attribute_details_for(*args)
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


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

def attribute_value_pairs(details = attribute_details)
  details.each_with_object({}) do |attribute, hash|
    hash[attribute] = attribute.from(self)
  end
end

#field_infosObject


57
58
59
60
61
# File 'app/models/attributable.rb', line 57

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

#instance_defaultsObject


35
36
37
38
39
# File 'app/models/attributable.rb', line 35

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)

63
64
65
66
67
# File 'app/models/attributable.rb', line 63

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