Class: JSONModelType

Inherits:
Object
  • Object
show all
Defined in:
common/jsonmodel_type.rb

Overview

A common base class for all JSONModel classes

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (JSONModelType) initialize(params = {}, trusted = false)

Returns a new instance of JSONModelType



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'common/jsonmodel_type.rb', line 176

def initialize(params = {}, trusted = false)
  set_data(params)

  @uri ||= params['uri']

  # a hash to store transient instance data
  @instance_data = {}

  self.class.define_accessors(@data.keys)

  if trusted
    @validated = {}
    @cleaned_data = @data
  end
end

Instance Attribute Details

- (Object) uri

Returns the value of attribute uri



193
194
195
# File 'common/jsonmodel_type.rb', line 193

def uri
  @uri
end

Class Method Details

+ (Object) add_validation(name, level = :error, &block)

Add a custom validation to this model type.

The validation is a block that takes a hash of properties and returns an array of pairs like: [[“propertyname”, “the problem with it”], …]



54
55
56
57
58
59
60
61
# File 'common/jsonmodel_type.rb', line 54

def self.add_validation(name, level = :error, &block)
  raise "Validation name already taken: #{name}" if JSONModel.custom_validations[name]

  JSONModel.custom_validations[name] = block

  self.schema["validations"] ||= []
  self.schema["validations"] << [level, name]
end

+ (Object) from_hash(hash, raise_errors = true, trusted = false)

Create an instance of this JSONModel from the data contained in ‘hash’.



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'common/jsonmodel_type.rb', line 65

def self.from_hash(hash, raise_errors = true, trusted = false)
  hash["jsonmodel_type"] = self.record_type.to_s

  # If we're running in client mode, leave 'readonly' properties in place,
  # since they're intended for use by clients.  Otherwise, we drop them.
                                              drop_system_properties = !JSONModel.client_mode?

  if trusted
    # We got this data from a trusted source (such as another JSONModel
    # that had already been validated itself).  No need to double up
    self.new(hash, true)
  else
    cleaned = JSONSchemaUtils.drop_unknown_properties(hash, self.schema, drop_system_properties)
    cleaned = ASUtils.jsonmodels_to_hashes(cleaned)

    validate(cleaned, raise_errors)

    self.new(cleaned)
  end
end

+ (Object) from_json(s, raise_errors = true)

Create an instance of this JSONModel from a JSON string.



88
89
90
# File 'common/jsonmodel_type.rb', line 88

def self.from_json(s, raise_errors = true)
  self.from_hash(ASUtils.json_parse(s), raise_errors)
end

+ (Object) id_for(uri, opts = {}, noerror = false)

The inverse of uri_for:

JSONModel(:archival_object).id_for("/repositories/123/archival_objects/500", :repo_id => 123)

might yield 500



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'common/jsonmodel_type.rb', line 130

