jsonize 0.1.1 → 0.2.0

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 (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/jsonize/version.rb +1 -1
  3. data/lib/jsonize.rb +104 -72
  4. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bdb7d503cc06ab7caf4bad0cfb1f7162fab524a76d7cfc5d24c695f58231f5ae
4
- data.tar.gz: 5d4ac6b92ab4f1893d7cd23609460e9f2009bd646f1df4f2878a5fa4db758465
3
+ metadata.gz: d3227e59ca0f4826ae7a108ba9ab99419e2441fa7ca4182cd288000fe5caaa5b
4
+ data.tar.gz: 5d79a0a28100a90b628b96820d250a10fa9b70806203b078d68c7828a035d88a
5
5
  SHA512:
6
- metadata.gz: 93ee3812b793b0dd34f88df23bc3438372d7cfb07d1ddefa72026bd9a064e37e4d5689bb13d46ae8eff5e62e90ee844f16179235d4806ec71519ff6dc87e89f1
7
- data.tar.gz: 8830854c6b28efcdeae92aebef0b75138a6f85fc87be5016931374b7b3c2f32c2cec8a0aa133f6a14db1634d83ed5db7f2ab8be7baa40a1603000611e882809d
6
+ metadata.gz: e427382e3c42a97b5991c2d382a078a198562c1686c835e7039546de9ce360890c8cd6ada52bb3339c1835fd9422d686875631ecdad6bf30f312a5bac38480ab
7
+ data.tar.gz: e35614f1087c93893ee1dc739b4c2a85756f632afcb99a419b70afb605714b459f5b8bf3bc2b1e0435527d4ce24999993df61e6c39366eb5c53d01cbda81a7c8
@@ -1,3 +1,3 @@
1
1
  module Jsonize
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/jsonize.rb CHANGED
@@ -3,7 +3,9 @@ require 'redisize'
3
3
  require "jsonize/version"
4
4
 
5
5
  module Jsonize
6
- JSON_ATTRS = {
6
+ DEFAULT_EXCEPT_ATTRS = [:created_at, :updated_at]
7
+
8
+ JSONIZE_ATTRS = {
7
9
  created_at: nil,
8
10
  updated_at: nil,
9
11
  }
@@ -12,26 +14,13 @@ module Jsonize
12
14
  ActiveRecord: 'active_record'
13
15
  }
14
16
 
15
- def external_attrs options = {}
16
- if externals = options[:externals]
17
- externals.keys.map {|k| [k.to_sym, k.to_sym] }.to_h
18
- else
19
- {}
20
- end
21
- end
17
+ JSON_TYPES = [String, Integer, TrueClass, FalseClass, NilClass, Hash, Array]
22
18
 
23
- def instance_attrs
24
- self.attribute_names.map {|a| [a.to_sym, true] }.to_h
25
- end
26
-
27
- def embed_attrs
28
- begin
29
- self.class.const_get("JSON_ATTRS")
30
- rescue
31
- {}
32
- end
19
+ def default_except_attributes
20
+ DEFAULT_EXCEPT_ATTRS
33
21
  end
34
22
 
23
+ # TODO where is the addtional sources for attributes
35
24
  def additional_attrs
36
25
  attributes = self.instance_variable_get(:@attributes).send(:attributes)
37
26
 
@@ -44,77 +33,120 @@ module Jsonize
44
33
  end
45
34
  end
46
35
 
47
- def generate_json propses, options = {}
48
- propses.reduce({}) do |r, (name, props)|
36
+ def generate_relation rela, source_in, options
37
+ source = source_in.is_a?(Hash) ? source_in : source_in.polymorphic? ?
38
+ {} : required_attibutes(source_in.klass, {})
39
+
40
+ case rela
41
+ when Enumerable
42
+ rela.map do |rec|
43
+ generate_json(rec, source, options)
44
+ end
45
+ when NilClass
46
+ nil
47
+ when Object
48
+ generate_json(rela, source, options)
49
+ end
50
+ end
51
+
52
+ def generate_json flow, attr_props, options = {}
53
+ in_h = (options[:externals] || {}).map {|(x, y)| [x.to_s, y] }.to_h
54
+
55
+ attr_props.reduce(in_h) do |cr, (name, props)|
49
56
  value =
50
- if props["rule"] == '_reflection'
51
- send(name).as_json(options[name.to_sym] || {})
52
- elsif props["rule"].is_a?(String) # NOTE required for sidekiq key
53
- extenrals = options[:externals]
54
- externals.fetch(props["rule"].to_sym) { |x| externals[props["rule"]] }
55
- elsif props["real_name"] != name.to_s
56
- read_attribute(props["real_name"]).as_json
57
- elsif props["rule"].instance_variable_get(:@value)
58
- props["rule"].instance_variable_get(:@value)
59
- elsif props["rule"]
60
- read_attribute(props["real_name"] || props["rule"])
57
+ [props].flatten.reduce(nil) do |r, source|
58
+ case source
59
+ when UnboundMethod
60
+ r || source.bind(flow)[]
61
+ when Proc
62
+ r || source[flow]
63
+ when Hash, ActiveRecord::Reflection::AbstractReflection
64
+ generate_relation(r || flow.send(name), source, options)
65
+ else
66
+ raise
67
+ end
61
68
  end
62
69
 
63
- r.merge(name => value)
70
+ cr.merge(name.to_s => proceed_value(value))
64
71
  end
65
72
  end
66
73
 
67
- def prepare_json options = {}
68
- attr_hash = [
69
- instance_attrs,
70
- JSON_ATTRS,
71
- embed_attrs,
72
- additional_attrs,
73
- external_attrs(options),
74
- options[:map] || {},
75
- _reflections
76
- ].reduce { |r, hash| r.merge(hash.map {|k,v| [k.to_sym, v] }.to_h) }
77
- except = options.fetch(:except, [])
78
- only = options.fetch(:only, self.attributes.keys.map(&:to_sym) | (options[:map] || {}).keys | embed_attrs.keys | external_attrs(options).keys)
79
-
80
- attr_hash.map do |(name_in, rule_in)|
81
- name = /^_(?<_name>.*)/ =~ name_in && _name || name_in.to_s
82
-
83
- next nil if except.include?(name.to_sym) || (only & [ name.to_sym, name_in.to_sym ].uniq).blank?
84
-
85
- rule = parse_rule(rule_in)
86
- [name, { "rule" => rule, "real_name" => name_in.to_s }]
87
- end.compact.to_h
88
- end
89
-
90
- def parse_rule rule_in
91
- case rule_in
92
- when TrueClass, FalseClass, NilClass
93
- true
94
- when ActiveRecord::Reflection::AbstractReflection
95
- '_reflection'
96
- when Symbol, String
97
- rule_in.to_s
98
- else
99
- true
74
+ def proceed_value value_in
75
+ (value_in.class.ancestors & JSON_TYPES).any? ? value_in : value_in.to_s
76
+ end
77
+
78
+ def prepare_attributes model, attrs
79
+ attrs.reduce({}) do |h, x|
80
+ if x.is_a?(Hash)
81
+ x.reduce(h) do |hh, (sub, subattrs)|
82
+ if submodel = model._reflections[sub]&.klass
83
+ hh.merge(sub.to_sym => prepare_attributes(submodel, subattrs))
84
+ else
85
+ hh
86
+ end
87
+ end
88
+ else
89
+ props = [
90
+ model._reflections[x.to_s],
91
+ model.instance_methods.include?(x.to_sym) ? model.instance_method(x.to_sym) : nil,
92
+ (self.class == model ? self.attribute_names : model.attribute_names).
93
+ include?(x.to_s) ? ->(this) { this.read_attribute(x) } : nil
94
+ ].compact
95
+
96
+ h.merge(x.to_s.sub(/^_/, '').to_sym => props)
97
+ end
100
98
  end
101
99
  end
102
100
 
101
+ def attibute_tree klass, options = {}
102
+ options[:only] ||
103
+ jsonize_attributes_except(self.class == klass ? self.attribute_names : klass.attribute_names,
104
+ options[:except] || default_except_attributes)
105
+ end
106
+
107
+ def jsonize_scheme_for klass, attr_tree
108
+ jsonize_schemes[attr_tree] ||= prepare_attributes(klass, attr_tree)
109
+ end
110
+
111
+ def jsonize_attributes_except a_in, except_in
112
+ except_in.reduce(a_in) do |res, name|
113
+ if res.include?(name)
114
+ res.delete(name)
115
+ end
116
+
117
+ res
118
+ end
119
+ end
120
+
121
+ def jsonize_schemes
122
+ schemes = self.class.instance_variable_get(:@jsonize_schemes) || {}
123
+ self.class.instance_variable_set(:@jsonize_schemes, schemes)
124
+
125
+ schemes
126
+ end
127
+
128
+ def primary_key
129
+ @primary_key
130
+ end
131
+
103
132
  def jsonize options = {}
104
- attr_props = prepare_json(options)
105
- redisize_json(attr_props) do
106
- generate_json(attr_props, options)
133
+ attr_tree = attibute_tree(self.class, options)
134
+
135
+ redisize_json(attr_tree) do
136
+ attr_props = jsonize_scheme_for(self.class, attr_tree)
137
+ generate_json(self, attr_props, options)
107
138
  end
108
139
  end
109
140
 
110
141
  def dejsonize options = {}
111
- attr_props = prepare_json(options)
112
- deredisize_json(attr_props)
142
+ attr_tree = attibute_tree(self.class, options)
143
+ deredisize_json(attr_tree)
113
144
  end
114
145
 
115
146
  def as_json options = {}
116
- attr_props = prepare_json(options)
117
- generate_json(attr_props, options)
147
+ attr_props = jsonize_scheme_for(self.class, attibute_tree(self.class, options))
148
+
149
+ generate_json(self, attr_props, options)
118
150
  end
119
151
 
120
152
  module Relation
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pavel «Malo» Skrylev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-08-05 00:00:00.000000000 Z
11
+ date: 2023-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redisize
@@ -95,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  requirements: []
98
- rubygems_version: 3.1.6
98
+ rubygems_version: 3.3.7
99
99
  signing_key:
100
100
  specification_version: 4
101
101
  summary: Act as as_json for active record model or as a jsonize