shreddies 0.2.0 → 0.6.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: 1f3a9878d5d25ca7eb02bc3d9f3e4e4dc6f71ab6f970312331ed01fe864923b4
4
- data.tar.gz: bfba9356df3012c94527f1214d1862c5a507f91aab243f43fc85c8a30b0d50e3
3
+ metadata.gz: 5d29eb71728861282bd3c4a7e04ee829c4d647962951dfc494b311146142a84b
4
+ data.tar.gz: 9281b757f6ac85f5d17879b54b4554a7cf4ea5853c04420f52a4755080157092
5
5
  SHA512:
6
- metadata.gz: '069be646751138acce14f15960e417c18dcb2f57981a49b77d7d1a3a71ef4c2c079c49be4535c8ae193e752cb90298ddca0a72d5f51d12a9f2f2860c940a1e84'
7
- data.tar.gz: 8cf4dd148fe6ab7a6989e52462bc3fd3b14cddf592d17b45bd6470ec60f7482fe21e64a12af1909181bf789981b64a964b30f241e746ff3150de7bb4edfa3245
6
+ metadata.gz: 70f1959dbd3cd6a7e134c3fb4404a8d75ea55e219ba8e01eaba675bcfbbdc597fc0e85a12df4574e73617cb5aec946f67fcb3a077d73ccbf068d5ec158e82996
7
+ data.tar.gz: b8618164e87ad5d94279a5e9294ec7d975d2b96ec3966fe8b074f4733296b9c047348b718002942911442f9f4511a61909045baeccfb9d9705975c749ffa7fb7
data/Gemfile CHANGED
@@ -5,7 +5,7 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in shreddies.gemspec
6
6
  gemspec
7
7
 
8
- gem 'rake', '~> 12.0'
8
+ gem 'rake', '~> 13.0'
9
9
  gem 'minitest', '~> 5.0'
10
10
  gem 'autotest-suffix'
11
11
  gem 'minitest-autotest'
@@ -1,32 +1,32 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- shreddies (0.1.0)
4
+ shreddies (0.6.0)
5
5
  activerecord (>= 5)
6
6
  railties (>= 5)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- actionpack (6.0.3.2)
12
- actionview (= 6.0.3.2)
13
- activesupport (= 6.0.3.2)
11
+ actionpack (6.0.3.4)
12
+ actionview (= 6.0.3.4)
13
+ activesupport (= 6.0.3.4)
14
14
  rack (~> 2.0, >= 2.0.8)
15
15
  rack-test (>= 0.6.3)
16
16
  rails-dom-testing (~> 2.0)
17
17
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
18
- actionview (6.0.3.2)
19
- activesupport (= 6.0.3.2)
18
+ actionview (6.0.3.4)
19
+ activesupport (= 6.0.3.4)
20
20
  builder (~> 3.1)
21
21
  erubi (~> 1.4)
22
22
  rails-dom-testing (~> 2.0)
23
23
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
24
- activemodel (6.0.3.2)
25
- activesupport (= 6.0.3.2)
26
- activerecord (6.0.3.2)
27
- activemodel (= 6.0.3.2)
28
- activesupport (= 6.0.3.2)
29
- activesupport (6.0.3.2)
24
+ activemodel (6.0.3.4)
25
+ activesupport (= 6.0.3.4)
26
+ activerecord (6.0.3.4)
27
+ activemodel (= 6.0.3.4)
28
+ activesupport (= 6.0.3.4)
29
+ activesupport (6.0.3.4)
30
30
  concurrent-ruby (~> 1.0, >= 1.0.2)
31
31
  i18n (>= 0.7, < 2)
32
32
  minitest (~> 5.1)
@@ -34,21 +34,21 @@ GEM
34
34
  zeitwerk (~> 2.2, >= 2.2.2)
35
35
  autotest-suffix (1.1.0)
36
36
  builder (3.2.4)
37
- combustion (1.3.0)
37
+ combustion (1.3.1)
38
38
  activesupport (>= 3.0.0)
39
39
  railties (>= 3.0.0)
40
40
  thor (>= 0.14.6)
41
- concurrent-ruby (1.1.6)
41
+ concurrent-ruby (1.1.7)
42
42
  crass (1.0.6)
43
43
  erubi (1.9.0)
44
- i18n (1.8.3)
44
+ i18n (1.8.5)
45
45
  concurrent-ruby (~> 1.0)
46
- loofah (2.6.0)
46
+ loofah (2.7.0)
47
47
  crass (~> 1.0.2)
48
48
  nokogiri (>= 1.5.9)
49
49
  method_source (1.0.0)
50
50
  mini_portile2 (2.4.0)
51
- minitest (5.14.1)
51
+ minitest (5.14.2)
52
52
  minitest-autotest (1.1.1)
53
53
  minitest-server (~> 1.0)
