jsonize 0.1.1 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bdb7d503cc06ab7caf4bad0cfb1f7162fab524a76d7cfc5d24c695f58231f5ae
4
- data.tar.gz: 5d4ac6b92ab4f1893d7cd23609460e9f2009bd646f1df4f2878a5fa4db758465
3
+ metadata.gz: 5f9ca1fdab05a8d207c70e1600579a486d4532431fae68683398cb1ee1d8e7ec
4
+ data.tar.gz: bd1db6eda7a52b81fbfdeda0b83c9ede523da3c06df6fecefe961e9006784def
5
5
  SHA512:
6
- metadata.gz: 93ee3812b793b0dd34f88df23bc3438372d7cfb07d1ddefa72026bd9a064e37e4d5689bb13d46ae8eff5e62e90ee844f16179235d4806ec71519ff6dc87e89f1
7
- data.tar.gz: 8830854c6b28efcdeae92aebef0b75138a6f85fc87be5016931374b7b3c2f32c2cec8a0aa133f6a14db1634d83ed5db7f2ab8be7baa40a1603000611e882809d
6
+ metadata.gz: 427fbc6d4eb02797ffcf4a93915b044d14cfb205ec7b8cd2784258f989b98739cef5b69a294e37cbd6a5e02a6895a9eecf45a92911906f64229296ae3398ce14
7
+ data.tar.gz: 47329b942f4f8f89243c5cb8c775186d80febecb0233944978cfdd3d1b8a3cae2bc90bb9e79ce893487dbea49b86c5b3505a0c8259b23657a548819febc6dcca
data/README.md CHANGED
@@ -32,7 +32,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
32
 
33
33
  ## Contributing
34
34
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/jsonize. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/jsonize/blob/master/CODE_OF_CONDUCT.md).
35
+ Bug reports and pull requests are welcome on GitHub at https://codeberg.org/majioa/jsonize. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://codeberg.org/majioa/jsonize/blob/master/CODE_OF_CONDUCT.md).
36
36
 
37
37
 
38
38
  ## License
@@ -41,4 +41,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
41
41
 
42
42
  ## Code of Conduct
43
43
 
44
- Everyone interacting in the Jsonize project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/jsonize/blob/master/CODE_OF_CONDUCT.md).
44
+ Everyone interacting in the Jsonize project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://codeberg.org/majioa/jsonize/blob/master/CODE_OF_CONDUCT.md).
data/jsonize.gemspec CHANGED
@@ -8,15 +8,15 @@ Gem::Specification.new do |spec|
8
8
 
9
9
  spec.summary = %q{Act as as_json for active record model or as a jsonize}
10
10
  spec.description = %q{Act as as_json for active record model or as a jsonize using the cacheable redisize}
11
- spec.homepage = "https://github.com/majioa/jsonize"
11
+ spec.homepage = "https://codeberg.org/majioa/jsonize"
12
12
  spec.license = "MIT"
13
13
  spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
14
14
 
15
15
  spec.metadata["allowed_push_host"] = "https://rubygems.org"
16
16
 
17
17
  spec.metadata["homepage_uri"] = spec.homepage
18
- spec.metadata["source_code_uri"] = "https://github.com/majioa/jsonize"
19
- spec.metadata["changelog_uri"] = "https://github.com/majioa/jsonize/CHANGELOG.md"
18
+ spec.metadata["source_code_uri"] = "https://codeberg.org/majioa/jsonize"
19
+ spec.metadata["changelog_uri"] = "https://codeberg.org/majioa/jsonize/CHANGELOG.md"
20
20
 
21
21
  # Specify which files should be added to the gem when it is released.
22
22
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@@ -3,4 +3,5 @@ require 'active_support/lazy_load_hooks'
3
3
  ActiveSupport.on_load :active_record do
4
4
  ::ActiveRecord::Base.send :include, Jsonize
5
5
  ::ActiveRecord::Relation.send :include, Jsonize::Relation
6
+ ::Enumerable.send :include, Jsonize::Collection
6
7
  end
