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



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

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

Instance Method Details

#as_json(opts = {}) ⇒ Object



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

def as_json(opts = {})
  hash = HashWithIndifferentAccess.new
  self.class.types.each_key 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



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

def attributes
  hash = HashWithIndifferentAccess.new
  self.class.types.each_key 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



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

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



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

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

#validation_errors(prefix = nil) ⇒ Object



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

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