Class: Windoo::BaseClasses::JSONObject

Inherits:
Object
  • Object
show all
Defined in:
lib/windoo/base_classes/json_object.rb

Overview

The base class for objects that are instantiated from a JSON Hash

Constant Summary collapse

PP_OMITTED_INST_VARS =

When using prettyprint, don’t spit out these instance variables.

%i[@init_data @container @softwareTitle].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**init_data) ⇒ JSONObject

Constructor



353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
# File 'lib/windoo/base_classes/json_object.rb', line 353

def initialize(**init_data)
  @init_data = init_data
  @init_data.each do |key, val|
    next unless self.class.json_attributes.key? key

    # The inst var is always a dup of the init_data, so that
    # changes to it don't affect the init data.
    ruby_val =
      if val && self.class.json_attributes[key][:to_ruby]
        Windoo::Converters.send self.class.json_attributes[key][:to_ruby], val.dup
      else
        val.dup
      end

    instance_variable_set "@#{key}", ruby_val
  end
end

Instance Attribute Details

#init_dataHash (readonly)

Returns The raw JSON data this object was instantiated with.

Returns:

  • (Hash)

    The raw JSON data this object was instantiated with



28
29
30
# File 'lib/windoo/base_classes/json_object.rb', line 28

def init_data
  @init_data
end

Class Method Details

.attribute_already_parsed?(attr_name) ⇒ Boolean

has one of our superclasses already parsed this attribute?

Returns:

  • (Boolean)


159
160
161
# File 'lib/windoo/base_classes/json_object.rb', line 159

def self.attribute_already_parsed?(attr_name)
  superclass.respond_to?(:json_attributes_parsed) && superclass.json_attributes_parsed.include?(attr_name)
end

.ident_keysArray<Symbol>

Returns the available identifier keys for objects that have them.

Returns:

  • (Array<Symbol>)

    the available identifier keys for objects that have them



68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/windoo/base_classes/json_object.rb', line 68

def self.ident_keys
  return @ident_keys if @ident_keys

  @ident_keys = []

  json_attributes.each do |key, deets|
    next unless deets[:identifier]

    @primary_id_key = key if deets[:identifier] == :primary
    @ident_keys << key
  end

  @ident_keys
end

.json_attributesHash{Symbol => Hash}

The merged JSON_ATTRIBUTES Hashes of any subclass of JSONObject including all ancestors up to JSONObject itself

Returns:

  • (Hash{Symbol => Hash})


48
49
50
51
52
53
54
55
# File 'lib/windoo/base_classes/json_object.rb', line 48

def self.json_attributes
  return {} if self == Windoo::BaseClasses::JSONObject
  return @json_attributes if @json_attributes

  @json_attributes = defined?(self::JSON_ATTRIBUTES) ? self::JSON_ATTRIBUTES.dup : {}
  @json_attributes.merge! superclass.json_attributes if superclass.respond_to?(:json_attributes)
  @json_attributes
end

.json_attributes_parsedObject

have we already parsed our JSON_ATTRIBUTES? If so, we shoudn’t do it again, and this can be used to check



129
130
131
# File 'lib/windoo/base_classes/json_object.rb', line 129

def self.json_attributes_parsed
  @json_attributes_parsed ||= []
end

.mutable?Boolean

by default, instances of subclasses are mutable as a whole (even if some attributes are readonly) To make them immutable, they should extend Windoo::Mixins::Immutable, which overrides this method

Returns:

  • (Boolean)


38
39
40
# File 'lib/windoo/base_classes/json_object.rb', line 38

def self.mutable?
  true
end

.parse_json_attributesObject

create getters and setters for subclasses of JSONObject based on their JSON_ATTRIBUTES Hash.

This method can’t be private, cuz we want to call it from a Zeitwerk callback when subclasses are loaded.



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/windoo/base_classes/json_object.rb', line 98

