aspace_client 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/lib/aspace_client.rb +15 -0
  3. data/lib/aspace_client/archivesspace_json_schema.rb +210 -0
  4. data/lib/aspace_client/asutils.rb +142 -0
  5. data/lib/aspace_client/client_enum_source.rb +30 -0
  6. data/lib/aspace_client/exceptions.rb +15 -0
  7. data/lib/aspace_client/helpers.rb +0 -0
  8. data/lib/aspace_client/json_schema_concurrency_fix.rb +52 -0
  9. data/lib/aspace_client/json_schema_utils.rb +414 -0
  10. data/lib/aspace_client/jsonmodel.rb +342 -0
  11. data/lib/aspace_client/jsonmodel_client.rb +528 -0
  12. data/lib/aspace_client/jsonmodel_i18n_mixin.rb +77 -0
  13. data/lib/aspace_client/jsonmodel_type.rb +478 -0
  14. data/lib/aspace_client/memoryleak.rb +59 -0
  15. data/lib/aspace_client/schemas/abstract_agent.rb +51 -0
  16. data/lib/aspace_client/schemas/abstract_agent_relationship.rb +12 -0
  17. data/lib/aspace_client/schemas/abstract_archival_object.rb +96 -0
  18. data/lib/aspace_client/schemas/abstract_classification.rb +44 -0
  19. data/lib/aspace_client/schemas/abstract_name.rb +23 -0
  20. data/lib/aspace_client/schemas/abstract_note.rb +13 -0
  21. data/lib/aspace_client/schemas/accession.rb +174 -0
  22. data/lib/aspace_client/schemas/accession_parts_relationship.rb +31 -0
  23. data/lib/aspace_client/schemas/accession_sibling_relationship.rb +31 -0
  24. data/lib/aspace_client/schemas/active_edits.rb +23 -0
  25. data/lib/aspace_client/schemas/advanced_query.rb +12 -0
  26. data/lib/aspace_client/schemas/agent_contact.rb +25 -0
  27. data/lib/aspace_client/schemas/agent_corporate_entity.rb +32 -0
  28. data/lib/aspace_client/schemas/agent_family.rb +29 -0
  29. data/lib/aspace_client/schemas/agent_person.rb +31 -0
  30. data/lib/aspace_client/schemas/agent_relationship_associative.rb +28 -0
  31. data/lib/aspace_client/schemas/agent_relationship_earlierlater.rb +28 -0
  32. data/lib/aspace_client/schemas/agent_relationship_parentchild.rb +26 -0
  33. data/lib/aspace_client/schemas/agent_relationship_subordinatesuperior.rb +26 -0
  34. data/lib/aspace_client/schemas/agent_software.rb +22 -0
  35. data/lib/aspace_client/schemas/archival_object.rb +60 -0
  36. data/lib/aspace_client/schemas/archival_record_children.rb +15 -0
  37. data/lib/aspace_client/schemas/boolean_field_query.rb +13 -0
  38. data/lib/aspace_client/schemas/boolean_query.rb +13 -0
  39. data/lib/aspace_client/schemas/classification.rb +10 -0
  40. data/lib/aspace_client/schemas/classification_term.rb +38 -0
  41. data/lib/aspace_client/schemas/classification_tree.rb +17 -0
  42. data/lib/aspace_client/schemas/collection_management.rb +27 -0
  43. data/lib/aspace_client/schemas/container.rb +29 -0
  44. data/lib/aspace_client/schemas/container_location.rb +19 -0
  45. data/lib/aspace_client/schemas/date.rb +19 -0
  46. data/lib/aspace_client/schemas/date_field_query.rb +14 -0
  47. data/lib/aspace_client/schemas/deaccession.rb +20 -0
  48. data/lib/aspace_client/schemas/defaults.rb +104 -0
  49. data/lib/aspace_client/schemas/digital_object.rb +64 -0
  50. data/lib/aspace_client/schemas/digital_object_component.rb +53 -0
  51. data/lib/aspace_client/schemas/digital_object_tree.rb +19 -0
  52. data/lib/aspace_client/schemas/digital_record_children.rb +15 -0
  53. data/lib/aspace_client/schemas/enumeration.rb +29 -0
  54. data/lib/aspace_client/schemas/enumeration_migration.rb +14 -0
  55. data/lib/aspace_client/schemas/event.rb +88 -0
  56. data/lib/aspace_client/schemas/extent.rb +17 -0
  57. data/lib/aspace_client/schemas/external_document.rb +12 -0
  58. data/lib/aspace_client/schemas/external_id.rb +11 -0
  59. data/lib/aspace_client/schemas/field_query.rb +15 -0
  60. data/lib/aspace_client/schemas/file_version.rb +26 -0
  61. data/lib/aspace_client/schemas/group.rb +17 -0
  62. data/lib/aspace_client/schemas/instance.rb +27 -0
  63. data/lib/aspace_client/schemas/job.rb +57 -0
  64. data/lib/aspace_client/schemas/location.rb +36 -0
  65. data/lib/aspace_client/schemas/location_batch.rb +45 -0
  66. data/lib/aspace_client/schemas/merge_request.rb +48 -0
  67. data/lib/aspace_client/schemas/name_corporate_entity.rb +15 -0
  68. data/lib/aspace_client/schemas/name_family.rb +13 -0
  69. data/lib/aspace_client/schemas/name_form.rb +15 -0
  70. data/lib/aspace_client/schemas/name_person.rb +19 -0
  71. data/lib/aspace_client/schemas/name_software.rb +14 -0
  72. data/lib/aspace_client/schemas/note_abstract.rb +17 -0
  73. data/lib/aspace_client/schemas/note_bibliography.rb +29 -0
  74. data/lib/aspace_client/schemas/note_bioghist.rb +22 -0
  75. data/lib/aspace_client/schemas/note_chronology.rb +28 -0
  76. data/lib/aspace_client/schemas/note_citation.rb +32 -0
  77. data/lib/aspace_client/schemas/note_definedlist.rb +25 -0
  78. data/lib/aspace_client/schemas/note_digital_object.rb +23 -0
  79. data/lib/aspace_client/schemas/note_index.rb +29 -0
  80. data/lib/aspace_client/schemas/note_index_item.rb +25 -0
  81. data/lib/aspace_client/schemas/note_multipart.rb +25 -0
  82. data/lib/aspace_client/schemas/note_orderedlist.rb +27 -0
  83. data/lib/aspace_client/schemas/note_outline.rb +20 -0
  84. data/lib/aspace_client/schemas/note_outline_level.rb +21 -0
  85. data/lib/aspace_client/schemas/note_singlepart.rb +24 -0
  86. data/lib/aspace_client/schemas/note_text.rb +17 -0
  87. data/lib/aspace_client/schemas/permission.rb +15 -0
  88. data/lib/aspace_client/schemas/preference.rb +16 -0
  89. data/lib/aspace_client/schemas/record_tree.rb +17 -0
  90. data/lib/aspace_client/schemas/repository.rb +32 -0
  91. data/lib/aspace_client/schemas/repository_with_agent.rb +14 -0
  92. data/lib/aspace_client/schemas/resource.rb +112 -0
  93. data/lib/aspace_client/schemas/resource_tree.rb +20 -0
  94. data/lib/aspace_client/schemas/rights_statement.rb +35 -0
  95. data/lib/aspace_client/schemas/subject.rb +30 -0
  96. data/lib/aspace_client/schemas/term.rb +16 -0
  97. data/lib/aspace_client/schemas/user.rb +56 -0
  98. data/lib/aspace_client/schemas/user_defined.rb +42 -0
  99. data/lib/aspace_client/schemas/vocabulary.rb +15 -0
  100. data/lib/aspace_client/validations.rb +434 -0
  101. data/lib/aspace_client/validator_cache.rb +47 -0
  102. data/lib/aspace_client/version.rb +3 -0
  103. metadata +244 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ac953db47d3758e451a44a90dbdf570bad1c6d48