@@ -1,3 +1,3 @@
1
1
  module Jsonize
2
- VERSION = "0.1.1"
2
+ VERSION = "0.3.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,188 @@ 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
+ attr_props = source_in.is_a?(Hash) ? source_in : source_in.polymorphic? ?
38
+ {} : jsonize_scheme_for(source_in.klass, attibute_tree(source_in.klass, options))
39
+
40
+ case rela
41
+ when Enumerable
42
+ rela.map do |rec|
43
+ generate_json(rec, attr_props, options)
44
+ end
45
+ when NilClass
46
+ nil
47
+ when Object
48
+ generate_json(rela, attr_props, 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 ||
61
+ begin
62
+ source.bind(flow)[]
63
+ rescue ActiveModel::MissingAttributeError, TypeError, NoMethodError
64
+ rescue Exception => e
65
+ $stderr.puts("#{e.class}: #{e.message}")
66
+ # binding.pry
67
+ end
68
+ when Proc
69
+ r || source[flow]
70
+ when Hash, ActiveRecord::Reflection::AbstractReflection
71
+ o = !options[:only] ? options :
72
+ options[:only].is_a?(Hash) ? options.merge(only: options[:only][name]) :
73
+ options.merge(only: nil)
74
+
75
+ generate_relation(r || flow.respond_to?(name) && flow.send(name) || nil, source, o)
76
+ when NilClass
77
+ r
78
+ else
79
+ raise
80
+ end
61
81
  end
62
82
 
63
- r.merge(name => value)
83
+ cr.merge(name.to_s => proceed_value(value))
64
84
  end
65
85
  end
66
86
 
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
87
+ def proceed_value value_in
88
+ (value_in.class.ancestors & JSON_TYPES).any? ? value_in : value_in.to_s
89
+ end
90
+
91
+ def prepare_attributes model, attrs
92
+ attrs.reduce({}) do |h, x|
93
+ if x.is_a?(Hash)
94
+ x.reduce(h) do |hh, (sub, subattrs)|
95
+ if submodel = model._reflections[sub]&.klass
96
+ collect_attributes(hh, model, sub, sub.to_sym, prepare_attributes(submodel, subattrs))
97
+ else
98
+ hh
99
+ end
100
+ end
101
+ else
102
+ collect_attributes(h, model, x, x.to_s.sub(/^_/, '').to_sym, nil)
103
+ end
104
+ end
105
+ end
106
+
107
+ def collect_attributes h, model, name, key, value
108
+ base = [ ->(this) { this.respond_to?(:read_attribute) ? this.read_attribute("_#{name}") : nil } ]
109
+
110
+ props =
111
+ unless value
112
+ [model._reflections[name.to_s],
113
+ model.instance_methods.include?(name.to_sym) ? model.instance_method(name.to_sym) : nil,
114
+ ->(this) { this.is_a?(Hash) ? this[name] : nil },
115
+ (self.class == model ? self.attribute_names : model.attribute_names).include?(name.to_s) ?
116
+ ->(this) { this.respond_to?(:read_attribute) ? this.read_attribute(name) : nil } : nil,
117
+ ].compact
98
118
  else
99
- true
119
+ [value]
120
+ end
121
+
122
+ h.merge(key => base.concat(props))
123
+ end
124
+
125
+ def attibute_tree klass, options = {}
126
+ options[:only] ||
127
+ jsonize_attributes_except(self.class == klass ? self.attribute_names : klass.attribute_names,
128
+ options[:except] || default_except_attributes)
129
+ end
130
+
131
+ def jsonize_scheme_for klass, attr_tree
132
+ jsonize_schemes[attr_tree] ||= prepare_attributes(klass, attr_tree)
133
+ end
134
+
135
+ def jsonize_attributes_except a_in, except_in
136
+ except_in.reduce(a_in) do |res, name|
137
+ if res.include?(name)
138
+ res.delete(name)
139
+ end
140
+
141
+ res
100
142
  end
101
143
  end
102
144
 
145
+ def jsonize_schemes
146
+ schemes = self.class.instance_variable_get(:@jsonize_schemes) || {}
147
+ self.class.instance_variable_set(:@jsonize_schemes, schemes)
148
+
149
+ schemes
150
+ end
151
+
152
+ def primary_key
153
+ @primary_key
154
+ end
155
+
103
156
  def jsonize options = {}
104
- attr_props = prepare_json(options)
105
- redisize_json(attr_props) do
106
- generate_json(attr_props, options)
157
+ attr_tree = attibute_tree(self.class, options)
158
+
159
+ redisize_json(attr_tree) do
160
+ attr_props = jsonize_scheme_for(self.class, attr_tree)
161
+ generate_json(self, attr_props, options)
107
162
  end
108
163
  end
109
164
 
110
165
  def dejsonize options = {}
111
- attr_props = prepare_json(options)
112
- deredisize_json(attr_props)
166
+ attr_tree = attibute_tree(self.class, options)
167
+ deredisize_json(attr_tree)
113
168
  end
114
169
 
115
170
  def as_json options = {}
116
- attr_props = prepare_json(options)
117
- generate_json(attr_props, options)
171
+ attr_props = jsonize_scheme_for(self.class, attibute_tree(self.class, options))
172
+
173
+ generate_json(self, attr_props, options)
174
+ end
175
+
176
+ module Collection
177
+ def jsonize context = {}
178
+ method =
179
+ case self
180
+ when Hash
181
+ :redisize_hash
182
+ when Array
183
+ :redisize_array
184
+ end
185
+
186
+ send(method) do
187
+ as_pure_json(context)
188
+ end
189
+ end
190
+
191
+ def recontext context, key
192
+ context_only = [context[:only]].flatten(1).reduce(nil) { |r, x| r || (x.is_a?(Hash) ? x[key] : r) }
193
+ context_except = [context[:except]].flatten(1).reduce(nil) { |r, x| r || (x.is_a?(Hash) ? x[key] : r) }
194
+
195
+ context.merge(only: context_only, except: context_except)
196
+ end
197
+
198
+ def as_pure_json context = {}
199
+ case self
200
+ when Hash
201
+ self.map do |key, value_in|
202
+ new_context = recontext(context, key)
203
+
204
+ value = value_in.respond_to?(:as_pure_json) ? value_in.as_pure_json(new_context) : value_in.as_json(new_context)
205
+
206
+ [key.to_s, value]
207
+ end.to_h
208
+ when Array
209
+ self.map.with_index do |value_in, index|
210
+ new_context = recontext(context, index.to_i)
211
+
212
+ value_in.respond_to?(:as_pure_json) ? value_in.as_pure_json(new_context) : value_in.as_json(new_context)
213
+ end
214
+ else
215
+ as_json(context)
216
+ end
217
+ end
118
218
  end
119
219
 
120
220
  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.3.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: 2024-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redisize
@@ -72,14 +72,14 @@ files:
72
72
  - lib/jsonize.rb
73
73
  - lib/jsonize/orm/active_record.rb
74
74
  - lib/jsonize/version.rb
75
- homepage: https://github.com/majioa/jsonize
75
+ homepage: https://codeberg.org/majioa/jsonize
76
76
  licenses:
77
77
  - MIT
78
78
  metadata:
79
79
  allowed_push_host: https://rubygems.org
80
- homepage_uri: https://github.com/majioa/jsonize
81
- source_code_uri: https://github.com/majioa/jsonize
82
- changelog_uri: https://github.com/majioa/jsonize/CHANGELOG.md
80
+ homepage_uri: https://codeberg.org/majioa/jsonize
81
+ source_code_uri: https://codeberg.org/majioa/jsonize
82
+ changelog_uri: https://codeberg.org/majioa/jsonize/CHANGELOG.md
83
83
  post_install_message:
84
84
  rdoc_options: []
85
85
  require_paths:
@@ -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.26
99
99
  signing_key:
100
100
  specification_version: 4
101
101
  summary: Act as as_json for active record model or as a jsonize