lhs 2.2.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +296 -30
- data/lhs.gemspec +3 -3
- data/lib/lhs.rb +0 -7
- data/lib/lhs/collection.rb +4 -4
- data/lib/lhs/concerns/item/destroy.rb +2 -2
- data/lib/lhs/concerns/item/save.rb +3 -3
- data/lib/lhs/concerns/item/update.rb +2 -2
- data/lib/lhs/concerns/item/validation.rb +4 -5
- data/lib/lhs/concerns/{service → record}/all.rb +2 -2
- data/lib/lhs/concerns/{service → record}/batch.rb +3 -3
- data/lib/lhs/concerns/{service → record}/create.rb +4 -3
- data/lib/lhs/concerns/{service → record}/endpoints.rb +6 -6
- data/lib/lhs/concerns/{service → record}/find.rb +3 -2
- data/lib/lhs/concerns/{service → record}/find_by.rb +3 -2
- data/lib/lhs/concerns/{service → record}/first.rb +1 -1
- data/lib/lhs/concerns/{service → record}/includes.rb +4 -2
- data/lib/lhs/concerns/{service → record}/mapping.rb +1 -1
- data/lib/lhs/concerns/{service → record}/model.rb +1 -1
- data/lib/lhs/concerns/{service → record}/request.rb +12 -12
- data/lib/lhs/concerns/{service → record}/where.rb +3 -2
- data/lib/lhs/data.rb +25 -53
- data/lib/lhs/endpoint.rb +2 -2
- data/lib/lhs/item.rb +8 -2
- data/lib/lhs/proxy.rb +2 -2
- data/lib/lhs/record.rb +42 -0
- data/lib/lhs/version.rb +1 -1
- data/spec/collection/meta_data_spec.rb +2 -2
- data/spec/collection/without_object_items_spec.rb +1 -1
- data/spec/data/item_spec.rb +2 -14
- data/spec/data/merge_spec.rb +3 -3
- data/spec/data/raw_spec.rb +1 -1
- data/spec/data/respond_to_spec.rb +3 -3
- data/spec/data/root_spec.rb +2 -2
- data/spec/data/to_json_spec.rb +2 -2
- data/spec/endpoint/for_url_spec.rb +1 -1
- data/spec/item/delegate_spec.rb +2 -2
- data/spec/item/destroy_spec.rb +4 -4
- data/spec/item/errors_spec.rb +4 -4
- data/spec/item/getter_spec.rb +2 -2
- data/spec/item/internal_data_structure_spec.rb +1 -1
- data/spec/item/save_spec.rb +3 -4
- data/spec/item/setter_spec.rb +2 -2
- data/spec/item/update_spec.rb +2 -2
- data/spec/item/validation_spec.rb +47 -75
- data/spec/proxy/load_spec.rb +2 -2
- data/spec/{service → record}/all_spec.rb +7 -7
- data/spec/{service → record}/build_spec.rb +5 -4
- data/spec/{service → record}/create_spec.rb +6 -5
- data/spec/{service → record}/creation_failed_spec.rb +6 -5
- data/spec/record/definitions_spec.rb +29 -0
- data/spec/{service → record}/endpoint_misconfiguration_spec.rb +3 -3
- data/spec/{service → record}/endpoint_options_spec.rb +4 -4
- data/spec/{service → record}/endpoints_spec.rb +15 -15
- data/spec/{service → record}/find_by_spec.rb +8 -8
- data/spec/{service → record}/find_each_spec.rb +3 -3
- data/spec/{service → record}/find_in_batches_spec.rb +6 -6
- data/spec/{service → record}/find_spec.rb +10 -9
- data/spec/{service → record}/first_spec.rb +7 -6
- data/spec/{service → record}/includes_spec.rb +7 -7
- data/spec/{service → record}/mapping_spec.rb +27 -16
- data/spec/{service → record}/model_name_spec.rb +2 -2
- data/spec/{service → record}/new_spec.rb +4 -3
- data/spec/{service → record}/request_spec.rb +3 -3
- data/spec/record/where_spec.rb +34 -0
- data/spec/support/cleanup_endpoints.rb +1 -1
- data/spec/support/{cleanup_services.rb → cleanup_records.rb} +2 -2
- metadata +60 -67
- data/docs/collections.md +0 -28
- data/docs/data.md +0 -39
- data/docs/items.md +0 -79
- data/docs/service.jpg +0 -0
- data/docs/service.pdf +2 -650
- data/docs/services.md +0 -266
- data/lib/lhs/concerns/service/build.rb +0 -19
- data/lib/lhs/service.rb +0 -18
- data/spec/data/pagination_spec.rb +0 -60
- data/spec/dummy/README.rdoc +0 -28
- data/spec/service/where_spec.rb +0 -33
@@ -14,9 +14,9 @@ class LHS::Item < LHS::Proxy
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def update!(params)
|
17
|
-
|
17
|
+
record = _data._root._record_class
|
18
18
|
_data.merge_raw!(LHS::Data.new(params))
|
19
|
-
response_data =
|
19
|
+
response_data = record.request(
|
20
20
|
method: :post,
|
21
21
|
url: href,
|
22
22
|
body: _data.to_json,
|
@@ -8,11 +8,10 @@ class LHS::Item < LHS::Proxy
|
|
8
8
|
def valid?
|
9
9
|
self.errors = nil
|
10
10
|
fail 'No validation endpoint found!' unless validation_endpoint
|
11
|
-
|
12
|
-
|
13
|
-
params = validation_endpoint.options.fetch(:params, {}).merge(validation_params)
|
11
|
+
record = LHS::Record.for_url(validation_endpoint.url)
|
12
|
+
params = validation_endpoint.options.fetch(:params, {}).merge(persist: false)
|
14
13
|
begin
|
15
|
-
|
14
|
+
record.request(
|
16
15
|
url: validation_endpoint.url,
|
17
16
|
method: :post,
|
18
17
|
params: params,
|
@@ -30,7 +29,7 @@ class LHS::Item < LHS::Proxy
|
|
30
29
|
private
|
31
30
|
|
32
31
|
def validation_endpoint
|
33
|
-
endpoint = _data.
|
32
|
+
endpoint = _data._record_class.find_endpoint(_data._raw)
|
34
33
|
endpoint ||= LHS::Endpoint.for_url(_data.href) if _data.href
|
35
34
|
validates = endpoint.options && endpoint.options.fetch(:validates, false)
|
36
35
|
fail 'Endpoint does not support validations!' unless validates
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'active_support'
|
2
2
|
|
3
|
-
class LHS::
|
3
|
+
class LHS::Record
|
4
4
|
|
5
5
|
module All
|
6
6
|
extend ActiveSupport::Concern
|
@@ -26,7 +26,7 @@ class LHS::Service
|
|
26
26
|
all.concat request(params: params.merge(limit: limit, offset: offset))._raw[:items]
|
27
27
|
end
|
28
28
|
end
|
29
|
-
LHS::Data.new(all, nil, self)
|
29
|
+
data._record_class.new(LHS::Data.new(all, nil, self))
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'active_support'
|
2
2
|
|
3
|
-
class LHS::
|
3
|
+
class LHS::Record
|
4
4
|
|
5
5
|
module Batch
|
6
6
|
extend ActiveSupport::Concern
|
@@ -12,7 +12,7 @@ class LHS::Service
|
|
12
12
|
find_in_batches(options) do |data|
|
13
13
|
data.each do |record|
|
14
14
|
item = LHS::Item.new(LHS::Data.new(record, data, self))
|
15
|
-
yield LHS::Data.new(item, data, self)
|
15
|
+
yield self.new(LHS::Data.new(item, data, self))
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -27,7 +27,7 @@ class LHS::Service
|
|
27
27
|
data = request(params: params.merge(limit: batch_size, offset: start))
|
28
28
|
batch_size = data._raw[:limit]
|
29
29
|
left = data._raw[:total].to_i - data._raw[:offset].to_i - data._raw[:limit].to_i
|
30
|
-
yield data
|
30
|
+
yield self.new(data)
|
31
31
|
break if left <= 0
|
32
32
|
start += batch_size
|
33
33
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'active_support'
|
2
2
|
|
3
|
-
class LHS::
|
3
|
+
class LHS::Record
|
4
4
|
|
5
5
|
module Create
|
6
6
|
extend ActiveSupport::Concern
|
@@ -14,12 +14,13 @@ class LHS::Service
|
|
14
14
|
data = LHS::Data.new(json, nil, self, e.response.request)
|
15
15
|
item = LHS::Item.new(data)
|
16
16
|
item.errors = LHS::Errors.new(e.response)
|
17
|
-
LHS::Data.new(item, data)
|
17
|
+
data._record_class.new(LHS::Data.new(item, data))
|
18
18
|
end
|
19
19
|
|
20
20
|
def create!(data = {})
|
21
21
|
url = compute_url!(data)
|
22
|
-
request(url: url, method: :post, body: data.to_json, headers: {'Content-Type' => 'application/json'})
|
22
|
+
data = request(url: url, method: :post, body: data.to_json, headers: {'Content-Type' => 'application/json'})
|
23
|
+
data._record_class.new(data)
|
23
24
|
end
|
24
25
|
end
|
25
26
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'active_support'
|
2
2
|
|
3
|
-
class LHS::
|
3
|
+
class LHS::Record
|
4
4
|
|
5
5
|
# An endpoint is an url that leads to a backend resource.
|
6
|
-
# A
|
6
|
+
# A record can contain multiple endpoints.
|
7
7
|
# The endpoint that is used to request data is choosen
|
8
8
|
# based on the provided parameters.
|
9
9
|
module Endpoints
|
@@ -26,16 +26,16 @@ class LHS::Service
|
|
26
26
|
endpoint = LHC::Endpoint.new(url, options)
|
27
27
|
sanity_check(endpoint)
|
28
28
|
endpoints.push(endpoint)
|
29
|
-
LHS::
|
30
|
-
LHS::
|
29
|
+
LHS::Record::Endpoints.all ||= {}
|
30
|
+
LHS::Record::Endpoints.all[url] = self
|
31
31
|
end
|
32
32
|
|
33
33
|
def for_url(url)
|
34
34
|
return unless url
|
35
|
-
template,
|
35
|
+
template, record = LHS::Record::Endpoints.all.detect do |template, _record_class|
|
36
36
|
LHC::Endpoint.match?(url, template)
|
37
37
|
end
|
38
|
-
|
38
|
+
record
|
39
39
|
end
|
40
40
|
|
41
41
|
# Find an endpoint based on the provided parameters.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'active_support'
|
2
2
|
|
3
|
-
class LHS::
|
3
|
+
class LHS::Record
|
4
4
|
|
5
5
|
module Find
|
6
6
|
extend ActiveSupport::Concern
|
@@ -9,11 +9,12 @@ class LHS::Service
|
|
9
9
|
|
10
10
|
# Find a single uniqe record
|
11
11
|
def find(args)
|
12
|
-
if args.is_a? Hash
|
12
|
+
data = if args.is_a? Hash
|
13
13
|
find_with_parameters(args)
|
14
14
|
else
|
15
15
|
find_by_id(args)
|
16
16
|
end
|
17
|
+
data._record_class.new(data)
|
17
18
|
end
|
18
19
|
|
19
20
|
private
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'active_support'
|
2
2
|
|
3
|
-
class LHS::
|
3
|
+
class LHS::Record
|
4
4
|
|
5
5
|
module FindBy
|
6
6
|
extend ActiveSupport::Concern
|
@@ -24,11 +24,12 @@ class LHS::Service
|
|
24
24
|
def _find_by(params)
|
25
25
|
params = params.dup.merge(limit: 1)
|
26
26
|
data = request(params: params)
|
27
|
-
if data._proxy.is_a?(LHS::Collection)
|
27
|
+
data = if data._proxy.is_a?(LHS::Collection)
|
28
28
|
data.first || fail(LHC::NotFound.new('No item was found.', data._request.response))
|
29
29
|
else
|
30
30
|
data
|
31
31
|
end
|
32
|
+
data._record_class.new(data)
|
32
33
|
end
|
33
34
|
end
|
34
35
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'active_support'
|
2
2
|
|
3
|
-
class LHS::
|
3
|
+
class LHS::Record
|
4
4
|
|
5
5
|
module Includes
|
6
6
|
extend ActiveSupport::Concern
|
@@ -16,7 +16,9 @@ class LHS::Service
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def includes(*args)
|
19
|
-
|
19
|
+
name = "#{self}#{args.object_id}"
|
20
|
+
constant = Object.const_set(name, self)
|
21
|
+
class_clone = constant
|
20
22
|
class_clone.endpoints = endpoints
|
21
23
|
class_clone.mapping = mapping
|
22
24
|
class_clone.including = args.size == 1 ? args[0] : args
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'active_support'
|
2
2
|
|
3
|
-
class LHS::
|
3
|
+
class LHS::Record
|
4
4
|
|
5
5
|
module Request
|
6
6
|
extend ActiveSupport::Concern
|
@@ -71,12 +71,12 @@ class LHS::Service
|
|
71
71
|
|
72
72
|
# Load additional resources that are requested with include
|
73
73
|
def load_include(options, data, sub_includes)
|
74
|
-
|
75
|
-
options = convert_options_to_endpoints(options) if
|
74
|
+
record = record_for_options(options) || self
|
75
|
+
options = convert_options_to_endpoints(options) if record_for_options(options)
|
76
76
|
begin
|
77
|
-
|
77
|
+
record.includes(sub_includes).request(options)
|
78
78
|
rescue LHC::NotFound
|
79
|
-
LHS::Data.new({}, data,
|
79
|
+
LHS::Data.new({}, data, record)
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
@@ -116,17 +116,17 @@ class LHS::Service
|
|
116
116
|
options
|
117
117
|
end
|
118
118
|
|
119
|
-
def
|
120
|
-
|
119
|
+
def record_for_options(options)
|
120
|
+
records = []
|
121
121
|
if options.is_a?(Array)
|
122
122
|
options.each do |option|
|
123
|
-
next unless
|
124
|
-
|
123
|
+
next unless record = LHS::Record.for_url(option[:url])
|
124
|
+
records.push(record)
|
125
125
|
end
|
126
|
-
fail 'Found more than one
|
127
|
-
|
126
|
+
fail 'Found more than one record that could be used to do the request' if records.uniq.count > 1
|
127
|
+
records.uniq.first
|
128
128
|
else # Hash
|
129
|
-
LHS::
|
129
|
+
LHS::Record.for_url(options[:url])
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'active_support'
|
2
2
|
|
3
|
-
class LHS::
|
3
|
+
class LHS::Record
|
4
4
|
|
5
5
|
module Where
|
6
6
|
extend ActiveSupport::Concern
|
@@ -9,7 +9,8 @@ class LHS::Service
|
|
9
9
|
|
10
10
|
# Used to query data from the service.
|
11
11
|
def where(params = {})
|
12
|
-
request(params: params)
|
12
|
+
data = request(params: params)
|
13
|
+
data._record_class.new(data)
|
13
14
|
end
|
14
15
|
end
|
15
16
|
end
|
data/lib/lhs/data.rb
CHANGED
@@ -6,12 +6,12 @@ class LHS::Data
|
|
6
6
|
include Json
|
7
7
|
|
8
8
|
# prevent clashing with attributes of underlying data
|
9
|
-
attr_accessor :_proxy, :_raw, :_parent, :
|
9
|
+
attr_accessor :_proxy, :_raw, :_parent, :_record_class, :_request
|
10
10
|
|
11
|
-
def initialize(input, parent = nil,
|
11
|
+
def initialize(input, parent = nil, record = nil, request = nil)
|
12
12
|
self._raw = raw_from_input(input)
|
13
13
|
self._proxy = proxy_from_input(input)
|
14
|
-
self.
|
14
|
+
self._record_class = record
|
15
15
|
self._parent = parent
|
16
16
|
self._request = request
|
17
17
|
end
|
@@ -30,7 +30,7 @@ class LHS::Data
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def class
|
33
|
-
_root.
|
33
|
+
_root._record_class
|
34
34
|
end
|
35
35
|
|
36
36
|
# enforce internal data structure to have deep symbolized keys
|
@@ -39,48 +39,18 @@ class LHS::Data
|
|
39
39
|
@_raw = raw
|
40
40
|
end
|
41
41
|
|
42
|
-
def
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
def first_page
|
47
|
-
1
|
48
|
-
end
|
49
|
-
|
50
|
-
def last_page
|
51
|
-
total_pages
|
52
|
-
end
|
53
|
-
|
54
|
-
def prev_page
|
55
|
-
current_page - 1
|
56
|
-
end
|
57
|
-
|
58
|
-
def next_page
|
59
|
-
current_page + 1
|
60
|
-
end
|
61
|
-
|
62
|
-
def limit_value
|
63
|
-
limit
|
64
|
-
end
|
65
|
-
|
66
|
-
def total_pages
|
67
|
-
total / limit
|
42
|
+
def root_item?
|
43
|
+
root_item == self
|
68
44
|
end
|
69
45
|
|
70
46
|
protected
|
71
47
|
|
72
|
-
# Use existing mapping to provide data
|
73
|
-
# or forward to proxy
|
74
48
|
def method_missing(name, *args, &block)
|
75
|
-
|
76
|
-
self.instance_exec(&mapping)
|
77
|
-
else
|
78
|
-
_proxy.send(name, *args, &block)
|
79
|
-
end
|
49
|
+
_proxy.send(name, *args, &block)
|
80
50
|
end
|
81
51
|
|
82
52
|
def respond_to_missing?(name, include_all = false)
|
83
|
-
(root_item? && _root.
|
53
|
+
(root_item? && _root._record_class.instance_methods.include?(name)) ||
|
84
54
|
_proxy.respond_to?(name, include_all)
|
85
55
|
end
|
86
56
|
|
@@ -90,13 +60,6 @@ class LHS::Data
|
|
90
60
|
!! (input.is_a?(Hash) && input[:items]) || input.is_a?(Array) || _raw.is_a?(Array)
|
91
61
|
end
|
92
62
|
|
93
|
-
def mapping_for(name)
|
94
|
-
service = LHS::Service.for_url(_raw[:href]) if _raw.is_a?(Hash)
|
95
|
-
service ||= _root._service if root_item? && _root._service
|
96
|
-
return unless service
|
97
|
-
service.mapping[name]
|
98
|
-
end
|
99
|
-
|
100
63
|
def root_item
|
101
64
|
return if self._proxy.class != LHS::Item
|
102
65
|
root = root_item = self
|
@@ -111,10 +74,6 @@ class LHS::Data
|
|
111
74
|
root_item
|
112
75
|
end
|
113
76
|
|
114
|
-
def root_item?
|
115
|
-
root_item == self
|
116
|
-
end
|
117
|
-
|
118
77
|
def root?
|
119
78
|
_root == self
|
120
79
|
end
|
@@ -131,15 +90,28 @@ class LHS::Data
|
|
131
90
|
|
132
91
|
def raw_from_input(input)
|
133
92
|
if input.is_a?(String) && input.length > 0
|
134
|
-
|
93
|
+
raw_from_json_string(input)
|
135
94
|
elsif defined?(input._raw)
|
136
95
|
input._raw
|
137
96
|
elsif defined?(input._data)
|
138
97
|
input._data._raw
|
139
98
|
else
|
140
|
-
input
|
141
|
-
input.deep_symbolize_keys! if input.is_a?(Hash)
|
142
|
-
input
|
99
|
+
raw_from_anything_else(input)
|
143
100
|
end
|
144
101
|
end
|
102
|
+
|
103
|
+
def raw_from_json_string(input)
|
104
|
+
json = JSON.parse(input)
|
105
|
+
if json.is_a?(Hash)
|
106
|
+
json.deep_symbolize_keys
|
107
|
+
else
|
108
|
+
json
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def raw_from_anything_else(input)
|
113
|
+
input = input.to_hash if input.class != Hash && input.respond_to?(:to_hash)
|
114
|
+
input.deep_symbolize_keys! if input.is_a?(Hash)
|
115
|
+
input
|
116
|
+
end
|
145
117
|
end
|
data/lib/lhs/endpoint.rb
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
class LHS::Endpoint
|
3
3
|
|
4
4
|
def self.for_url(url)
|
5
|
-
template,
|
5
|
+
template, record = LHS::Record::Endpoints.all.detect do |template, _record_class|
|
6
6
|
LHC::Endpoint.match?(url, template)
|
7
7
|
end
|
8
|
-
|
8
|
+
record.endpoints.detect { |endpoint| endpoint.url == template } if record
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
data/lib/lhs/item.rb
CHANGED
@@ -58,7 +58,13 @@ class LHS::Item < LHS::Proxy
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def handle_hash(value)
|
61
|
-
LHS::
|
61
|
+
record = LHS::Record.for_url(value[:href]) if value[:href]
|
62
|
+
data = LHS::Data.new(value, _data)
|
63
|
+
if record
|
64
|
+
record.new(data)
|
65
|
+
else
|
66
|
+
data
|
67
|
+
end
|
62
68
|
end
|
63
69
|
|
64
70
|
def set(name, value)
|
@@ -81,6 +87,6 @@ class LHS::Item < LHS::Proxy
|
|
81
87
|
end
|
82
88
|
|
83
89
|
def date_time_regex
|
84
|
-
/(?<date>\d{4}-\d{2}-\d{2})?(?<time>T\d{2}:\d{2}:\d{2}
|
90
|
+
/(?<date>\d{4}-\d{2}-\d{2})?(?<time>T\d{2}:\d{2}:\d{2}\.\d*.\d{2}:\d{2})?/
|
85
91
|
end
|
86
92
|
end
|