Class: WscSdk::SchemaAttribute

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

Overview

A class to represent an attribute inside of a model's data schema.

Constant Summary collapse

TYPES =

A list of valid types for a schema attribute

[
  :string,
  :integer,
  :float,
  :boolean,
  :array,
  :hash,
  :datetime
]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, type, options = {}) ⇒ SchemaAttribute

Create a new schema attribute.

Parameters:

  • name (Symbol)

    The name of the attribute.

  • type (Symbol)

    The type of the attribute. The type must be in the list of WscSdk::SchemaAttribute::TYPES

  • options (Hash) (defaults to: {})

    A hash of options

Options Hash (options):

  • :default (Any, Proc, Symbol)

    The default value of the attribute. This value must match the assigned type of the attribute. The default value can be determined by a direct value, a Proc or a Symbol that represents a method in the model.

    If a Proc is provided it will be passed an instance of the model, which can be used to determine the default value for the attribute. The Proc should return a value that is the same type as the attribute.

    If a Symbol is provided, the Symbol will be checked against the model to determine if there is a method available that has the same name. If one exists, that method will be passed an instance of the model, which can be used to determine the default value for the attribute. The method should return a value that is the same type as the attribute. If no method is found that matches the symbol, the symbol itself is used as the default.

  • :required (Array, Proc, Symbol)

    Determines if the attribute is required.

    If a Proc is provided it will be passed an instance of the model, which can be used to determine if the value is required. The Proc should return a boolean value.

    If a Symbol is provided, the Symbol will be checked against the model to determine if there is a method available that has the same name. If one exists, that method will be called. The method should return a boolean value.

  • :validate (Array, Proc, Symbol)

    Determines if the attribute is valid.

    If a Proc is provided it will be passed an instance of the model, which can be used to determine if the value is valid. The Proc should return a string describing why the attribute is not valid, otherwise it should return nil.

    If a Symbol is provided, the Symbol will be checked against the model to determine if there is a method available that has the same name. If one exists, that method will be passed an instance of the model, which can be used to determine if the value is valid. The Proc should return a string describing why the attribute is not valid, otherwise it should return nil.

Raises:

  • (ArgumentError)

    If the type is not in the WscSdk::SchemaAttribute::TYPES list.



82
83
84
85
86
87
88
89
90
91
# File 'lib/wsc_sdk/schema_attribute.rb', line 82

def initialize(name, type, options={})
  raise ArgumentError.new("Invalid schema attribute type specified: #{type}") unless valid_type?(type)
  @name       = name.to_sym
  @type       = type
  @access     = options.fetch(:access,    :read_write)
  @default    = options.fetch(:default,   nil)
  @required   = options.fetch(:required,  false)
  @validate   = options.fetch(:validate,  nil)
  @as         = options.fetch(:as,        nil)
end

Instance Attribute Details

#accessObject (readonly)

Returns the value of attribute access



21
22
23
# File 'lib/wsc_sdk/schema_attribute.rb', line 21

def access
  @access
end

#asObject (readonly)

Returns the value of attribute as



21
22
23
# File 'lib/wsc_sdk/schema_attribute.rb', line 21

def as
  @as
end

#defaultObject (readonly)

Returns the value of attribute default



21
22
23
# File 'lib/wsc_sdk/schema_attribute.rb', line 21

def default
  @default
end

#nameObject (readonly)

Returns the value of attribute name



21
22
23
# File 'lib/wsc_sdk/schema_attribute.rb', line 21

def name
  @name
end

#requiredObject (readonly)

Returns the value of attribute required



21
22
23
# File 'lib/wsc_sdk/schema_attribute.rb', line 21

def required
  @required
end

#typeObject (readonly)

Returns the value of attribute type



21
22
23
# File 'lib/wsc_sdk/schema_attribute.rb', line 21

def type
  @type
end

#validateObject (readonly)

Returns the value of attribute validate



21
22
23
# File 'lib/wsc_sdk/schema_attribute.rb', line 21