def self.parse_json_attributes
  # nothing to do if JSON_ATTRIBUTES is not defined for this class
  return unless defined? self::JSON_ATTRIBUTES

  self::JSON_ATTRIBUTES.each do |attr_name, attr_def|
    if attribute_already_parsed?(attr_name)
      Windoo.load_msg "Ancestor of #{self} has already parsed attribute #{attr_name}"
      next
    end

    Windoo.load_msg "Defining getters and setters for attribute '#{attr_name}' of #{self}"

    # there can be only one (primary ident)
    if attr_def[:identifier] == :primary
      raise Windoo::UnsupportedError, 'Two identifiers marked as :primary' if @got_primary

      @got_primary = true
    end

    # create getter unless the attr is write only
    define_getters attr_name, attr_def unless attr_def[:writeonly]

    # Don't crete setters for readonly attrs, or immutable objects
    define_setters attr_name, attr_def if mutable? && !attr_def[:readonly]

    json_attributes_parsed << attr_name
  end #  do |attr_name, attr_def|
end

.primary_id_keySymbol

Returns the key of the primary identifier, if there is one.

Returns:

  • (Symbol)

    the key of the primary identifier, if there is one



84
85
86
87
88
89
90
# File 'lib/windoo/base_classes/json_object.rb', line 84

def self.primary_id_key
  return @primary_id_key if @primary_id_key

  # this method sets @primary_id_key as it loops through json_attributes
  ident_keys
  @primary_id_key
end

.required_attributesArray<Symbol>

The attributes that are required to have values. These must be passed in when calling .create, and must exist in the instance when calling #save

Returns:

  • (Array<Symbol>)


63
64
65
# File 'lib/windoo/base_classes/json_object.rb', line 63

def self.required_attributes
  @required_attributes ||= json_attributes.select { |_key, deets| deets[:required] }.keys
end

.validate_attr(attr_name, value) ⇒ Object

Used by auto-generated setters and .create to validate new values.

returns a valid value or raises an exception

This method only validates single values. When called from multi-value setters, it is used for each value individually.

Parameters:

  • attr_name (Symbol)

    , a top-level key from OAPI_PROPERTIES for this class

  • value (Object)

    the value to validate for that attribute.

Returns:

  • (Object)

    The validated, possibly converted, value.

Raises:

  • (ArgumentError)


146
147
148
149
150
151
152
# File 'lib/windoo/base_classes/json_object.rb', line 146

def self.validate_attr(attr_name, value)
  attr_def = json_attributes[attr_name]
  raise ArgumentError, "Unknown attribute: #{attr_name} for #{self} objects" unless attr_def

  # validate the value based on the OAPI definition.
  Windoo::Validate.json_attr value, attr_def: attr_def, attr_name: attr_name
end

Instance Method Details

#pretty_print_instance_variablesArray

Only selected items are displayed with prettyprint otherwise its too much data in irb.

Returns:

  • (Array)

    the desired instance_variables



420
421
422
# File 'lib/windoo/base_classes/json_object.rb', line 420

def pretty_print_instance_variables
  instance_variables - PP_OMITTED_INST_VARS
end

#to_apiHash

Returns The data to be sent to the API, as a Hash to be converted to JSON before sending to the JPAPI

This is currently only used when creating new objects in the API. Updates happen immediately per attribute, from the setter methods, sending only the new value to the server.

It might also be used in the future to export JSON title definitions to import into other Title Servers.

Returns:

  • (Hash)

    The data to be sent to the API, as a Hash to be converted to JSON before sending to the JPAPI

    This is currently only used when creating new objects in the API. Updates happen immediately per attribute, from the setter methods, sending only the new value to the server.

    It might also be used in the future to export JSON title definitions to import into other Title Servers.



384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/windoo/base_classes/json_object.rb', line 384

def to_api
  api_data = {}
  attrs_for_save = self.class.json_attributes.keys

  attrs_for_save.each do |attr_name|
    attr_def = self.class.json_attributes[attr_name]
    next if attr_def[:do_not_send]

    raw_value = instance_variable_get "@#{attr_name}"

    api_data[attr_name] =
      if raw_value.nil?
        nil
      else
        single_to_api(raw_value, attr_def)
      end
  end
  api_data
end

#to_json(*_args) ⇒ String

This is only used when creating new objects in the API.

Updates happen immediately from the setter methods,
sending only the new value to the server.

Returns:

  • (String)

    the JSON to be sent to the API for this object



411
412
413
# File 'lib/windoo/base_classes/json_object.rb', line 411

def to_json(*_args)
  JSON.pretty_generate to_api
end