54
54
  path_expander (~> 1.0)
@@ -56,7 +56,7 @@ GEM
56
56
  minitest (>= 4, < 6)
57
57
  minitest-server (1.0.6)
58
58
  minitest (~> 5.0)
59
- nokogiri (1.10.9)
59
+ nokogiri (1.10.10)
60
60
  mini_portile2 (~> 2.4.0)
61
61
  path_expander (1.1.0)
62
62
  rack (2.2.3)
@@ -67,19 +67,19 @@ GEM
67
67
  nokogiri (>= 1.6)
68
68
  rails-html-sanitizer (1.3.0)
69
69
  loofah (~> 2.3)
70
- railties (6.0.3.2)
71
- actionpack (= 6.0.3.2)
72
- activesupport (= 6.0.3.2)
70
+ railties (6.0.3.4)
71
+ actionpack (= 6.0.3.4)
72
+ activesupport (= 6.0.3.4)
73
73
  method_source
74
74
  rake (>= 0.8.7)
75
75
  thor (>= 0.20.3, < 2.0)
76
- rake (12.3.3)
76
+ rake (13.0.1)
77
77
  sqlite3 (1.4.2)
78
78
  thor (1.0.1)
79
79
  thread_safe (0.3.6)
80
- tzinfo (1.2.7)
80
+ tzinfo (1.2.8)
81
81
  thread_safe (~> 0.1)
82
- zeitwerk (2.3.1)
82
+ zeitwerk (2.4.1)
83
83
 
84
84
  PLATFORMS
85
85
  ruby
@@ -90,7 +90,7 @@ DEPENDENCIES
90
90
  minitest (~> 5.0)
91
91
  minitest-autotest
92
92
  minitest-focus
93
- rake (~> 12.0)
93
+ rake (~> 13.0)
94
94
  shreddies!
95
95
  sqlite3
96
96
 
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Shreddies is a JSON serialization library for Rails that focuses on simplicity and speed. No more "magic" DSL's - just plain old Ruby objects! It's primarily intended to serialize Rails models as JSON, but will also work with pretty much anything at all.
4
4
 
5
+ Shreddies primary principle is to be explicit. So a serializer will return nothing until you define some methods. This gives you complete control and everything is a known quantity - no surprises.
6
+
5
7
  ## Installation
6
8
 
7
9
  Add this line to your application's Gemfile:
@@ -65,6 +67,8 @@ Model collections and array's are also supported:
65
67
  User.all.as_json
66
68
  ```
67
69
 
70
+ ### Collection and Single Modules
71
+
68
72
  You may find that you don't want or need to return as much data in collections of objects, or may want to include differtent data. So if a serializer defines a `Collection` module, and a collection or array is being rendered, then that Collection module will automatically be included:
69
73
 
70
74
  ```ruby
@@ -89,6 +93,40 @@ ArticleSerializer < Shreddies::Json
89
93
  end
90
94
  ```
91
95
 
96
+ ### ActiveRecord Associations
97
+
98
+ ActiveRecord associations are supported with no additional work on your part. Shreddies will simply call `#as_json` on any method that returns an ActiveRecord model or relation.
99
+
100
+ ```ruby
101
+ # app/serializers/user_serializer.rb
102
+ class UserSerializer < Shreddies::Json
103
+ delegate :articles
104
+
105
+ def latest_article
106
+ articles.latest
107
+ end
108
+ end
109
+ ```
110
+
111
+ And if you need to be specific about what you render, just call the serializer or `#as_json` directly:
112
+
113
+ ```ruby
114
+ # app/serializers/user_serializer.rb
115
+ class UserSerializer < Shreddies::Json
116
+ def articles
117
+ subject.articles.as_json index_by: :slug
118
+ end
119
+
120
+ def latest_article
121
+ LatestArticleSerializer.render articles.latest
122
+ end
123
+ end
124
+ ```
125
+
126
+ ### `before_render` callback
127
+
128
+ You can define a `#before_render` private method in your serializers, which will act as a callback. It receives the object to be output, and expects you to return the object, which allows you to modify it before rendering.
129
+
92
130
  ### Options
93
131
 
94
132
  Both `#as_json` and `.render` accepts an `options` hash, which will be forwarded to the serializer class, and available as `options`. This allows you to pass arbitrary options and use them in your serializer.
@@ -123,6 +161,28 @@ end
123
161
 
124
162
  The `Collection` and `Single` modules can be defined and they will be automatically included. The Collection module will be included when rendering an array or ActiveRecord collection (`ActiveRecord::Relation`), and the Single module will be included when rendering a single obejct.
125
163
 
