Class: JSONModelType
- Inherits:
-
Object
- Object
- JSONModelType
- Defined in:
- common/jsonmodel_type.rb
Overview
A common base class for all JSONModel classes
Constant Summary collapse
- ID_REGEXP =
The inverse of uri_for:
JSONModel(:archival_object).id_for("/repositories/123/archival_objects/500", :repo_id => 123)
might yield 500
IDs are either positive integers, or importer-provided logical IDs
/([0-9]+|import_[a-f0-9-]+)/
Instance Attribute Summary collapse
-
#uri ⇒ Object
Returns the value of attribute uri.
Class Method Summary collapse
-
.add_validation(name, level = :error, &block) ⇒ Object
Add a custom validation to this model type.
-
.from_hash(hash, raise_errors = true, trusted = false) ⇒ Object
Create an instance of this JSONModel from the data contained in ‘hash’.
-
.from_json(s, raise_errors = true) ⇒ Object
Create an instance of this JSONModel from a JSON string.
-
.id_for(uri, opts = {}, noerror = false) ⇒ Object
-
.inherited(child) ⇒ Object
If a JSONModel is extended, make its schema and record type class variables available on the subclass too.
-
.init(type, schema, mixins = []) ⇒ Object
Class instance variables store the bits specific to this model.
-
.record_type ⇒ Object
Return the type of this JSONModel class (a keyword like :archival_object).
-
.schema ⇒ Object
Return the JSON schema that defines this JSONModel class.
-
.schema_version ⇒ Object
Return the version number of this JSONModel’s schema.
-
.to_s ⇒ Object
-
.type_of(path) ⇒ Object
Return the type of the schema property defined by ‘path’.
-
.uri_and_remaining_options_for(id = nil, opts = {}) ⇒ Object
-
.uri_for(id = nil, opts = {}) ⇒ Object
Given a numeric internal ID and additional options produce a pair containing a URI reference.
Instance Method Summary collapse
-
#[](key) ⇒ Object
-
#[]=(key, val) ⇒ Object
-
#_always_valid! ⇒ Object
Set this object instance to always pass validation.
-
#_exceptions ⇒ Object
Validate the current JSONModel instance and return a list of exceptions produced.
-
#_warnings ⇒ Object
-
#add_error(attribute, message) ⇒ Object
-
#clear_errors ⇒ Object
-
#has_key?(key) ⇒ Boolean
-
#id ⇒ Object
Return the internal ID of this JSONModel.
-
#initialize(params = {}, trusted = false) ⇒ JSONModelType
constructor
A new instance of JSONModelType.
-
#inspect ⇒ Object
-
#instance_data ⇒ Object
-
#replace(params) ⇒ Object
Replace the values of the current JSONModel instance with the contents of ‘params’, validating before accepting the replacement.
-
#reset_from(another_jsonmodel) ⇒ Object
-
#to_hash(mode = nil) ⇒ Object
Produce a (possibly nested) hash from the values of this JSONModel.
-
#to_json(opts = {}) ⇒ Object
Produce a JSON string from the values of this JSONModel.
-
#to_s ⇒ Object
-
#update(params) ⇒ Object
Update the values of the current JSONModel instance with the contents of ‘params’, validating before accepting the update.
-
#update_concat(params) ⇒ Object
Update the values of the current JSONModel instance with the contents of ‘params’, validating before accepting the update.
Constructor Details
#initialize(params = {}, trusted = false) ⇒ JSONModelType
Returns a new instance of JSONModelType.
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'common/jsonmodel_type.rb', line 184 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
#uri ⇒ Object
Returns the value of attribute uri
201 202 203 |
# File 'common/jsonmodel_type.rb', line 201 def uri @uri end |
Class Method Details
.add_validation(name, level = :error, &block) ⇒ Object
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”], …]
62 63 64 65 66 67 68 69 |
# File 'common/jsonmodel_type.rb', line 62 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 |
.from_hash(hash, raise_errors = true, trusted = false) ⇒ Object
Create an instance of this JSONModel from the data contained in ‘hash’.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'common/jsonmodel_type.rb', line 73 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 |
.from_json(s, raise_errors = true) ⇒ Object
Create an instance of this JSONModel from a JSON string.
96 97 98 |
# File 'common/jsonmodel_type.rb', line 96 def self.from_json(s, raise_errors = true) self.from_hash(ASUtils.json_parse(s), raise_errors) end |
.id_for(uri, opts = {}, noerror = false) ⇒ Object
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'common/jsonmodel_type.rb', line 141 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_]+(\/|$)/, '/[^/ ]+\1') if uri =~ /#{pattern}\/#{ID_REGEXP}(\#.*)?$/ return id_to_int($1) elsif uri =~ /#{pattern.gsub(/\[\^\/ \]\+\/tree/, '')}#{ID_REGEXP}\/(tree|ordered_records)$/ # FIXME: gross hardcoding... return id_to_int($1) else if noerror nil else raise "Couldn't make an ID out of URI: #{uri}" end end end |
.inherited(child) ⇒ Object
If a JSONModel is extended, make its schema and record type class variables available on the subclass too.
28 29 30 31 |
# File 'common/jsonmodel_type.rb', line 28 def self.inherited(child) child.instance_variable_set(:@schema, schema) child.instance_variable_set(:@record_type, record_type) end |
.init(type, schema, mixins = []) ⇒ Object
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 |
.record_type ⇒ Object
Return the type of this JSONModel class (a keyword like :archival_object)
48 49 50 |
# File 'common/jsonmodel_type.rb', line 48 def self.record_type @record_type end |
.schema ⇒ Object
Return the JSON schema that defines this JSONModel class
35 36 37 |
# File 'common/jsonmodel_type.rb', line 35 def self.schema @schema end |
.schema_version ⇒ Object
Return the version number of this JSONModel’s schema
41 42 43 |
# File 'common/jsonmodel_type.rb', line 41 def self.schema_version self.schema['version'] end |
.to_s ⇒ Object
53 54 55 |
# File 'common/jsonmodel_type.rb', line 53 def self.to_s "JSONModel(:#{self.record_type})" end |
.type_of(path) ⇒ Object
Return the type of the schema property defined by ‘path’
For example, type_of(“names/items/type”) might return a JSONModel class
171 172 173 174 175 176 177 178 179 180 181 |
# File 'common/jsonmodel_type.rb', line 171 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 |
.uri_and_remaining_options_for(id = nil, opts = {}) ⇒ Object
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'common/jsonmodel_type.rb', line 101 def self.(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 += "/#{self.escape_uri_component(id.to_s)}" end self.substitute_parameters(uri, opts) end |
.uri_for(id = nil, opts = {}) ⇒ Object
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”
125 126 127 128 129 |
# File 'common/jsonmodel_type.rb', line 125 def self.uri_for(id = nil, opts = {}) result = self.(id, opts) result ? result[0] : nil end |
Instance Method Details
#[](key) ⇒ Object
213 214 215 |
# File 'common/jsonmodel_type.rb', line 213 def [](key) @data[key.to_s] end |
#[]=(key, val) ⇒ Object
218 219 220 221 |
# File 'common/jsonmodel_type.rb', line 218 def []=(key, val) @validated = false @data[key.to_s] = val end |
#_always_valid! ⇒ Object
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.
278 279 280 281 |
# File 'common/jsonmodel_type.rb', line 278 def _always_valid! @always_valid = true self end |
#_exceptions ⇒ Object
Validate the current JSONModel instance and return a list of exceptions produced.
232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'common/jsonmodel_type.rb', line 232 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 |
#_warnings ⇒ Object
264 265 266 267 268 269 270 271 272 |
# File 'common/jsonmodel_type.rb', line 264 def _warnings exceptions = self._exceptions if exceptions.has_key?(:warnings) exceptions[:warnings] else [] end end |
#add_error(attribute, message) ⇒ Object
255 256 257 258 259 260 261 |
# File 'common/jsonmodel_type.rb', line 255 def add_error(attribute, ) # reset validation @validated = false # call JSONModel::Client's version super end |
#clear_errors ⇒ Object
248 249 250 251 252 |
# File 'common/jsonmodel_type.rb', line 248 def clear_errors # reset validation @validated = false @errors = nil end |
#has_key?(key) ⇒ Boolean
224 225 226 |
# File 'common/jsonmodel_type.rb', line 224 def has_key?(key) @data.has_key?(key) end |
#id ⇒ Object
Return the internal ID of this JSONModel.
355 356 357 358 359 360 361 362 363 |
# File 'common/jsonmodel_type.rb', line 355 def id ref = JSONModel::parse_reference(self.uri) if ref ref[:id] else nil end end |
#inspect ⇒ Object
316 317 318 |
# File 'common/jsonmodel_type.rb', line 316 def inspect self.to_s end |
#instance_data ⇒ Object
208 209 210 |
# File 'common/jsonmodel_type.rb', line 208 def instance_data @instance_data end |
#replace(params) ⇒ Object
Replace the values of the current JSONModel instance with the contents of ‘params’, validating before accepting the replacement.
300 301 302 303 |
# File 'common/jsonmodel_type.rb', line 300 def replace(params) @validated = false set_data(params) end |
#reset_from(another_jsonmodel) ⇒ Object
306 307 308 |
# File 'common/jsonmodel_type.rb', line 306 def reset_from(another_jsonmodel) @data = another_jsonmodel.instance_eval { @data } end |
#to_hash(mode = nil) ⇒ Object
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.
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 |
# File 'common/jsonmodel_type.rb', line 324 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 |
#to_json(opts = {}) ⇒ Object
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.
349 350 351 |
# File 'common/jsonmodel_type.rb', line 349 def to_json(opts = {}) ASUtils.to_json(self.to_hash(opts[:mode]), opts.is_a?(Hash) ? opts.merge(:max_nesting => false) : {}) end |
#to_s ⇒ Object
311 312 313 |
# File 'common/jsonmodel_type.rb', line 311 def to_s "#<JSONModel(:#{self.class.record_type}) #{@data.inspect}>" end |
#update(params) ⇒ Object
Update the values of the current JSONModel instance with the contents of ‘params’, validating before accepting the update.
286 287 288 289 |
# File 'common/jsonmodel_type.rb', line 286 def update(params) @validated = false replace(ASUtils.deep_merge(@data, params)) end |
#update_concat(params) ⇒ Object
Update the values of the current JSONModel instance with the contents of ‘params’, validating before accepting the update.
293 294 295 296 |
# File 'common/jsonmodel_type.rb', line 293 def update_concat(params) @validated = false replace(ASUtils.deep_merge_concat(@data, params)) end |