onsi 0.3.0 → 0.4.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/.circleci/config.yml +4 -0
- data/Gemfile.lock +1 -1
- data/lib/onsi/controller.rb +2 -13
- data/lib/onsi/includes.rb +56 -0
- data/lib/onsi/params.rb +11 -1
- data/lib/onsi/resource.rb +116 -12
- data/lib/onsi/version.rb +1 -1
- data/lib/onsi.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 11cdb10f50e5e342639f7957e3e2cf867decc2773065232c3a880983936a5122
|
|
4
|
+
data.tar.gz: f37f95aaddd5d3736a7f165b4362876ef7a7a60865bae5183b7b850ba4ad6746
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fce49cd88116a547bd44bdc835b5def7a2dc5d54b07360d0185bf99008ba66c02a7821dadcc77cf9909bc62549ce57af5d30fd27c1eed9068d67041bdd943638
|
|
7
|
+
data.tar.gz: 452661c725d56fc43dd03a16499321614063830a4cfc6d4af29fb122d6c8349e71f4d122d8d56637fa80eaee80bc89be3a36e55a7aa6b20415db83ffaae6e2e4
|
data/.circleci/config.yml
CHANGED
|
@@ -16,6 +16,7 @@ jobs:
|
|
|
16
16
|
command: |
|
|
17
17
|
curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
|
18
18
|
chmod +x ./cc-test-reporter
|
|
19
|
+
- run: gem install bundler
|
|
19
20
|
- restore_cache:
|
|
20
21
|
keys:
|
|
21
22
|
- v1-gems-latest-{{ checksum "onsi.gemspec" }}
|
|
@@ -44,6 +45,7 @@ jobs:
|
|
|
44
45
|
working_directory: ~/repo
|
|
45
46
|
steps:
|
|
46
47
|
- checkout
|
|
48
|
+
- run: gem install bundler
|
|
47
49
|
- restore_cache:
|
|
48
50
|
keys:
|
|
49
51
|
- v1-gems-build_2_5-{{ checksum "onsi.gemspec" }}
|
|
@@ -65,6 +67,7 @@ jobs:
|
|
|
65
67
|
working_directory: ~/repo
|
|
66
68
|
steps:
|
|
67
69
|
- checkout
|
|
70
|
+
- run: gem install bundler
|
|
68
71
|
- restore_cache:
|
|
69
72
|
keys:
|
|
70
73
|
- v1-gems-build_2_4-{{ checksum "onsi.gemspec" }}
|
|
@@ -86,6 +89,7 @@ jobs:
|
|
|
86
89
|
working_directory: ~/repo
|
|
87
90
|
steps:
|
|
88
91
|
- checkout
|
|
92
|
+
- run: gem install bundler
|
|
89
93
|
- restore_cache:
|
|
90
94
|
keys:
|
|
91
95
|
- v1-gems-build_2_3-{{ checksum "onsi.gemspec" }}
|
data/Gemfile.lock
CHANGED
data/lib/onsi/controller.rb
CHANGED
|
@@ -17,22 +17,11 @@ module Onsi
|
|
|
17
17
|
|
|
18
18
|
def render_resource(resource, opts = {})
|
|
19
19
|
version = opts.delete(:version) || self.class.render_version || Model::DEFAULT_API_VERSION
|
|
20
|
-
payload =
|
|
20
|
+
payload = Resource.render(resource, version)
|
|
21
21
|
render_options = {}
|
|
22
|
-
render_options[:json] =
|
|
22
|
+
render_options[:json] = payload
|
|
23
23
|
render_options.merge!(opts)
|
|
24
24
|
render(render_options)
|
|
25
25
|
end
|
|
26
|
-
|
|
27
|
-
def format_resource(resource, version)
|
|
28
|
-
case resource
|
|
29
|
-
when Onsi::Resource
|
|
30
|
-
resource
|
|
31
|
-
when Enumerable
|
|
32
|
-
resource.map { |res| format_resource(res, version) }
|
|
33
|
-
else
|
|
34
|
-
Onsi::Resource.new(resource, version)
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
26
|
end
|
|
38
27
|
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module Onsi
|
|
2
|
+
class Includes
|
|
3
|
+
attr_reader :included
|
|
4
|
+
|
|
5
|
+
def initialize(included)
|
|
6
|
+
@included = parse_included(included)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def method_missing(name, *args, &block)
|
|
10
|
+
if name =~ /\Afetch_(.*)/
|
|
11
|
+
add_fetch_method(name.to_s.gsub(/\Afetch_/, ''), *args, &block)
|
|
12
|
+
else
|
|
13
|
+
super
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def load_included
|
|
18
|
+
@load_included ||= {}.tap do |root|
|
|
19
|
+
included.each do |name|
|
|
20
|
+
fetcher = fetch_methods[name]
|
|
21
|
+
next if fetcher.nil?
|
|
22
|
+
results = fetcher.call
|
|
23
|
+
root[name] = results
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def fetch_methods
|
|
31
|
+
@fetch_methods ||= {}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def add_fetch_method(name, &block)
|
|
35
|
+
if block.nil?
|
|
36
|
+
raise ArgumentError, "Must specify a block for fetch_#{name}"
|
|
37
|
+
end
|
|
38
|
+
fetch_methods[name.to_sym] = block
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def parse_included(included)
|
|
42
|
+
case included
|
|
43
|
+
when Enumerable
|
|
44
|
+
included.map(&:to_sym)
|
|
45
|
+
when String
|
|
46
|
+
included.split(',').map(&:to_sym)
|
|
47
|
+
when Symbol
|
|
48
|
+
Array(included)
|
|
49
|
+
when nil
|
|
50
|
+
[]
|
|
51
|
+
else
|
|
52
|
+
raise ArgumentError, "Onsi::Includes unknown included type #{included}"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
data/lib/onsi/params.rb
CHANGED
|
@@ -72,8 +72,12 @@ module Onsi
|
|
|
72
72
|
attributes.to_h.merge(relationships.to_h).with_indifferent_access
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
+
def fetch(key, default = nil)
|
|
76
|
+
attrs_hash[key] || default
|
|
77
|
+
end
|
|
78
|
+
|
|
75
79
|
def require(key)
|
|
76
|
-
value =
|
|
80
|
+
value = attrs_hash[key]
|
|
77
81
|
if value.nil?
|
|
78
82
|
raise MissingReqiredAttribute.new("Missing attribute #{key}", key)
|
|
79
83
|
end
|
|
@@ -85,5 +89,11 @@ module Onsi
|
|
|
85
89
|
rescue ActiveRecord::RecordNotFound
|
|
86
90
|
raise RelationshipNotFound.new("Can't find relationship #{key}", key)
|
|
87
91
|
end
|
|
92
|
+
|
|
93
|
+
private
|
|
94
|
+
|
|
95
|
+
def attrs_hash
|
|
96
|
+
@attrs_hash ||= attributes.to_h.with_indifferent_access
|
|
97
|
+
end
|
|
88
98
|
end
|
|
89
99
|
end
|
data/lib/onsi/resource.rb
CHANGED
|
@@ -1,38 +1,107 @@
|
|
|
1
1
|
module Onsi
|
|
2
2
|
class Resource
|
|
3
|
-
attr_reader :object, :version
|
|
3
|
+
attr_reader :object, :version, :includes
|
|
4
|
+
|
|
5
|
+
TYPE_KEY = 'type'.freeze
|
|
6
|
+
ID_KEY = 'id'.freeze
|
|
7
|
+
ATTRIBUTES_KEY = 'attributes'.freeze
|
|
8
|
+
RELATIONSHIPS_KEY = 'relationships'.freeze
|
|
9
|
+
META_KEY = 'meta'.freeze
|
|
10
|
+
DATA_KEY = 'data'.freeze
|
|
11
|
+
INCLUDED_KEY = 'included'.freeze
|
|
4
12
|
|
|
5
13
|
class InvalidResourceError < StandardError; end
|
|
6
14
|
|
|
7
|
-
|
|
15
|
+
class << self
|
|
16
|
+
def as_resource(resource, version)
|
|
17
|
+
case resource
|
|
18
|
+
when Onsi::Resource
|
|
19
|
+
resource
|
|
20
|
+
when Enumerable
|
|
21
|
+
resource.map { |res| as_resource(res, version) }
|
|
22
|
+
else
|
|
23
|
+
Onsi::Resource.new(resource, version)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def render(resource, version)
|
|
28
|
+
resources = as_resource(resource, version)
|
|
29
|
+
{}.tap do |root|
|
|
30
|
+
root[DATA_KEY] = resources.as_json
|
|
31
|
+
included = all_included(resources)
|
|
32
|
+
if included.any?
|
|
33
|
+
root[INCLUDED_KEY] = included
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def all_included(resources)
|
|
39
|
+
Array(resources).map(&:flat_includes).flatten.uniq do |res|
|
|
40
|
+
"#{res[TYPE_KEY]}-#{res[ID_KEY]}"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def initialize(object, version = nil, includes: nil)
|
|
8
46
|
@object = object
|
|
9
|
-
@version = version
|
|
47
|
+
@version = version || Model::DEFAULT_API_VERSION
|
|
48
|
+
@includes = includes
|
|
10
49
|
validate!
|
|
11
50
|
end
|
|
12
51
|
|
|
13
52
|
def as_json(_opts = {})
|
|
14
53
|
{}.tap do |root|
|
|
15
|
-
root[
|
|
16
|
-
root[
|
|
17
|
-
root[
|
|
18
|
-
|
|
19
|
-
root
|
|
20
|
-
|
|
21
|
-
root['meta'] = meta if meta.any?
|
|
54
|
+
root[TYPE_KEY] = type
|
|
55
|
+
root[ID_KEY] = object.id.to_s
|
|
56
|
+
root[ATTRIBUTES_KEY] = generate_attributes
|
|
57
|
+
append_relationships(root)
|
|
58
|
+
append_meta(root)
|
|
59
|
+
append_includes(root)
|
|
22
60
|
end
|
|
23
61
|
end
|
|
24
62
|
|
|
63
|
+
def rendered_includes
|
|
64
|
+
@rendered_includes ||= perform_render_includes
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def flat_includes
|
|
68
|
+
rendered_includes.values.map { |root| root[DATA_KEY] }.flatten
|
|
69
|
+
end
|
|
70
|
+
|
|
25
71
|
private
|
|
26
72
|
|
|
27
73
|
def validate!
|
|
28
|
-
|
|
29
|
-
|
|
74
|
+
unless object.class.included_modules.include?(Onsi::Model)
|
|
75
|
+
raise InvalidResourceError, "Trying to render a #{object.class.name}. But it doesn't include Onsi::Model"
|
|
76
|
+
end
|
|
77
|
+
if includes.present? && !includes.is_a?(Onsi::Includes)
|
|
78
|
+
raise InvalidResourceError, "Included resources in #{self} is not a Onsi::Includes"
|
|
79
|
+
end
|
|
30
80
|
end
|
|
31
81
|
|
|
32
82
|
def type
|
|
33
83
|
object.class.api_renderer(version, for_render: true).type || object.class.name.underscore
|
|
34
84
|
end
|
|
35
85
|
|
|
86
|
+
def append_relationships(root)
|
|
87
|
+
relationships = generate_relationships
|
|
88
|
+
return unless relationships.any?
|
|
89
|
+
root[RELATIONSHIPS_KEY] = relationships
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def append_meta(root)
|
|
93
|
+
meta = generate_metadata
|
|
94
|
+
return unless meta.any?
|
|
95
|
+
root[META_KEY] = meta
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def append_includes(root)
|
|
99
|
+
includes = generate_includes
|
|
100
|
+
return unless includes.any?
|
|
101
|
+
root[RELATIONSHIPS_KEY] ||= {}
|
|
102
|
+
root[RELATIONSHIPS_KEY].merge!(includes)
|
|
103
|
+
end
|
|
104
|
+
|
|
36
105
|
def generate_attributes
|
|
37
106
|
object.class.api_renderer(version, for_render: true).render_attributes(object)
|
|
38
107
|
end
|
|
@@ -44,5 +113,40 @@ module Onsi
|
|
|
44
113
|
def generate_metadata
|
|
45
114
|
object.class.api_renderer(version, for_render: true).render_metadata(object)
|
|
46
115
|
end
|
|
116
|
+
|
|
117
|
+
def generate_includes
|
|
118
|
+
{}.tap do |root|
|
|
119
|
+
rendered_includes.each do |key, values|
|
|
120
|
+
included = values[DATA_KEY]
|
|
121
|
+
case included
|
|
122
|
+
when Array
|
|
123
|
+
root[key] = {}.tap do |subobj|
|
|
124
|
+
subobj[DATA_KEY] = included.map do |inc|
|
|
125
|
+
{
|
|
126
|
+
TYPE_KEY => inc[TYPE_KEY],
|
|
127
|
+
ID_KEY => inc[ID_KEY]
|
|
128
|
+
}
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
when Hash
|
|
132
|
+
root[key] = { DATA_KEY => { TYPE_KEY => included[TYPE_KEY], ID_KEY => included[ID_KEY] } }
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def perform_render_includes
|
|
139
|
+
included = includes&.load_included
|
|
140
|
+
{}.tap do |root|
|
|
141
|
+
Hash(included).each do |key, results|
|
|
142
|
+
root[key.to_s] = {}
|
|
143
|
+
root[key.to_s][DATA_KEY] = render_included(results)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def render_included(resources)
|
|
149
|
+
Resource.as_resource(resources, version).as_json
|
|
150
|
+
end
|
|
47
151
|
end
|
|
48
152
|
end
|
data/lib/onsi/version.rb
CHANGED
data/lib/onsi.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: onsi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Skylar Schipper
|
|
@@ -166,6 +166,7 @@ files:
|
|
|
166
166
|
- lib/onsi/controller.rb
|
|
167
167
|
- lib/onsi/error_responder.rb
|
|
168
168
|
- lib/onsi/errors.rb
|
|
169
|
+
- lib/onsi/includes.rb
|
|
169
170
|
- lib/onsi/model.rb
|
|
170
171
|
- lib/onsi/params.rb
|
|
171
172
|
- lib/onsi/resource.rb
|