scorpio 0.2.1 → 0.2.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4c02ae6ac0aa557b45883e8b1261ed89cf7f98d65a4c3a1224144aefba1abe0e
4
- data.tar.gz: 4961d26ac46421417cb40ca6929c7fca53007d773457860cb18006a1c38dbf49
3
+ metadata.gz: 772f6b246d831d6737118bed2f363358ac6b62dc055c3503f0a96e04d416985e
4
+ data.tar.gz: 20e4a1d856105a0c2f25d80fb252afd7b91bc35f71babc47f2d8ab3fbd46b2df
5
5
  SHA512:
6
- metadata.gz: e7c669c5820372b7abc5d8a881b37c73d681f051a70309b68f61574be58f5b1eac4d3928a4419aecb59a2c415c29eeb329cdd4327b60cb31604a9a5ad63ef855
7
- data.tar.gz: a435561553f6ab3c9fff2e122fbfed6d56126688f23ea7a7579a0999a281e66b046c224ff2ae398ffeb827e68f2a080867d364b0b8a3b6c586a4a8f01f41b854
6
+ metadata.gz: 8796f5f5227d3a70c374ae94b30cb6be1d7ad4dad71fb399c37c6c74e21117442d582a44d3417c828f156e42690d8f34a692bc3de5fcae4070431583ba1e5d88
7
+ data.tar.gz: 5d1b897306c6a43e16016e13f125e81d0408e3aca0c94009a2d8804aef0835b3a5cec144441de2979b51c9436e2fff016f0a1046e65d25dcc17471f60cda5869
@@ -1,3 +1,6 @@
1
+ # v0.2.2
2
+ - Scorpio::SchemaInstanceJSONCoder
3
+
1
4
  # v0.2.1
2
5
  - SchemaInstanceBase#parent, #parents
3
6
  - compatibility fix #as_json
@@ -91,4 +91,12 @@ module Scorpio
91
91
  autoload :ResourceBase, 'scorpio/resource_base'
92
92
  autoload :Schema, 'scorpio/schema'
93
93
  autoload :SchemaInstanceBase, 'scorpio/schema_instance_base'
94
+ autoload :SchemaClasses, 'scorpio/schema_instance_base'
95
+ autoload :ObjectJSONCoder, 'scorpio/schema_instance_json_coder'
96
+ autoload :StructJSONCoder, 'scorpio/struct_json_coder'
97
+ autoload :SchemaInstanceJSONCoder,'scorpio/schema_instance_json_coder'
98
+
99
+ def self.class_for_schema(*a, &b)
100
+ SchemaClasses.class_for_schema(*a, &b)
101
+ end
94
102
  end
@@ -87,6 +87,10 @@ module Scorpio
87
87
  end
88
88
  end
89
89
 
90
+ def schema_class
91
+ Scorpio.class_for_schema(self)
92
+ end
93
+
90
94
  def match_to_instance(instance)
91
95
  # matching oneOf is good here. one schema for one instance.
92
96
  # matching anyOf is okay. there could be more than one schema matched. it's often just one. if more
@@ -156,13 +156,14 @@ module Scorpio
156
156
 
157
157
  # this module is just a namespace for schema classes.
158
158
  module SchemaClasses
159
+ extend Memoize
159
160
  def self.[](schema_id)
160
161
  @classes_by_id[schema_id]
161
162
  end
162
163
  @classes_by_id = {}
163
164
  end
164
165
 
165
- def self.class_for_schema(schema_object)
166
+ def SchemaClasses.class_for_schema(schema_object)
166
167
  if schema_object.is_a?(Scorpio::Schema)
167
168
  schema__ = schema_object
168
169
  else
