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



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

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

Instance Method Details

#as_json(opts = {}) ⇒ Object



181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/sequent/core/helpers/attribute_support.rb', line 181

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

#attributesObject



168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/sequent/core/helpers/attribute_support.rb', line 168

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

#ensure_known_attributes(attrs) ⇒ Object



217
218
219
220
221
222
223
224
# File 'lib/sequent/core/helpers/attribute_support.rb', line 217

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)
  if unknowns.any?
    fail UnknownAttributeError, "#{self.class.name} does not specify attrs: #{unknowns.join(', ')}"
  end
end

#update(changes) ⇒ Object



194
195
196
# File 'lib/sequent/core/helpers/attribute_support.rb', line 194

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

#validation_errors(prefix = nil) ⇒ Object



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/sequent/core/helpers/attribute_support.rb', line 198

def validation_errors(prefix = nil)
  result = errors.to_hash
  self.class.types.each do |field|
    value = instance_variable_get("@#{field[0]}")
    if value.respond_to? :validation_errors
      value.validation_errors.each { |k, v| result["#{field[0]}_#{k}".to_sym] = v }
    elsif field[1].instance_of?(ArrayWithType) && 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]}_#{index}_#{k}".to_sym] = v
        end
      end
    end
  end
  prefix ? HashWithIndifferentAccess[result.map { |k, v| ["#{prefix}_#{k}", v] }] : result
end