def self.id_for(uri, opts = {}, noerror = false)
  if not self.schema['uri']
    if noerror
      return nil
    else
      raise "Missing a URI definition for class #{self.class}"
    end
  end

  pattern = self.schema['uri']
  pattern = pattern.gsub(/\/:[a-zA-Z_]+\//, '/[^/ ]+/')

  # IDs are either positive integers, or importer-provided logical IDs
  id_regexp = /([0-9]+|import_[a-f0-9-]+)/

  if uri =~ /#{pattern}\/#{id_regexp}(\#.*)?$/
    return id_to_int($1)
  elsif uri =~ /#{pattern.gsub(/\[\^\/ \]\+\/tree/, '')}#{id_regexp}\/tree$/
    return id_to_int($1)
  else
    if noerror
      nil
    else
      raise "Couldn't make an ID out of URI: #{uri}"
    end
  end
end

+ (Object) init(type, schema, mixins = [])

Class instance variables store the bits specific to this model



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'common/jsonmodel_type.rb', line 5

def self.init(type, schema, mixins = [])
  @record_type = type
  @schema = schema

  # In client mode, mix in some extra convenience methods for querying the
  # ArchivesSpace backend service via HTTP.
  if JSONModel.client_mode?
    require_relative 'jsonmodel_client'
    include JSONModel::Client
  end


  define_accessors(schema['properties'].keys)


  mixins.each do |mixin|
    include(mixin)
  end
end

+ (Object) record_type

Return the type of this JSONModel class (a keyword like :archival_object)



40
41
42
# File 'common/jsonmodel_type.rb', line 40

def self.record_type
  find_ancestor_class_instance(:@record_type)
end

+ (Object) schema

Return the JSON schema that defines this JSONModel class



27
28
29
# File 'common/jsonmodel_type.rb', line 27

def self.schema
  find_ancestor_class_instance(:@schema)
end

+ (Object) schema_version

Return the version number of this JSONModel’s schema



33
34
35
# File 'common/jsonmodel_type.rb', line 33

def self.schema_version
  self.schema['version']
end

+ (Object) to_s



45
46
47
# File 'common/jsonmodel_type.rb', line 45

def self.to_s
  "JSONModel(:#{self.record_type})"
end

+ (Object) type_of(path)

Return the type of the schema property defined by ‘path’

For example, type_of(“names/items/type”) might return a JSONModel class



162
163
164
165
166
167
168
169
170
171
172
# File 'common/jsonmodel_type.rb', line 162

def self.type_of(path)
  type = JSONSchemaUtils.schema_path_lookup(self.schema, path)["type"]

  ref = JSONModel.parse_jsonmodel_ref(type)

  if ref
    JSONModel.JSONModel(ref.first)
  else
    Kernel.const_get(type.capitalize)
  end
end

+ (Object) uri_and_remaining_options_for(id = nil, opts = {})



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'common/jsonmodel_type.rb', line 93

def self.uri_and_remaining_options_for(id = nil, opts = {})
  # Some schemas (like name schemas) don't have a URI because they don't
  # need endpoints.  That's fine.
  if not self.schema['uri']
    return nil
  end

  uri = self.schema['uri']

  if not id.nil?
    uri += "/#{URI.escape(id.to_s)}"
  end

  self.substitute_parameters(uri, opts)
end

+ (Object) uri_for(id = nil, opts = {})

Given a numeric internal ID and additional options produce a pair containing a URI reference. For example:

JSONModel(:archival_object).uri_for(500, :repo_id => 123)

might yield “/repositories/123/archival_objects/500”



117
118
119
120
121
# File 'common/jsonmodel_type.rb', line 117

def self.uri_for(id = nil, opts = {})
  result = self.uri_and_remaining_options_for(id, opts)

  result ? result[0] : nil
end

Instance Method Details

- (Object) [](key)



205
206
207
# File 'common/jsonmodel_type.rb', line 205

def [](key)
  @data[key.to_s]
end

- (Object) []=(key, val)



210
211
212
213
# File 'common/jsonmodel_type.rb', line 210

def []=(key, val)
  @validated = false
  @data[key.to_s] = val
end

- (Object) _always_valid!

Set this object instance to always pass validation. Used so the frontend can create intentionally incomplete objects that will be filled out by the user.



269
270
271
272
# File 'common/jsonmodel_type.rb', line 269

def _always_valid!
  @always_valid = true
  self
end

- (Object) _exceptions

Validate the current JSONModel instance and return a list of exceptions produced.



223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'common/jsonmodel_type.rb', line 223

def _exceptions
  return @validated if @validated && @errors.nil?

  exceptions = {}
  if not @always_valid
    exceptions = self.validate(@data, false)
  end

  if @errors
    exceptions[:errors] = (exceptions[:errors] or {}).merge(@errors)
  end

  exceptions
end

- (Object) _warnings



255
256
257
258
259
260
261
262
263
# File 'common/jsonmodel_type.rb', line 255

def _warnings
  exceptions = self._exceptions

  if exceptions.has_key?(:warnings)
    exceptions[:warnings]
  else
    []
  end
end

- (Object) add_error(attribute, message)



246
247
248
249
250
251
252
# File 'common/jsonmodel_type.rb', line 246

def add_error(attribute, message)
  # reset validation
  @validated = false

  # call JSONModel::Client's version
  super
end

- (Object) clear_errors



239
240
241
242
243
# File 'common/jsonmodel_type.rb', line 239

def clear_errors
  # reset validation
  @validated = false
  @errors = nil
end

- (Boolean) has_key?(key)

Returns:

  • (Boolean)


216
217
218
# File 'common/jsonmodel_type.rb', line 216

def has_key?(key)
  @data.has_key?(key)
end

- (Object) id

Return the internal ID of this JSONModel.



340
341
342
343
344
345
346
347
348
# File 'common/jsonmodel_type.rb', line 340

def id
  ref = JSONModel::parse_reference(self.uri)

  if ref
    ref[:id]
  else
    nil
  end
end

- (Object) inspect



301
302
303
# File 'common/jsonmodel_type.rb', line 301

def inspect
  self.to_s
end

- (Object) instance_data



200
201
202
# File 'common/jsonmodel_type.rb', line 200

def instance_data
  @instance_data
end

- (Object) replace(params)

Replace the values of the current JSONModel instance with the contents of ‘params’, validating before accepting the replacement.



285
286
287
288
# File 'common/jsonmodel_type.rb', line 285

def replace(params)
  @validated = false
  set_data(params)
end

- (Object) reset_from(another_jsonmodel)



291
292
293
# File 'common/jsonmodel_type.rb', line 291

def reset_from(another_jsonmodel)
  @data = another_jsonmodel.instance_eval { @data }
end

- (Object) to_hash(mode = nil)

Produce a (possibly nested) hash from the values of this JSONModel. Any values that don’t appear in the JSON schema will not appear in the result.



309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'common/jsonmodel_type.rb', line 309

def to_hash(mode = nil)
  mode = (mode || :validated)

  raise "Invalid .to_hash mode: #{mode}" unless [:trusted, :validated, :raw].include?(mode)

  return @data if mode == :raw

  if @validated and @cleaned_data
    return @cleaned_data
  end

  cleaned = JSONSchemaUtils.drop_unknown_properties(@data, self.class.schema)
  cleaned = ASUtils.jsonmodels_to_hashes(cleaned)

  if mode == :validated
    @validated = false
    self.validate(cleaned)
  end

  @cleaned_data = cleaned
end

- (Object) to_json(opts = {})

Produce a JSON string from the values of this JSONModel. Any values that don’t appear in the JSON schema will not appear in the result.



334
335
336
# File 'common/jsonmodel_type.rb', line 334

def to_json(opts = {})
  ASUtils.to_json(self.to_hash(opts[:mode]), opts.is_a?(Hash) ? opts.merge(:max_nesting => false) : {})
end

- (Object) to_s



296
297
298
# File 'common/jsonmodel_type.rb', line 296

def to_s
  "#<JSONModel(:#{self.class.record_type}) #{@data.inspect}>"
end

- (Object) update(params)

Update the values of the current JSONModel instance with the contents of ‘params’, validating before accepting the update.



277
278
279
280
# File 'common/jsonmodel_type.rb', line 277

def update(params)
  @validated = false
  replace(ASUtils.deep_merge(@data, params))
end