jsonize 0.1.1 → 0.3.0

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: 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