scorpio 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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