def validate
  @validate
end

Instance Method Details

#attribute_nameSymbol

Returns the expected attribute name for the attribute. If the `as` value is returned, this is returned, otherwise the attributes `name` value is returned.

Returns:

  • (Symbol)

    The `as` or `name` value for the attribute



100
101
102
# File 'lib/wsc_sdk/schema_attribute.rb', line 100

def attribute_name
  (self.as || self.name).to_sym
end

#call_proc_or_symbol(proc_or_symbol, model) ⇒ Any

Call a Proc or Symbol against a model.

Parameters:

  • proc_or_symbol (Proc, Symbol)

    The Proc or Symbol to attempt to make a call against. If the value provided is Nil, or not a Proc or Symbol, then it is returned directly.

  • model (WscSdk::Model)

    The model to pass into the Proc or Symbol method if appropriate.

Returns:

  • (Any)

    The results of calling the Proc or Symbol or the value of proc_or_symbol if it isn't a Proc or Symbol.

Raises:

  • (ArgumentError)

    If the provided model does not have this attribute configured.



308
309
310
311
312
313
# File 'lib/wsc_sdk/schema_attribute.rb', line 308

def call_proc_or_symbol(proc_or_symbol, model)
  return proc_or_symbol if proc_or_symbol.nil?
  return proc_or_symbol.call(model) if proc_or_symbol.is_a?(Proc)
  return model.send(proc_or_symbol) if proc_or_symbol.is_a?(Symbol) and model.respond_to?(proc_or_symbol)
  return proc_or_symbol
end

#default_value(model) ⇒ Object

Returns the default value for the attribute

Parameters:



258
259
260
# File 'lib/wsc_sdk/schema_attribute.rb', line 258

def default_value(model)
  call_proc_or_symbol(default, model)
end

#read_access?(model) ⇒ Boolean

Determine if the attribute is readable according to the attribute configuration.

Parameters:

  • model (WscSdk::Model)

    The model that will determine the access level of the attribute.

Returns:

  • (Boolean)

    An indication if this attribute is readable by the model.

Raises:

  • (ArgumentError)

    If the provided model does not have this attribute configured.



116
117
118
119
120
121
122
# File 'lib/wsc_sdk/schema_attribute.rb', line 116

def read_access?(model)
  return true if access.nil?
  raise ::ArgumentError.new("The provided #{model.class.name} model does not have the #{self.name} attribute configured") unless model.has_attribute?(self.name)

  current_access = call_proc_or_symbol(access, model)
  [:read, :read_write].include?(current_access)
end

#required?(model) ⇒ Boolean

Determine if the attribute is required.

Parameters:

Returns:

  • (Boolean)

Raises:

  • (ArgumentError)

    If the provided model does not have this attribute configured.



284
285
286
287
288
289
290
# File 'lib/wsc_sdk/schema_attribute.rb', line 284

def required?(model)
  raise ArugumentError.new("The provided #{model.class.name} model does not have the #{self.name} attribute configured") unless model.has_attribute?(self.name)
  return required if required.is_a?(TrueClass) or required.is_a?(FalseClass)
  _required = call_proc_or_symbol(required, model)
  return false if _required.nil?
  _required
end

#transform_value(model, value) ⇒ Any

Converts an inbound value to the appropriate type.

Parameters:

  • model (WscSdk::Model)

    The model the value is for.

  • value (Any)

    The value to be transformed

Returns:

  • (Any)

    The transformed value



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/wsc_sdk/schema_attribute.rb', line 234

def transform_value(model, value)

  # Booleans are a special case because they are not represented by a single
  # class.
  return value.to_s.downcase.start_with?("y","t","1") if self.type == :boolean
  type_class        = type_to_class(self.type)
  transformed_value = value

  if type_class == Time
    current_timezone = Time.zone
    Time.zone = "UTC"
    transformed_value = Time.zone.parse(value) # => Tue, 23 Nov 2010 23:29:57 UTC +00:00
    Time.zone = current_timezone
  elsif type_class < WscSdk::Model and value.is_a?(Hash)
    transformed_value = type_class.new(model.endpoint, value)
  end
  transformed_value
