Class: ValueSemantics::Attribute

Inherits:
Object
  • Object
show all
Defined in:
lib/value_semantics.rb

Overview

Represents a single attribute of a value class

Constant Summary collapse

NO_DEFAULT_GENERATOR =
lambda do
  raise NoDefaultValue, "Attribute does not have a default value"
end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:, default_generator: NO_DEFAULT_GENERATOR, validator: Anything, coercer: nil) ⇒ Attribute

Returns a new instance of Attribute.



164
165
166
167
168
169
170
171
172
173
# File 'lib/value_semantics.rb', line 164

def initialize(name:,
               default_generator: NO_DEFAULT_GENERATOR,
               validator: Anything,
               coercer: nil)
  @name = name.to_sym
  @default_generator = default_generator
  @validator = validator
  @coercer = coercer
  freeze
end

Instance Attribute Details

#coercerObject (readonly)

Returns the value of attribute coercer.



162
163
164
# File 'lib/value_semantics.rb', line 162

def coercer
  @coercer
end

#default_generatorObject (readonly)

Returns the value of attribute default_generator.



162
163
164
# File 'lib/value_semantics.rb', line 162

def default_generator
  @default_generator
end

#nameObject (readonly)

Returns the value of attribute name.



162
163
164
# File 'lib/value_semantics.rb', line 162

def name
  @name
end

#validatorObject (readonly)

Returns the value of attribute validator.



162
163
164
# File 'lib/value_semantics.rb', line 162

def validator
  @validator
end

Class Method Details

.define(name, validator = Anything, default: NOT_SPECIFIED, default_generator: nil, coerce: nil) ⇒ Object



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/value_semantics.rb', line 175

def self.define(name,
                validator=Anything,
                default: NOT_SPECIFIED,
                default_generator: nil,
                coerce: nil)
  generator = begin
    if default_generator && !default.equal?(NOT_SPECIFIED)
      raise ArgumentError, "Attribute '#{name}' can not have both a :default and a :default_generator"
    elsif default_generator
      default_generator
    elsif !default.equal?(NOT_SPECIFIED)
      ->{ default }
    else
      NO_DEFAULT_GENERATOR
    end
  end

  new(
    name: name,
    validator: validator,
    default_generator: generator,
    coercer: coerce,
  )
end

Instance Method Details

#coerce(attr_value, klass) ⇒ Object



218
219
220
221
222
223
224
225
226
# File 'lib/value_semantics.rb', line 218

def coerce(attr_value, klass)
  return attr_value unless coercer # coercion not enabled

  if coercer.equal?(true)
    klass.public_send(coercion_method, attr_value)
  else
    coercer.call(attr_value)
  end
end

#coercion_methodObject



236
237
238
# File 'lib/value_semantics.rb', line 236

def coercion_method
  "coerce_#{name}"
end

#determine_from!(attr_hash, klass) ⇒ Object



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

def determine_from!(attr_hash, klass)
  raw_value = attr_hash.fetch(name) do
    if default_generator.equal?(NO_DEFAULT_GENERATOR)
      raise MissingAttributes, "Value missing for attribute '#{name}'"
    else
      default_generator.call
    end
  end

  coerced_value = coerce(raw_value, klass)

  if validate?(coerced_value)
    [name, coerced_value]
  else
    raise ArgumentError, "Value for attribute '#{name}' is not valid: #{coerced_value.inspect}"
  end
end

#instance_variableObject



232
233
234
# File 'lib/value_semantics.rb', line 232

def instance_variable
  '@' + name.to_s.chomp('!').chomp('?')
end

#validate?(value) ⇒ Boolean

Returns:

  • (Boolean)


228
229
230
# File 'lib/value_semantics.rb', line 228

def validate?(value)
  validator === value
end