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. You typically do not need to include this module in your classes. If you extend from Sequent::ValueObject, Sequent::Event or Sequent::Command you will get this functionality for free.

Example:

attrs name: String, age: Integer, born: Date

Currently Sequent supports the following types:

  • String

  • Integer

  • Boolean

  • Date

  • DateTime

  • Subclasses of Sequent::ValueObject

  • Lists defined as ‘array(String)`

  • BigDecimal

  • Sequent::Secret

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



123
124
125
# File 'lib/sequent/core/helpers/attribute_support.rb', line 123

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

Instance Method Details

#as_json(opts = {}) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/sequent/core/helpers/attribute_support.rb', line 141

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



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

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



177
178
179
180
181
182
# File 'lib/sequent/core/helpers/attribute_support.rb', line 177

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



154
155
156
# File 'lib/sequent/core/helpers/attribute_support.rb', line 154

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

#validation_errors(prefix = nil) ⇒ Object



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/sequent/core/helpers/attribute_support.rb', line 158

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