end

#type_to_class(attribute_type) ⇒ Any

Converts the specified type to a class

Parameters:

  • attribute_type (Symbol)

    The type to check if it's valid.

Returns:

  • (Any)

    The class represented by the type, or nil if it's not a valid type.



210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/wsc_sdk/schema_attribute.rb', line 210

def type_to_class(attribute_type)
  # Booleans are a special case because they are not represented by a single
  # class.
  return String if attribute_type == :boolean
  return Time   if attribute_type == :datetime

  class_name = attribute_type.to_s.camelize
  unless TYPES.include?(attribute_type)
    class_name  = "WscSdk::Models::#{class_name}"
  end
  return (class_name.constantize)
end

#valid?(model) ⇒ String

Determine if a value is valid according to the attribute configuration.

Parameters:

Returns:

  • (String)

    A message of what's wrong if the value isn't valid, or nil if the value is valid.

Raises:

  • (ArgumentError)

    If the provided model does not have this attribute configured.



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/wsc_sdk/schema_attribute.rb', line 156

def valid?(model)
  return nil if validate.nil?

  raise ArugumentError.new("The provided #{model.class.name} model does not have the #{self.name} attribute configured") unless model.has_attribute?(self.name)
  value = model.attributes[self.name]

  message = nil

  if validate.is_a?(Array)
    valid   = validate.include?(value)
    model.add_error(name, "value must be one of the following: #{validate.join(", ")}")  unless valid
    return valid
  else
    return call_proc_or_symbol(validate, model)
  end

  # Calls should never get here.
  return true
end

#valid_model_type?(attribute_type) ⇒ Boolean

Determines if the specified type of the attribute matches a model.

Parameters:

  • attribute_type (Symbol)

    The type to check if it's valid.

Returns:

  • (Boolean)

    An indication that the type represents a model.



197
198
199
200
# File 'lib/wsc_sdk/schema_attribute.rb', line 197

def valid_model_type?(attribute_type)
  type_class = type_to_class(attribute_type)
  !type_class.nil?
end

#valid_type?(value) ⇒ Boolean

Determine if the provided value is of a valid type for the attribute.

Parameters:

  • value (Any)

    The value whose type will be compared to the attribute to determine if it is valid.

Returns:

  • (Boolean)

    An indication of whether or not the value's type matches the attribute type.



184
185
186
187
# File 'lib/wsc_sdk/schema_attribute.rb', line 184

def valid_type?(attribute_type)
  return true if TYPES.include?(attribute_type)
  return valid_model_type?(attribute_type)
end

#value_or_default(model) ⇒ Object

Return either the value from the model that is represented by the attribute, or the default value if the value is not assigned.

Parameters:

Raises:

  • (ArgumentError)

    If the provided model does not have this attribute configured.



271
272
273
274
# File 'lib/wsc_sdk/schema_attribute.rb', line 271

def value_or_default(model)
  raise ArugumentError.new("The provided #{model.class.name} model does not have the #{self.name} attribute configured") unless model.has_attribute?(self.name)
  model.attributes[self.name] || default_value(model)
end

#write_access?(model) ⇒ Boolean

Determine if the attribute is writable according to the attribute configuration.

Parameters:

  • model (WscSdk::Model)

    The model that will determine the access level of the attribute.

Returns:

  • (Boolean)

    An indication if this attribute is writable by the model.

Raises:

  • (ArgumentError)

    If the provided model does not have this attribute configured.



136
137
138
139
140
141
142
# File 'lib/wsc_sdk/schema_attribute.rb', line 136

def write_access?(model)
  return true if access.nil?
  raise ArugumentError.new("The provided #{model.class.name} model does not have the #{self.name} attribute configured") unless model.has_attribute?(self.name)

  current_access = call_proc_or_symbol(access, model)
  [:write, :read_write].include?(current_access)
end