Module: Sequent::Core::Helpers::AttributeSupport

Included in:
BaseCommand, Event, ValueObject
Defined in:
lib/sequent/core/helpers/attribute_support.rb

Overview

Provides functionality for defining attributes with their types

Since our Commands and ValueObjects are not backed by a database like e.g. rails we can not infer their types. We need the types to be able to parse from and to json. We could have stored te type information in the json, but we didn’t.

You typically do not need to include this module in your classes. If you extend from Sequent::Core::ValueObject, Sequent::Core::Event or Sequent::Core::BaseCommand you will get this functionality for free.

Defined Under Namespace

Modules: ClassMethods Classes: UnknownAttributeError

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(host_class) ⇒ Object

extend host class with class methods when we’re included



109
110
111
# File 'lib/sequent/core/helpers/attribute_support.rb', line 109

def self.included(host_class)
  host_class.extend(ClassMethods)
end

Instance Method Details

#as_json(opts = {}) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/sequent/core/helpers/attribute_support.rb', line 127

def as_json(opts = {})
  hash = HashWithIndifferentAccess.new
  self.class.types.each do |name, _|
    value = self.instance_variable_get("@#{name}")
    hash[name] = if value.respond_to?(:as_json)
                   value.as_json(opts)
                 else
                   value
                 end
  end
  hash
end

#attributesObject



114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/sequent/core/helpers/attribute_support.rb', line 114

def attributes
  hash = HashWithIndifferentAccess.new
  self.class.types.each do |name, _|
    value = self.instance_variable_get("@#{name}")
    hash[name] = if value.respond_to?(:attributes)
                   value.attributes
                 else
                   value
                 end
  end
  hash
end

#ensure_known_attributes(attrs) ⇒ Object



163
164
165
166
167
168
# File 'lib/sequent/core/helpers/attribute_support.rb', line 163

def ensure_known_attributes(attrs)
  return unless Sequent.configuration.strict_check_attributes_on_apply_events

  unknowns = attrs.keys.map(&:to_s) - self.class.types.keys.map(&:to_s)
  raise UnknownAttributeError.new("#{self.class.name} does not specify attrs: #{unknowns.join(", ")}") if unknowns.any?
end

#update(changes) ⇒ Object



140
141
142
# File 'lib/sequent/core/helpers/attribute_support.rb', line 140

def update(changes)
  self.class.new(attributes.merge(changes))
end

#validation_errors(prefix = nil) ⇒ Object



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/sequent/core/helpers/attribute_support.rb', line 144

def validation_errors(prefix = nil)
  result = errors.to_hash
  self.class.types.each do |field|
    value = self.instance_variable_get("@#{field[0]}")
    if value.respond_to? :validation_errors
      value.validation_errors.each { |k, v| result["#{field[0].to_s}_#{k.to_s}".to_sym] = v }
    elsif field[1].class == ArrayWithType and value.present?
      value
        .select { |val| val.respond_to?(:validation_errors) }
        .each_with_index do |val, index|
        val.validation_errors.each do |k, v|
          result["#{field[0].to_s}_#{index}_#{k.to_s}".to_sym] = v
        end
      end
    end
  end
  prefix ? HashWithIndifferentAccess[result.map { |k, v| ["#{prefix}_#{k}", v] }] : result
end