shreddies 0.1.0 → 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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +80 -1
- data/lib/shreddies/as_json.rb +6 -10
- data/lib/shreddies/json.rb +48 -9
- data/lib/shreddies/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f3a9878d5d25ca7eb02bc3d9f3e4e4dc6f71ab6f970312331ed01fe864923b4
|
4
|
+
data.tar.gz: bfba9356df3012c94527f1214d1862c5a507f91aab243f43fc85c8a30b0d50e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '069be646751138acce14f15960e417c18dcb2f57981a49b77d7d1a3a71ef4c2c079c49be4535c8ae193e752cb90298ddca0a72d5f51d12a9f2f2860c940a1e84'
|
7
|
+
data.tar.gz: 8cf4dd148fe6ab7a6989e52462bc3fd3b14cddf592d17b45bd6470ec60f7482fe21e64a12af1909181bf789981b64a964b30f241e746ff3150de7bb4edfa3245
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -20,7 +20,7 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
-
Serializers should be named after your models and located in "`app/serializers`". Any public methods you define will be serialized, and you can quickly expose methods from the serialized subject using the `delegate` class method.
|
23
|
+
Serializers should be named after your models and located in "`app/serializers`". Any public methods you define will be serialized, and you can quickly expose methods from the serialized subject using the `delegate` class method, which simply delegates to the subject.
|
24
24
|
|
25
25
|
```ruby
|
26
26
|
# app/serializers/user_serializer.rb
|
@@ -65,12 +65,64 @@ Model collections and array's are also supported:
|
|
65
65
|
User.all.as_json
|
66
66
|
```
|
67
67
|
|
68
|
+
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
|
+
|
70
|
+
```ruby
|
71
|
+
ArticleSerializer < Shreddies::Json
|
72
|
+
module Collection
|
73
|
+
def url
|
74
|
+
"https://blah.com/#{subject.slug}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
Conversely, you can define a `Single` module, and that will be included when rendering a single object.
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
ArticleSerializer < Shreddies::Json
|
84
|
+
module Single
|
85
|
+
def body
|
86
|
+
'this body is really, really long, and I do not want it returned in lists.'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
68
92
|
### Options
|
69
93
|
|
70
94
|
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.
|
71
95
|
|
72
96
|
The following standard options are supported, and provide additional built-in functionality:
|
73
97
|
|
98
|
+
#### `serializer`
|
99
|
+
|
100
|
+
By default `#as_json` will look for a serializer named after your model. So a `User` model will automatically use the `UserSerializer`. Sometimes you want to use a different serializer class, in which case you can use the `serializer` option:
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
User.all.as_json serializer: User::AdminSerializer
|
104
|
+
```
|
105
|
+
|
106
|
+
#### `module`
|
107
|
+
|
108
|
+
You can pass one or module names in the `module` option, and these modules will be included into the serializer. This is great for selectively including attributes and methods.
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
Article.all.as_json module: :WithBody
|
112
|
+
```
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
ArticleSerializer < Shreddies::Json
|
116
|
+
module WithBody
|
117
|
+
def body
|
118
|
+
'This article body is really, really long'
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
```
|
123
|
+
|
124
|
+
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
|
+
|
74
126
|
#### `index_by`
|
75
127
|
|
76
128
|
Give this option a property of your serialized subject as a Symbol, and the returned collection will be a Hash keyed by that property.
|
@@ -99,6 +151,33 @@ User.all.as_json index_by: :id
|
|
99
151
|
}
|
100
152
|
```
|
101
153
|
|
154
|
+
### Serializer Inheritance
|
155
|
+
|
156
|
+
A serializer can inherit from any other serializer, which is a great way to create custom views:
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
# app/serializers/user_serializer.rb
|
160
|
+
class UserSerializer < Shreddies::Json
|
161
|
+
delegate :id, :first_name, :last_name, :email
|
162
|
+
|
163
|
+
def name
|
164
|
+
"#{first_name} #{last_name}"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
class User::AdministratorSerializer < UserSerializer
|
169
|
+
def type
|
170
|
+
'administrator'
|
171
|
+
end
|
172
|
+
end
|
173
|
+
```
|
174
|
+
|
175
|
+
Then call it like any other serializer:
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
User::AdministratorSerializer.render(user)
|
179
|
+
```
|
180
|
+
|
102
181
|
## Development
|
103
182
|
|
104
183
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/shreddies/as_json.rb
CHANGED
@@ -7,12 +7,10 @@ module Shreddies
|
|
7
7
|
serializer = options.delete(:serializer) || "#{model_name}Serializer"
|
8
8
|
|
9
9
|
if serializer.is_a?(String) || serializer.is_a?(Symbol)
|
10
|
-
serializer.to_s.
|
11
|
-
else
|
12
|
-
serializer.render self, options
|
10
|
+
serializer = serializer.to_s.safe_constantize
|
13
11
|
end
|
14
|
-
|
15
|
-
super
|
12
|
+
|
13
|
+
serializer ? serializer.render_as_json(self, options) : super
|
16
14
|
end
|
17
15
|
end
|
18
16
|
|
@@ -21,12 +19,10 @@ module Shreddies
|
|
21
19
|
serializer = options.delete(:serializer) || "#{model_name}Serializer"
|
22
20
|
|
23
21
|
if serializer.is_a?(String) || serializer.is_a?(Symbol)
|
24
|
-
serializer.to_s.
|
25
|
-
else
|
26
|
-
serializer.render self, options
|
22
|
+
serializer = serializer.to_s.safe_constantize
|
27
23
|
end
|
28
|
-
|
29
|
-
super
|
24
|
+
|
25
|
+
serializer ? serializer.render_as_json(self, options) : super
|
30
26
|
end
|
31
27
|
end
|
32
28
|
end
|
data/lib/shreddies/json.rb
CHANGED
@@ -6,20 +6,28 @@ module Shreddies
|
|
6
6
|
# Render a subject as json, where `subject` is a single object (usually a Rails model), or an
|
7
7
|
# array/collection of objects.
|
8
8
|
#
|
9
|
+
# If subject is an array/collection then it will look for a `Collection` module prepend it to
|
10
|
+
# the `module` option.
|
11
|
+
#
|
9
12
|
# A Hash of options can be given as the second argument:
|
10
13
|
# - index_by - Key the returned array by the value, transforming it from an array to a hash.
|
14
|
+
# - module - A Symbol or String of a local module to include. Or an array of several
|
15
|
+
# modules, where each will be mixed in in order. Use this to mix in groups of
|
16
|
+
# attributes. Eg. `ArticleSerializer.render(data, module: :WithBody)`.
|
11
17
|
#
|
12
18
|
def render(subject, options = {})
|
13
19
|
index_by = options.delete(:index_by)
|
14
20
|
|
15
21
|
if subject.is_a?(Array) || subject.is_a?(ActiveRecord::Relation)
|
22
|
+
collection_options = options.merge(from_collection: true)
|
23
|
+
|
16
24
|
if index_by
|
17
25
|
mapped = {}
|
18
26
|
subject.each do |x|
|
19
|
-
mapped[x[index_by]] = new(x,
|
27
|
+
mapped[x[index_by]] = new(x, collection_options)
|
20
28
|
end
|
21
29
|
else
|
22
|
-
mapped = subject.map { |x| new(x,
|
30
|
+
mapped = subject.map { |x| new(x, collection_options) }
|
23
31
|
end
|
24
32
|
|
25
33
|
mapped.as_json
|
@@ -31,31 +39,62 @@ module Shreddies
|
|
31
39
|
alias render_as_json render
|
32
40
|
end
|
33
41
|
|
34
|
-
# Monkey patches Rails Module#delegate so that the `:to` argument defaults
|
42
|
+
# Monkey patches Rails Module#delegate so that the `:to` argument defaults to `:subject`.
|
35
43
|
def self.delegate(*methods, to: :subject, prefix: nil, allow_nil: nil, private: nil)
|
36
44
|
super(*methods, to: to, prefix: prefix, allow_nil: allow_nil, private: private)
|
37
45
|
end
|
38
46
|
|
39
|
-
attr_reader :subject, :options
|
47
|
+
attr_reader :subject, :options, :from_collection
|
40
48
|
|
41
49
|
def initialize(subject, options)
|
42
50
|
@subject = subject
|
43
51
|
@options = options
|
52
|
+
|
53
|
+
extend_with_modules
|
44
54
|
end
|
45
55
|
|
56
|
+
# Travel through the ancestors that are serializers (class name ends with "Serializer"), and
|
57
|
+
# call all public instance methods, returning a hash.
|
46
58
|
def as_json
|
47
59
|
json = {}
|
60
|
+
methods = Set.new(public_methods(false))
|
48
61
|
|
49
|
-
|
50
|
-
|
51
|
-
|
62
|
+
self.class.ancestors.each do |ancestor|
|
63
|
+
if ancestor.to_s.end_with?('Serializer')
|
64
|
+
methods.merge ancestor.public_instance_methods(false)
|
65
|
+
end
|
52
66
|
end
|
53
67
|
|
54
|
-
methods.
|
55
|
-
json[attr] = public_send(attr)
|
68
|
+
methods.map do |attr|
|
69
|
+
json[attr.to_s.camelize :lower] = public_send(attr)
|
56
70
|
end
|
57
71
|
|
58
72
|
json.deep_transform_keys { |key| key.to_s.camelize :lower }
|
59
73
|
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def extend_with_modules
|
78
|
+
self.class.ancestors.reverse.each do |ancestor|
|
79
|
+
next unless ancestor.to_s.end_with?('Serializer')
|
80
|
+
|
81
|
+
# Extend with Collection module if it exists, and a collection is being rendered. Otherwise,
|
82
|
+
# extend with the Single module if that exists.
|
83
|
+
if options[:from_collection]
|
84
|
+
(collection_mod = "#{ancestor}::Collection".safe_constantize) && extend(collection_mod)
|
85
|
+
else
|
86
|
+
(single_mod = "#{ancestor}::Single".safe_constantize) && extend(single_mod)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# 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
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
60
99
|
end
|
61
100
|
end
|
data/lib/shreddies/version.rb
CHANGED
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.
|
4
|
+
version: 0.2.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-
|
11
|
+
date: 2020-07-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|