4
+ data.tar.gz: ee196ef429407e4f59cea5190865fd08a70b9c44
5
+ SHA512:
6
+ metadata.gz: 191e45a120e291974d55e0000073acfd460e6162847d3c891c7b9422e98532b5ad8f8f7861410d4906191bb4d37fbbfe4833c05c5c45328f957152e8880cc1ec
7
+ data.tar.gz: 34076a7f7f5fb3d8c8d64ac578c66bde17f1c5887da65462af9b76855c94c5ed70bafcf145c4c7b58db9bd121d9fa6ed0015039cf8000705e00b7c5343a8426c
@@ -0,0 +1,15 @@
1
+ $: << "#{File.dirname(__FILE__)}" unless $:.include? File.dirname(__FILE__)
2
+
3
+ require "aspace_client/jsonmodel"
4
+ require "aspace_client/asutils"
5
+ require "aspace_client/memoryleak"
6
+ require "aspace_client/client_enum_source"
7
+ require "aspace_client/jsonmodel_i18n_mixin"
8
+ require 'aspace_client/jsonmodel_client'
9
+ require 'aspace_client/archivesspace_json_schema.rb'
10
+
11
+ include JSONModel
12
+
13
+ module AspaceClient
14
+
15
+ end
@@ -0,0 +1,210 @@
1
+ require 'date'
2
+
3
+ # Add a new 'ifmissing' attribute which emits either an error or warning
4
+ # depending on its value.
5
+ class IfMissingAttribute < JSON::Schema::PropertiesAttribute
6
+
7
+ def self.validate(current_schema, data, fragments, validator, options = {})
8
+ super
9
+
10
+ if data.is_a?(Hash)
11
+ current_schema.schema['properties'].each do |property, property_schema|
12
+ if (property_schema['ifmissing'] && !data.has_key?(property))
13
+ message = nil
14
+
15
+ if property_schema['ifmissing'] == 'error'
16
+ message = "ERROR: The property '#{build_fragment(fragments)}' did not contain a required property of '#{property}'"
17
+ elsif property_schema['ifmissing'] == 'warn'
18
+ message = "WARNING: The property '#{build_fragment(fragments)}' did not contain a required property of '#{property}'"
19
+ end
20
+
21
+ if message
22
+ validation_error(message, fragments, current_schema, self, options[:record_errors])
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+
32
+ class ArchivesSpaceTypeAttribute < JSON::Schema::TypeAttribute
33
+ extend JSONModel
34
+
35
+
36
+ # This reuse business is a bit of a pain. The story here: JRuby backtraces
37
+ # are relatively expensive to create (relative to MRI Ruby), and JSON Schema
38
+ # validation is using exceptions as control flow here (sigh). During imports,
39
+ # these validation error are hit a *lot*, and calculating a backtrace every
40
+ # time is expensive.
41
+ #
42
+ # So, we recycle.
43
+ def self.validation_error_for(expected_type, fragments, current_schema)
44
+ Thread.current[:json_validation_cached_errors] ||= {}
45
+ if !Thread.current[:json_validation_cached_errors][expected_type]
46
+ msg = "ERROR: Schema type mismatch. Expected type: #{expected_type}"
47
+ Thread.current[:json_validation_cached_errors][expected_type] = JSON::Schema::ValidationError.new(msg, fragments, self, current_schema)
48
+ end
49
+
50
+ Thread.current[:json_validation_cached_errors][expected_type].fragments = fragments
51
+ Thread.current[:json_validation_cached_errors][expected_type]
52
+ end
53
+
54
+
55
+ def self.validate(current_schema, data, fragments, validator, options = {})
56
+ types = current_schema.schema['type']
57
+
58
+ if types == 'date'
59
+ begin
60
+ Date.parse(data)
61
+ return
62
+ rescue
63
+ validation_error("The property '#{build_fragment(fragments)}' was not " +
64
+ "a well-formed date (value: #{data})",
65
+ fragments, current_schema, self, options[:record_errors])
66
+ end
67
+ end
68
+
69
+
70
+ if types == 'object' && data.is_a?(Hash) && data.has_key?('ref') && current_schema.schema['subtype'] != 'ref'
71
+ # Provide a helpful warning about potentially missing subtype definitions
72
+ $stderr.puts("WARNING: Schema #{current_schema.inspect} appears to be missing a subtype definition of 'ref'")
73
+ end
74
+
75
+ # A bit crazy, sorry. If we're being asked to validate a hash whose
76
+ # jsonmodel_type is marked against a different JSONModel schema, we're
77
+ # wasting our time. Just stop straight away.
78
+ if (data.is_a?(Hash) && data["jsonmodel_type"]) &&
79
+ (current_schema.schema.is_a?(Hash) &&
80
+ "#{current_schema.schema["type"]}".include?("JSONModel") &&
81
+ !"#{current_schema.schema["type"]}".include?("JSONModel(:#{data['jsonmodel_type']})"))
82
+
83
+ raise validation_error_for(data['jsonmodel_type'], fragments, current_schema)
84
+ end
85
+
86
+ if JSONModel.parse_jsonmodel_ref(types)
87
+ (model, qualifier) = JSONModel.parse_jsonmodel_ref(types)
88
+
89
+ if qualifier == 'uri' || (qualifier == 'uri_or_object' && data.is_a?(String))
90
+ if JSONModel(model).id_for(data, {}, true).nil?
91
+ validation_error("The property '#{build_fragment(fragments)}' of type " +
92
+ "#{data.class} did not match the following type: #{types} in schema",
93
+ fragments, current_schema, self, options[:record_errors])
94
+ end
95
+
96
+ elsif qualifier == 'uri_or_object' || qualifier == 'object'
97
+ if data.is_a?(Hash)
98
+ data["jsonmodel_type"] ||= model.to_s
99
+
100
+ ValidatorCache.with_validator_for(JSONModel(model), data) do |subvalidator|
101
+ # Urk. Validate the subrecord but pass in the fragments of the point
102
+ # we're at in the parent record.
103
+ subvalidator.instance_eval do
104
+ @base_schema.validate(@data, fragments, @validation_options)
105
+ end
106
+ end
107
+
108
+ else
109
+ validation_error("The property '#{build_fragment(fragments)}' of type " +
110
+ "#{data.class} did not match the following type: #{types} in schema",
111
+ fragments, current_schema, self, options[:record_errors])
112
+ end
113
+ end
114
+ else
115
+ super
116
+ end
117
+ end
118
+ end
119
+
120
+
121
+ class ArchivesSpaceSubTypeAttribute < JSON::Schema::TypeAttribute
122
+
123
+ def self.validate(current_schema, data, fragments, validator, options = {})
124
+ if data.is_a?(Hash) && !data.has_key?('ref')
125
+ message = "ERROR: The property '#{build_fragment(fragments)}' did not contain a required property of 'ref'"
126
+ validation_error(message, fragments, current_schema, self, options[:record_errors])
127
+ end
128
+ end
129
+
130
+ end
131
+
132
+ class ArchivesSpaceReadOnlyDynamicEnumAttribute < JSON::Schema::TypeAttribute; end
133
+
134
+ class ArchivesSpaceDynamicEnumAttribute < JSON::Schema::TypeAttribute
135
+
136
+ def self.validate(current_schema, data, fragments, validator, options = {})
137
+ enum_name = current_schema.schema['dynamic_enum']
138
+
139
+ if !JSONModel.init_args[:enum_source].valid?(enum_name, data)
140
+ possible_values = JSONModel.init_args[:enum_source].values_for(enum_name)
141
+ message = ("The property '#{build_fragment(fragments)}' value #{data.inspect} " +
142
+ "did not match one of the following configurable values: #{possible_values.join(', ')}")
143
+
144
+ if JSONModel.init_args[:enum_source].editable?(enum_name)
145
+ klass = self
146
+ else
147
+ klass = ArchivesSpaceReadOnlyDynamicEnumAttribute
148
+ end
149
+
150
+ validation_error(message, fragments, current_schema, klass, options[:record_errors])
151
+ end
152
+ end
153
+
154
+ end
155
+
156
+
157
+ class ArchivesSpaceSchema < JSON::Schema::Validator
158
+ def initialize
159
+ super
160
+ extend_schema_definition("http://json-schema.org/draft-03/schema#")
161
+ @attributes["type"] = ArchivesSpaceTypeAttribute
162
+ @attributes["subtype"] = ArchivesSpaceSubTypeAttribute
163
+ @attributes["dynamic_enum"] = ArchivesSpaceDynamicEnumAttribute
164
+ @attributes["properties"] = IfMissingAttribute
165
+ @uri = URI.parse("http://www.archivesspace.org/archivesspace.json")
166
+ end
167
+
168
+
169
+ def already_failed?(fragments)
170
+ JSON::Validator.validation_errors.any? {|error|
171
+ error.fragments == fragments
172
+ }
173
+ end
174
+
175
+
176
+ def validate(current_schema, data, fragments, options = {})
177
+ super
178
+
179
+ # Run any custom validations if we've made it this far with no errors
180
+ if !already_failed?(fragments) && current_schema.schema.has_key?("validations")
181
+ current_schema.schema["validations"].each do |level_and_name|
182
+ level, name = level_and_name
183
+
184
+ errors = JSONModel::custom_validations[name].call(data)
185
+
186
+ errors.each do |error|
187
+ error_string = nil
188
+
189
+ if error.is_a? Symbol
190
+ error_string = "Validation error code: #{error}"
191
+ else
192
+ field, msg = error
193
+ prefix = level == :warning ? "Warning generated for" : "Validation failed for"
194
+ error_string = "#{prefix} '#{field}': #{msg}"
195
+
196
+ end
197
+
198
+ err = JSON::Schema::ValidationError.new(error_string,
199
+ fragments,
200
+ "custom_validation",
201
+ current_schema)
202
+
203
+ JSON::Validator.validation_error(err)
204
+ end
205
+ end
206
+ end
207
+ end
208
+
209
+ JSON::Validator.register_validator(self.new)
210
+ end
@@ -0,0 +1,142 @@
1
+ require 'json'
2
+ require 'tmpdir'
3
+ require 'tempfile'
4
+
5
+ module ASUtils
6
+
7
+ def self.keys_as_strings(hash)
8
+ result = {}
9
+
10
+ hash.each do |key, value|
11
+ result[key.to_s] = value.is_a?(Date) ? value.to_s : value
12
+ end
13
+
14
+ result
15
+ end
16
+
17
+
18
+ def self.as_array(thing)
19
+ return [] if thing.nil?
20
+ thing.kind_of?(Array) ? thing : [thing]
21
+ end
22
+
23
+
24
+ def self.jsonmodels_to_hashes(elt)
25
+
26
+ if elt.is_a?(JSONModelType)
27
+ elt = elt.to_hash(:raw)
28
+ end
29
+
30
+ if elt.is_a?(Hash)
31
+ Hash[elt.map {|k, v| [k, self.jsonmodels_to_hashes(v)]}]
32
+ elsif elt.is_a?(Array)
33
+ elt.map {|v| self.jsonmodels_to_hashes(v)}
34
+ else
35
+ elt
36
+ end
37
+ end
38
+
39
+
40
+ def self.json_parse(s)
41
+ JSON.parse(s, :max_nesting => false, :create_additions => false)
42
+ end
43
+
44
+
45
+
46
+ def self.to_json(obj, opts = {})
47
+ if obj.respond_to?(:jsonize)
48
+ obj.jsonize(opts.merge(:max_nesting => false))
49
+ else
50
+ obj.to_json(opts.merge(:max_nesting => false))
51
+ end
52
+ end
53
+
54
+
55
+ def self.find_base_directory(root = nil)
56
+ [ File.join(*[File.dirname(__FILE__), "..", root].compact)].find {|dir|
57
+ Dir.exists?(dir)
58
+ }
59
+ end
60
+
61
+
62
+ def self.find_local_directories(base = nil, *plugins)
63
+ base_directory = self.find_base_directory
64
+ Array(plugins).map { |plugin| File.join(*[base_directory, "plugins", plugin, base].compact) }
65
+ end
66
+
67
+
68
+ def self.find_locales_directories(base = nil)
69
+ [File.join(*[self.find_base_directory("common"), "locales", base].compact)]
70
+ end
71
+
72
+
73
+ def self.extract_nested_strings(coll)
74
+ if coll.is_a?(Hash)
75
+ coll.values.map {|v| self.extract_nested_strings(v)}.flatten.compact
76
+ elsif coll.is_a?(Array)
77
+ coll.map {|v| self.extract_nested_strings(v)}.flatten.compact
78
+ else
79
+ coll
80
+ end
81
+ end
82
+
83
+ def self.dump_diagnostics(exception = nil)
84
+ diagnostics = self.get_diagnostics( exception )
85
+ tmp = File.join(Dir.tmpdir, "aspaue_diagnostic_#{Time.now.to_i}.txt")
86
+ File.open(tmp, "w") do |fh|
87
+ fh.write(JSON.pretty_generate(diagnostics))
88
+ end
89
+
90
+ msg = <<EOF
91
+ A trace file has been written to the following location: #{tmp}
92
+
93
+ This file contains information that will assist developers in diagnosing
94
+ problems with your ArchivesSpace installation. Please review the file's
95
+ contents for sensitive information (such as passwords) that you might not
96
+ want to share.
97
+ EOF
98
+
99
+ $stderr.puts("=" * 72)
100
+ $stderr.puts(msg)
101
+ $stderr.puts("=" * 72)
102
+
103
+ raise exception if exception
104
+ end
105
+
106
+
107
+ # Recursively overlays hash2 onto hash 1
108
+ def self.deep_merge(hash1, hash2)
109
+ target = hash1.dup
110
+ hash2.keys.each do |key|
111
+ if hash2[key].is_a? Hash and hash1[key].is_a? Hash
112
+ target[key] = self.deep_merge(target[key], hash2[key])
113
+ next
114
+ end
115
+ target[key] = hash2[key]
116
+ end
117
+ target
118
+ end
119
+
120
+
121
+ def self.load_plugin_gems(context)
122
+ ASUtils.find_local_directories.each do |plugin|
123
+ gemfile = File.join(plugin, 'Gemfile')
124
+ if File.exists?(gemfile)
125
+ context.instance_eval(File.read(gemfile))
126
+ end
127
+ end
128
+ end
129
+
130
+
131
+ # Borrowed from: file activesupport/lib/active_support/core_ext/array/wrap.rb, line 36
132
+ def self.wrap(object)
133
+ if object.nil?
134
+ []
135
+ elsif object.respond_to?(:to_ary)
136
+ object.to_ary || [object]
137
+ else
138
+ [object]
139
+ end
140
+ end
141
+
142
+ end
@@ -0,0 +1,30 @@
1
+ require "aspace_client/jsonmodel"
2
+ require "aspace_client/memoryleak"
3
+
4
+ class ClientEnumSource
5
+
6
+ def initialize
7
+ MemoryLeak::Resources.define(:enumerations, proc {
8
+ JSONModel::Client::EnumSource.fetch_enumerations
9
+ }, 300)
10
+ end
11
+
12
+
13
+ def valid?(name, value)
14
+ values_for(name).include?(value)
15
+ end
16
+
17
+ def editable?(name)
18
+ MemoryLeak::Resources.get(:enumerations).fetch(name).editable?
19
+ end
20
+
21
+
22
+ def values_for(name)
23
+ MemoryLeak::Resources.get(:enumerations).fetch(name)
24
+ end
25
+
26
+ def default_value_for(name)
27
+ MemoryLeak::Resources.get(:enumerations)[:defaults].fetch(name)
28
+ end
29
+
30
+ end
@@ -0,0 +1,15 @@
1
+ class AccessDeniedException < StandardError
2
+ end
3
+
4
+
5
+ class ConflictException < StandardError
6
+ attr_reader :conflicts
7
+
8
+ def initialize(conflicts)
9
+ @conflicts = conflicts
10
+ super
11
+ end
12
+ end
13
+
14
+ class RecordNotFound < StandardError
15
+ end
File without changes
@@ -0,0 +1,52 @@
1
+ # Monkey patch against json-schema 1.0.12 to work around
2
+ # https://github.com/hoxworth/json-schema/issues/24
3
+
4
+
5
+ module JSON
6
+ class Validator
7
+
8
+ # Run a simple true/false validation of data against a schema
9
+ def validate()
10
+ begin
11
+ Validator.clear_errors
12
+ @base_schema.validate(@data,[],@validation_options)
13
+ Validator.clear_cache
14
+ if @options[:errors_as_objects]
15
+ self.class.validation_errors.map{|e| e.to_hash}
16
+ else
17
+ self.class.validation_errors.map{|e| e.to_string}
18
+ end
19
+ rescue JSON::Schema::ValidationError
20
+ Validator.clear_cache
21
+ raise $!
22
+ end
23
+ end
24
+
25
+ class << self
26
+ def clear_errors
27
+ Thread.current[:jsonschema_errors] = []
28
+ end
29
+
30
+ def validation_error(error)
31
+ Thread.current[:jsonschema_errors] << error
32
+ end
33
+
34
+ def validation_errors
35
+ Thread.current[:jsonschema_errors] or []
36
+ end
37
+ end
38
+
39
+
40
+ # Plus one bonus: don't use MultiJson here.
41
+ def serialize schema
42
+ # if defined?(MultiJson)
43
+ # MultiJson.respond_to?(:dump) ? MultiJson.dump(schema) : MultiJson.encode(schema)
44
+ # else
45
+ # @@serializer.call(schema)
46
+ # end
47
+
48
+ ASUtils.to_json(schema)
49
+ end
50
+
51
+ end
52
+ end