supa 0.2.3 → 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 +4 -4
- data/.codeclimate.yml +10 -11
- data/.reek +128 -0
- data/.rspec +2 -0
- data/.rubocop.yml +1197 -1011
- data/.travis.yml +12 -4
- data/Gemfile +0 -1
- data/README.md +142 -57
- data/Rakefile +3 -11
- data/bin/console +4 -4
- data/lib/supa.rb +9 -1
- data/lib/supa/builder.rb +14 -25
- data/lib/supa/command.rb +25 -28
- data/lib/supa/commands/append.rb +3 -11
- data/lib/supa/commands/attribute.rb +1 -3
- data/lib/supa/commands/collection.rb +26 -6
- data/lib/supa/commands/namespace.rb +2 -6
- data/lib/supa/commands/object.rb +23 -4
- data/lib/supa/commands/virtual.rb +7 -3
- data/lib/supa/representable.rb +1 -1
- data/lib/supa/version.rb +1 -1
- data/supa.gemspec +23 -14
- metadata +73 -9
data/.travis.yml
CHANGED
@@ -2,11 +2,19 @@ sudo: false
|
|
2
2
|
language: ruby
|
3
3
|
rvm:
|
4
4
|
- 2.3.1
|
5
|
-
|
5
|
+
|
6
|
+
notifications:
|
7
|
+
email: false
|
8
|
+
|
6
9
|
addons:
|
7
10
|
code_climate:
|
8
|
-
repo_token:
|
11
|
+
repo_token: ad743cd1c267d4a84bfa620869f906a68efba51baa3aadc0638b88330ce3ab3a
|
12
|
+
|
13
|
+
cache:
|
14
|
+
- bundler
|
15
|
+
|
16
|
+
before_install: gem install bundler -v 1.13.7
|
17
|
+
script:
|
18
|
+
- bundle exec rake
|
9
19
|
after_success:
|
10
20
|
- bundle exec codeclimate-test-reporter
|
11
|
-
notifications:
|
12
|
-
email: false
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
Ruby object → JSON serialization.
|
4
4
|
|
5
|
-
[](https://travis-ci.org/distribusion/supa)
|
6
|
+
[](https://codeclimate.com/repos/587387071c36ea7203000e0d/feed)
|
7
|
+
[](https://codeclimate.com/repos/587387071c36ea7203000e0d/coverage)
|
8
|
+
[](https://codeclimate.com/repos/587387071c36ea7203000e0d/feed)
|
9
9
|
|
10
10
|
## Introduction
|
11
11
|
|
@@ -24,7 +24,7 @@ bundle install
|
|
24
24
|
```
|
25
25
|
|
26
26
|
Or install it yourself as
|
27
|
-
```
|
27
|
+
```shell
|
28
28
|
gem install supa
|
29
29
|
```
|
30
30
|
|
@@ -49,75 +49,77 @@ end
|
|
49
49
|
```
|
50
50
|
|
51
51
|
```ruby
|
52
|
-
|
53
|
-
|
54
|
-
include Supa::Representable
|
52
|
+
class ArticleRepresenter
|
53
|
+
include Supa::Representable
|
55
54
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
55
|
+
define do
|
56
|
+
namespace :jsonapi do
|
57
|
+
virtual :version, getter: 1.1, modifier: :to_s
|
58
|
+
end
|
60
59
|
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
namespace :meta do
|
61
|
+
attribute :locale, getter: :language, exec_context: :representer
|
62
|
+
attribute :date, exec_context: :representer
|
63
|
+
end
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
namespace :data do
|
66
|
+
attribute :id
|
67
|
+
virtual :type, getter: 'articles'
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
69
|
+
namespace :attributes do
|
70
|
+
attribute :title
|
71
|
+
attribute :text
|
72
|
+
end
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
74
|
+
namespace :relationships do
|
75
|
+
object :author do
|
76
|
+
namespace :data do
|
77
|
+
attribute :id
|
78
|
+
virtual :type, getter: 'authors'
|
80
79
|
end
|
80
|
+
end
|
81
81
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
end
|
82
|
+
namespace :comments do
|
83
|
+
collection :data, getter: :comments do
|
84
|
+
attribute :id
|
85
|
+
virtual :type, getter: 'comments'
|
87
86
|
end
|
88
87
|
end
|
89
88
|
end
|
89
|
+
end
|
90
90
|
|
91
|
-
|
92
|
-
|
93
|
-
|
91
|
+
collection :included, getter: :author do
|
92
|
+
attribute :id
|
93
|
+
virtual :type, getter: 'authors'
|
94
94
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
end
|
95
|
+
namespace :attributes do
|
96
|
+
attribute :first_name
|
97
|
+
attribute :last_name
|
99
98
|
end
|
99
|
+
end
|
100
100
|
|
101
|
-
|
102
|
-
|
103
|
-
|
101
|
+
append :included, getter: :comments do
|
102
|
+
attribute :id
|
103
|
+
virtual :type, getter: 'comments'
|
104
104
|
|
105
|
-
|
106
|
-
|
107
|
-
end
|
105
|
+
namespace :attributes do
|
106
|
+
attribute :text
|
108
107
|
end
|
109
108
|
end
|
109
|
+
end
|
110
110
|
|
111
|
-
|
112
|
-
|
113
|
-
|
111
|
+
def to_s(value)
|
112
|
+
value.to_s
|
113
|
+
end
|
114
114
|
|
115
|
-
|
116
|
-
|
117
|
-
end
|
115
|
+
def language
|
116
|
+
'en'
|
118
117
|
end
|
119
|
-
end
|
120
118
|
|
119
|
+
def date
|
120
|
+
Date.today.iso8601
|
121
|
+
end
|
122
|
+
end
|
121
123
|
```
|
122
124
|
|
123
125
|
```ruby
|
@@ -130,7 +132,8 @@ ArticleRepresenter.new(Article.new).to_json
|
|
130
132
|
"version": "1.1"
|
131
133
|
},
|
132
134
|
"meta": {
|
133
|
-
"locale": "en"
|
135
|
+
"locale": "en",
|
136
|
+
"date": "2050-01-01"
|
134
137
|
},
|
135
138
|
"data": {
|
136
139
|
"id": "7aa15512-1f9d-4a86-98ad-4bb0aae487a2",
|
@@ -188,9 +191,92 @@ ArticleRepresenter.new(Article.new).to_json
|
|
188
191
|
```
|
189
192
|
|
190
193
|
### `attribute`
|
194
|
+
Attributes will be retrieved from correspondingly named instance methods unless a getter is defined:
|
195
|
+
```ruby
|
196
|
+
class ExampleRepresenter
|
197
|
+
include Supa::Representable
|
198
|
+
|
199
|
+
define do
|
200
|
+
attribute :name
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
ExampleRepresenter.new(OpenStruct.new(name: 'Heidi')).to_hash
|
205
|
+
|
206
|
+
#=> {
|
207
|
+
#=> name: 'Heidi'
|
208
|
+
#=> }
|
209
|
+
```
|
210
|
+
A getter can take several forms:
|
211
|
+
|
212
|
+
### 1. Method name
|
213
|
+
```ruby
|
214
|
+
class ExampleRepresenter
|
215
|
+
include Supa::Representable
|
216
|
+
|
217
|
+
define do
|
218
|
+
attribute :name, getter: :full_name
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
class Person
|
223
|
+
attr_accessor :full_name
|
224
|
+
end
|
225
|
+
|
226
|
+
example = Person.new
|
227
|
+
example.full_name = 'Heidi Shepherd'
|
228
|
+
|
229
|
+
ExampleRepresenter.new(example).to_hash
|
230
|
+
|
231
|
+
#=> {
|
232
|
+
#=> name: 'Heidi Shepherd'
|
233
|
+
#=> }
|
234
|
+
```
|
235
|
+
The lookup order is to first check the object instance and then the representer for a matching method.
|
236
|
+
|
237
|
+
###2. Hash key
|
238
|
+
```ruby
|
239
|
+
class ExampleRepresenter
|
240
|
+
include Supa::Representable
|
241
|
+
|
242
|
+
define do
|
243
|
+
attribute :name, getter: 'full_name'
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
example = {
|
248
|
+
'full_name' => 'Heidi Shepherd'
|
249
|
+
}
|
250
|
+
|
251
|
+
ExampleRepresenter.new(example).to_hash
|
252
|
+
|
253
|
+
#=> {
|
254
|
+
#=> name: 'Heidi Shepherd'
|
255
|
+
#=> }
|
256
|
+
|
257
|
+
```
|
191
258
|
|
192
259
|
### `virtual`
|
193
260
|
|
261
|
+
Virtual is an attribute that doesn't exist in representing object and defind as `string`.
|
262
|
+
```ruby
|
263
|
+
class ExampleRepresenter
|
264
|
+
include Supa::Representable
|
265
|
+
|
266
|
+
define do
|
267
|
+
attribute :version, getter: 1.0
|
268
|
+
attribute :type, getter: 'documentation'
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
ExampleRepresenter.new({}).to_hash
|
273
|
+
|
274
|
+
{
|
275
|
+
version: 1.0,
|
276
|
+
type: 'documentation',
|
277
|
+
}
|
278
|
+
```
|
279
|
+
|
194
280
|
### `namespace`
|
195
281
|
|
196
282
|
### `object`
|
@@ -223,10 +309,9 @@ bin/console
|
|
223
309
|
|
224
310
|
## Contributing
|
225
311
|
|
226
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
227
|
-
|
312
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/distribusion/supa.
|
313
|
+
This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
228
314
|
|
229
315
|
## License
|
230
316
|
|
231
317
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
232
|
-
|
data/Rakefile
CHANGED
@@ -1,14 +1,6 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
|
-
require '
|
2
|
+
require 'rspec/core/rake_task'
|
3
3
|
|
4
|
-
|
5
|
-
t.libs << %w(spec lib)
|
6
|
-
t.test_files = FileList['spec/**/*_spec.rb']
|
7
|
-
end
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
8
5
|
|
9
|
-
|
10
|
-
t.libs << %w(spec lib)
|
11
|
-
t.test_files = FileList['spec/benchmarks/**/*_bench.rb']
|
12
|
-
end
|
13
|
-
|
14
|
-
task :default => :test
|
6
|
+
task default: :spec
|
data/bin/console
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'supa'
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +10,5 @@ require "supa"
|
|
10
10
|
# require "pry"
|
11
11
|
# Pry.start
|
12
12
|
|
13
|
-
require
|
14
|
-
|
13
|
+
require 'pry-byebug'
|
14
|
+
Pry.start
|
data/lib/supa.rb
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
require 'supa/version'
|
2
|
-
require 'supa/builder'
|
3
2
|
require 'supa/representable'
|
3
|
+
require 'supa/command'
|
4
|
+
require 'supa/commands/attribute'
|
5
|
+
require 'supa/commands/virtual'
|
6
|
+
require 'supa/commands/object'
|
7
|
+
require 'supa/commands/namespace'
|
8
|
+
require 'supa/commands/collection'
|
9
|
+
require 'supa/commands/append'
|
10
|
+
|
11
|
+
require 'supa/builder'
|
4
12
|
|
5
13
|
module Supa
|
6
14
|
end
|
data/lib/supa/builder.rb
CHANGED
@@ -1,43 +1,32 @@
|
|
1
|
-
require 'supa/commands/attribute'
|
2
|
-
require 'supa/commands/virtual'
|
3
|
-
require 'supa/commands/object'
|
4
|
-
require 'supa/commands/namespace'
|
5
|
-
require 'supa/commands/collection'
|
6
|
-
require 'supa/commands/append'
|
7
|
-
|
8
1
|
module Supa
|
9
2
|
class Builder
|
10
3
|
COMMANDS = %w(attribute virtual object namespace collection append).freeze
|
11
4
|
|
5
|
+
def initialize(subject, representer:, tree:)
|
6
|
+
@subject = subject
|
7
|
+
@representer = representer
|
8
|
+
@tree = tree
|
9
|
+
end
|
10
|
+
|
12
11
|
COMMANDS.each do |command|
|
13
12
|
klass = Supa::Commands.const_get(command.capitalize)
|
14
13
|
|
15
|
-
define_method
|
16
|
-
klass.new(
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
14
|
+
define_method(command) do |name, options = {}, &block|
|
15
|
+
klass.new(@subject,
|
16
|
+
representer: @representer,
|
17
|
+
tree: @tree,
|
18
|
+
name: name,
|
19
|
+
options: options,
|
20
|
+
&block).represent
|
22
21
|
end
|
23
22
|
end
|
24
23
|
|
25
|
-
def initialize(representer:, context:, tree:)
|
26
|
-
@representer = representer
|
27
|
-
@context = context
|
28
|
-
@tree = tree
|
29
|
-
end
|
30
|
-
|
31
24
|
def to_hash
|
32
|
-
tree.to_hash
|
25
|
+
@tree.to_hash
|
33
26
|
end
|
34
27
|
|
35
28
|
def to_json
|
36
29
|
to_hash.to_json
|
37
30
|
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
attr_reader :representer, :context, :tree
|
42
31
|
end
|
43
32
|
end
|
data/lib/supa/command.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Supa
|
2
2
|
class Command
|
3
|
-
def initialize(representer:,
|
3
|
+
def initialize(subject, representer:, tree:, name:, options: {}, &block)
|
4
|
+
@subject = subject
|
4
5
|
@representer = representer
|
5
|
-
@context = context
|
6
6
|
@tree = tree
|
7
7
|
@name = name
|
8
8
|
@options = options
|
@@ -14,50 +14,47 @@ module Supa
|
|
14
14
|
end
|
15
15
|
|
16
16
|
private
|
17
|
-
attr_reader :representer, :context, :tree, :name, :options, :block
|
18
17
|
|
19
|
-
def
|
20
|
-
|
18
|
+
def value
|
19
|
+
return @representer.send(@options[:modifier], apply_render_flags(raw_value)) if @options[:modifier]
|
20
|
+
apply_render_flags(raw_value)
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
|
23
|
+
def apply_render_flags(val)
|
24
|
+
val
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
28
|
-
|
27
|
+
def raw_value
|
28
|
+
exec_on_representer? ? value_from_representer : value_from_subject
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
34
|
-
apply_modifier(value)
|
31
|
+
def value_from_subject
|
32
|
+
return @subject[getter] if @subject.is_a?(Hash)
|
33
|
+
@subject.send(getter) if @subject
|
35
34
|
end
|
36
35
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
else
|
41
|
-
value_from_representer
|
42
|
-
end
|
36
|
+
def value_from_representer
|
37
|
+
@representer.send(getter)
|
38
|
+
end
|
43
39
|
|
44
|
-
|
40
|
+
def exec_on_representer?
|
41
|
+
@options[:exec_context] == :representer
|
45
42
|
end
|
46
43
|
|
47
|
-
def
|
48
|
-
options[:
|
44
|
+
def getter
|
45
|
+
@options[:getter] || @name
|
49
46
|
end
|
50
47
|
|
51
|
-
def
|
52
|
-
|
48
|
+
def hide_when_empty?
|
49
|
+
@options.fetch(:hide_when_empty, false)
|
53
50
|
end
|
54
51
|
|
55
|
-
def
|
56
|
-
|
52
|
+
def empty_when_nil?
|
53
|
+
@options.fetch(:empty_when_nil, false)
|
57
54
|
end
|
58
55
|
|
59
|
-
def
|
60
|
-
|
56
|
+
def hide?
|
57
|
+
false
|
61
58
|
end
|
62
59
|
end
|
63
60
|
end
|