164
+ #### `transform_keys` (default: true)
165
+
166
+ If false, the returned keys will not be transformed. The default is to deeply transform all keys to camelCase.
167
+
168
+ #### `except`
169
+
170
+ Pass one or more attribute names as a Symbol or Array of Symbols, and these will be excluded from the results:
171
+
172
+ ```ruby
173
+ User.all.as_json(except: [:first_name, :age])
174
+ ```
175
+
176
+ #### `only`
177
+
178
+ Pass one or more attribute names as a Symbol or Array of Symbols, and _ONLY_ these will be included in the results:
179
+
180
+ ```ruby
181
+ User.all.as_json(only: :first_name)
182
+ ```
183
+
184
+ > Attributes must still be defined within the Serializer.
185
+
126
186
  #### `index_by`
127
187
 
128
188
  Give this option a property of your serialized subject as a Symbol, and the returned collection will be a Hash keyed by that property.
@@ -44,11 +44,11 @@ module Shreddies
44
44
  super(*methods, to: to, prefix: prefix, allow_nil: allow_nil, private: private)
45
45
  end
46
46
 
47
- attr_reader :subject, :options, :from_collection
47
+ attr_reader :subject, :options
48
48
 
49
- def initialize(subject, options)
50
- @subject = subject
51
- @options = options
49
+ def initialize(subject, opts = {})
50
+ @subject = subject.is_a?(Hash) ? OpenStruct.new(subject) : subject
51
+ @options = { transform_keys: true }.merge(opts).with_indifferent_access
52
52
 
53
53
  extend_with_modules
54
54
  end
@@ -56,7 +56,7 @@ module Shreddies
56
56
  # Travel through the ancestors that are serializers (class name ends with "Serializer"), and
57
57
  # call all public instance methods, returning a hash.
58
58
  def as_json
59
- json = {}
59
+ output = {}.with_indifferent_access
60
60
  methods = Set.new(public_methods(false))
61
61
 
62
62
  self.class.ancestors.each do |ancestor|
@@ -65,22 +65,43 @@ module Shreddies
65
65
  end
66
66
  end
67
67
 
68
+ # Filter out methods using the `only` or `except` options.
69
+ if @options[:only]
70
+ @options[:only] = Array(@options[:only])
71
+ methods = methods.select { |x| @options[:only].include? x }
72
+ elsif @options[:except]
73
+ methods = methods.excluding(@options[:except])
74
+ end
75
+
68
76
  methods.map do |attr|
69
- json[attr.to_s.camelize :lower] = public_send(attr)
77
+ res = public_send(attr)
78
+ if res.is_a?(ActiveRecord::Relation) || res.is_a?(ActiveRecord::Base)
79
+ res = res.as_json(transform_keys: @options[:transform_keys])
80
+ end
81
+
82
+ output[attr] = res
70
83
  end
71
84
 
72
- json.deep_transform_keys { |key| key.to_s.camelize :lower }
85
+ output = before_render(output)
86
+
87
+ return output unless @options[:transform_keys]
88
+
89
+ output.deep_transform_keys { |key| key.to_s.camelize :lower }
73
90
  end
74
91
 
75
92
  private
76
93
 
94
+ def before_render(output)
95
+ output
96
+ end
97
+
77
98
  def extend_with_modules
78
99
  self.class.ancestors.reverse.each do |ancestor|
79
100
  next unless ancestor.to_s.end_with?('Serializer')
80
101
 
81
102
  # Extend with Collection module if it exists, and a collection is being rendered. Otherwise,
82
103
  # extend with the Single module if that exists.
83
- if options[:from_collection]
104
+ if @options[:from_collection]
84
105
  (collection_mod = "#{ancestor}::Collection".safe_constantize) && extend(collection_mod)
85
106
  else
86
107
  (single_mod = "#{ancestor}::Single".safe_constantize) && extend(single_mod)
@@ -88,11 +109,9 @@ module Shreddies
88
109
  end
89
110
 
90
111
  # Extend with the :module option if given.
91
- if options[:module]
92
- Array(options[:module]).each do |m|
93
- mod = m.is_a?(Module) ? m : "#{self.class}::#{m}".constantize
94
-
95
- extend mod
112
+ if @options[:module]
113
+ Array(@options[:module]).each do |m|
114
+ extend m.is_a?(Module) ? m : "#{self.class}::#{m}".constantize
96
115
  end
97
116
  end
98
117
  end
@@ -1,3 +1,3 @@
1
1
  module Shreddies
2
- VERSION = "0.2.0"
2
+ VERSION = "0.6.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shreddies
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Moss
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-14 00:00:00.000000000 Z
11
+ date: 2020-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -84,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
84
84
  - !ruby/object:Gem::Version
85
85
  version: '0'
86
86
  requirements: []
87
- rubygems_version: 3.1.2
87
+ rubygems_version: 3.1.4
88
88
  signing_key:
89
89
  specification_version: 4
90
90
  summary: Stupid simple Rails model and object serializer