@@ -0,0 +1,83 @@
1
+ module Scorpio
2
+ # this is a ActiveRecord serialization class intended to store JSON in the
3
+ # database column and expose a ruby class once loaded on a model instance.
4
+ # this allows for better ruby idioms to access to properties, and definition
5
+ # of related methods on the loaded class.
6
+ #
7
+ # the first argument, `loaded_class`, is the class which will be used to
8
+ # instantiate the column data. properties of the loaded class will correspond
9
+ # to keys of the json object in the database.
10
+ #
11
+ # the column data may be either a single instance of the loaded class
12
+ # (represented as one json object) or an array of them (represented as a json
13
+ # array of json objects), indicated by the keyword argument `array`.
14
+ #
15
+ # the column behind the attribute may be an actual JSON column (postgres json
16
+ # or jsonb - hstore should work too if you only have string attributes) or a
17
+ # serialized string, indicated by the keyword argument `string`.
18
+ class ObjectJSONCoder
19
+ class Error < StandardError
20
+ end
21
+ class LoadError < Error
22
+ end
23
+ class DumpError < Error
24
+ end
25
+
26
+ def initialize(loaded_class, string: false, array: false, next_coder: nil)
27
+ @loaded_class = loaded_class
28
+ # this notes the order of the keys as they were in the json, used by dump_object to generate
29
+ # json that is equivalent to the json/jsonifiable that came in, so that AR's #changed_attributes
30
+ # can tell whether the attribute has been changed.
31
+ @loaded_class.send(:attr_accessor, :object_json_coder_keys_order)
32
+ @string = string
33
+ @array = array
34
+ @next_coder = next_coder
35
+ end
36
+
37
+ def load(column_data)
38
+ return nil if column_data.nil?
39
+ data = @string ? ::JSON.parse(column_data) : column_data
40
+ object = if @array
41
+ unless data.respond_to?(:to_ary)
42
+ raise TypeError, "expected array-like column data; got: #{data.class}: #{data.inspect}"
43
+ end
44
+ data.map { |el| load_object(el) }
45
+ else
46
+ load_object(data)
47
+ end
48
+ object = @next_coder.load(object) if @next_coder
49
+ object
50
+ end
51
+
52
+ def dump(object)
53
+ object = @next_coder.dump(object) if @next_coder
54
+ return nil if object.nil?
55
+ jsonifiable = begin
56
+ if @array
57
+ unless object.respond_to?(:to_ary)
58
+ raise DumpError, "expected array-like attribute; got: #{object.class}: #{object.inspect}"
59
+ end
60
+ object.map do |el|
61
+ dump_object(el)
62
+ end
63
+ else
64
+ dump_object(object)
65
+ end
66
+ end
67
+ @string ? ::JSON.generate(jsonifiable) : jsonifiable
68
+ end
69
+ end
70
+ # this is a ActiveRecord serialization class intended to store JSON in the
71
+ # database column and expose a given SchemaInstanceBase subclass once loaded
72
+ # on a model instance.
73
+ class SchemaInstanceJSONCoder < ObjectJSONCoder
74
+ private
75
+ def load_object(data)
76
+ @loaded_class.new(data)
77
+ end
78
+
79
+ def dump_object(object)
80
+ Scorpio::Typelike.as_json(object)
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,30 @@
1
+ module Scorpio
2
+ # this is a ActiveRecord serialization class intended to store JSON in the
3
+ # database column and expose a Struct subclass once loaded on a model instance.
4
+ class StructJSONCoder < ObjectJSONCoder
5
+ private
6
+ def load_object(data)
7
+ if data.is_a?(Hash)
8
+ good_keys = @loaded_class.members.map(&:to_s)
9
+ bad_keys = data.keys - good_keys
10
+ unless bad_keys.empty?
11
+ raise LoadError, "expected keys #{good_keys}; got unrecognized keys: #{bad_keys}"
12
+ end
13
+ instance = @loaded_class.new(*@loaded_class.members.map { |m| data[m.to_s] })
14
+ instance.object_json_coder_keys_order = data.keys
15
+ instance
16
+ else
17
+ raise LoadError, "expected instance(s) of #{Hash}; got: #{data.class}: #{data.inspect}"
18
+ end
19
+ end
20
+
21
+ def dump_object(object)
22
+ if object.is_a?(@loaded_class)
23
+ keys = (object.object_json_coder_keys_order || []) | @loaded_class.members.map(&:to_s)
24
+ keys.map { |member| {member => object[member]} }.inject({}, &:update)
25
+ else
26
+ raise TypeError, "expected instance(s) of #{@loaded_class}; got: #{object.class}: #{object.inspect}"
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,3 +1,3 @@
1
1
  module Scorpio
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scorpio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ethan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-08-04 00:00:00.000000000 Z
11
+ date: 2018-08-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -264,6 +264,8 @@ files:
264
264
  - lib/scorpio/schema.rb
265
265
  - lib/scorpio/schema_instance_base.rb
266
266
  - lib/scorpio/schema_instance_base/to_rb.rb
267
+ - lib/scorpio/schema_instance_json_coder.rb
268
+ - lib/scorpio/struct_json_coder.rb
267
269
  - lib/scorpio/typelike_modules.rb
268
270
  - lib/scorpio/util.rb
269
271
  - lib/scorpio/util/faraday/response_media_type.rb