lhs 3.0.0 → 3.0.1
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/.rubocop.localch.yml +190 -0
- data/.rubocop.yml +7 -0
- data/cider-ci.yml +2 -1
- data/cider-ci/jobs/rspec.yml +48 -0
- data/cider-ci/jobs/rubocop.yml +55 -0
- data/cider-ci/scripts/bundle.yml +2 -0
- data/cider-ci/scripts/github_comment.yml +6 -0
- data/cider-ci/scripts/rspec.yml +4 -0
- data/cider-ci/scripts/rubocop.yml +5 -0
- data/cider-ci/scripts/ruby-version.yml +2 -0
- data/cider-ci/scripts/tmp-cache.yml +2 -0
- data/lhs.gemspec +1 -0
- data/lib/lhs/collection.rb +2 -6
- data/lib/lhs/concerns/data/json.rb +1 -1
- data/lib/lhs/concerns/item/save.rb +11 -10
- data/lib/lhs/concerns/item/update.rb +1 -1
- data/lib/lhs/concerns/item/validation.rb +2 -2
- data/lib/lhs/concerns/record/all.rb +1 -2
- data/lib/lhs/concerns/record/batch.rb +2 -3
- data/lib/lhs/concerns/record/create.rb +7 -8
- data/lib/lhs/concerns/record/endpoints.rb +2 -3
- data/lib/lhs/concerns/record/find.rb +6 -6
- data/lib/lhs/concerns/record/find_by.rb +8 -8
- data/lib/lhs/concerns/record/first.rb +0 -1
- data/lib/lhs/concerns/record/includes.rb +0 -1
- data/lib/lhs/concerns/record/mapping.rb +0 -1
- data/lib/lhs/concerns/record/model.rb +0 -1
- data/lib/lhs/concerns/record/request.rb +18 -14
- data/lib/lhs/concerns/record/where.rb +0 -1
- data/lib/lhs/data.rb +3 -4
- data/lib/lhs/endpoint.rb +1 -2
- data/lib/lhs/errors.rb +7 -13
- data/lib/lhs/item.rb +5 -9
- data/lib/lhs/record.rb +12 -8
- data/lib/lhs/version.rb +1 -1
- data/spec/collection/delegate_spec.rb +0 -2
- data/spec/collection/enumerable_spec.rb +2 -4
- data/spec/collection/meta_data_spec.rb +0 -1
- data/spec/collection/respond_to_spec.rb +0 -1
- data/spec/collection/without_object_items_spec.rb +0 -1
- data/spec/data/collection_spec.rb +4 -7
- data/spec/data/item_spec.rb +3 -5
- data/spec/data/merge_spec.rb +7 -9
- data/spec/data/raw_spec.rb +3 -5
- data/spec/data/respond_to_spec.rb +3 -5
- data/spec/data/root_spec.rb +3 -5
- data/spec/data/select_spec.rb +2 -4
- data/spec/data/to_json_spec.rb +5 -7
- data/spec/dummy/bin/rails +1 -1
- data/spec/dummy/config.ru +1 -1
- data/spec/dummy/config/initializers/cookies_serializer.rb +1 -1
- data/spec/endpoint/for_url_spec.rb +3 -5
- data/spec/item/delegate_spec.rb +0 -2
- data/spec/item/destroy_spec.rb +3 -5
- data/spec/item/errors_spec.rb +20 -23
- data/spec/item/getter_spec.rb +1 -3
- data/spec/item/internal_data_structure_spec.rb +2 -3
- data/spec/item/respond_to_spec.rb +1 -1
- data/spec/item/save_spec.rb +7 -10
- data/spec/item/setter_spec.rb +2 -4
- data/spec/item/update_spec.rb +4 -7
- data/spec/item/validation_spec.rb +7 -9
- data/spec/proxy/load_spec.rb +0 -2
- data/spec/record/all_spec.rb +10 -12
- data/spec/record/build_spec.rb +0 -2
- data/spec/record/create_spec.rb +8 -10
- data/spec/record/creation_failed_spec.rb +4 -6
- data/spec/record/definitions_spec.rb +1 -3
- data/spec/record/endpoint_misconfiguration_spec.rb +2 -4
- data/spec/record/endpoint_options_spec.rb +0 -2
- data/spec/record/endpoints_spec.rb +1 -6
- data/spec/record/find_each_spec.rb +2 -4
- data/spec/record/find_in_batches_spec.rb +4 -6
- data/spec/record/find_spec.rb +10 -13
- data/spec/record/first_spec.rb +0 -3
- data/spec/record/includes_spec.rb +15 -20
- data/spec/record/mapping_spec.rb +13 -15
- data/spec/record/model_name_spec.rb +0 -2
- data/spec/record/new_spec.rb +4 -2
- data/spec/record/request_spec.rb +1 -3
- data/spec/record/where_spec.rb +1 -3
- data/spec/spec_helper.rb +1 -1
- data/spec/support/cleanup_configuration.rb +0 -2
- data/spec/support/cleanup_endpoints.rb +0 -1
- data/spec/support/cleanup_records.rb +0 -2
- metadata +26 -4
- data/cider-ci/contexts/rspec.yml +0 -16
- data/cider-ci/jobs/tests.yml +0 -27
@@ -6,7 +6,6 @@ class LHS::Record
|
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
module ClassMethods
|
9
|
-
|
10
9
|
# Should be an edge case but sometimes all objects from a certain resource
|
11
10
|
# are required. In this case we load the first page with the default max limit,
|
12
11
|
# compute the amount of left over requests, do all the the left over requests
|
@@ -22,7 +21,7 @@ class LHS::Record
|
|
22
21
|
if limit > 0
|
23
22
|
requests = total_left / limit
|
24
23
|
requests.times do |i|
|
25
|
-
offset = limit * (i+1) + 1
|
24
|
+
offset = limit * (i + 1) + 1
|
26
25
|
all.concat request(params: params.merge(limit: limit, offset: offset))._raw[:items]
|
27
26
|
end
|
28
27
|
end
|
@@ -6,13 +6,12 @@ class LHS::Record
|
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
module ClassMethods
|
9
|
-
|
10
9
|
# Process single entries fetched in batches
|
11
10
|
def find_each(options = {})
|
12
11
|
find_in_batches(options) do |data|
|
13
12
|
data.each do |record|
|
14
13
|
item = LHS::Item.new(LHS::Data.new(record, data, self))
|
15
|
-
yield
|
14
|
+
yield new(LHS::Data.new(item, data, self))
|
16
15
|
end
|
17
16
|
end
|
18
17
|
end
|
@@ -27,7 +26,7 @@ class LHS::Record
|
|
27
26
|
data = request(params: params.merge(limit: batch_size, offset: start))
|
28
27
|
batch_size = data._raw[:limit]
|
29
28
|
left = data._raw[:total].to_i - data._raw[:offset].to_i - data._raw[:limit].to_i
|
30
|
-
yield
|
29
|
+
yield new(data)
|
31
30
|
break if left <= 0
|
32
31
|
start += batch_size
|
33
32
|
end
|
@@ -6,20 +6,19 @@ class LHS::Record
|
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
module ClassMethods
|
9
|
-
|
10
9
|
def create(data = {})
|
11
10
|
create!(data)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
rescue LHC::Error => e
|
12
|
+
json = JSON.parse(data.to_json)
|
13
|
+
data = LHS::Data.new(json, nil, self, e.response.request)
|
14
|
+
item = LHS::Item.new(data)
|
15
|
+
item.errors = LHS::Errors.new(e.response)
|
16
|
+
data._record_class.new(LHS::Data.new(item, data))
|
18
17
|
end
|
19
18
|
|
20
19
|
def create!(data = {})
|
21
20
|
url = compute_url!(data)
|
22
|
-
data = request(url: url, method: :post, body: data.to_json, headers: {'Content-Type' => 'application/json'})
|
21
|
+
data = request(url: url, method: :post, body: data.to_json, headers: { 'Content-Type' => 'application/json' })
|
23
22
|
data._record_class.new(data)
|
24
23
|
end
|
25
24
|
end
|
@@ -12,7 +12,6 @@ class LHS::Record
|
|
12
12
|
mattr_accessor :all
|
13
13
|
|
14
14
|
module ClassMethods
|
15
|
-
|
16
15
|
def endpoints
|
17
16
|
@endpoints ||= []
|
18
17
|
end
|
@@ -32,7 +31,7 @@ class LHS::Record
|
|
32
31
|
|
33
32
|
def for_url(url)
|
34
33
|
return unless url
|
35
|
-
|
34
|
+
_template, record = LHS::Record::Endpoints.all.detect do |template, _record_class|
|
36
35
|
LHC::Endpoint.match?(url, template)
|
37
36
|
end
|
38
37
|
record
|
@@ -75,7 +74,7 @@ class LHS::Record
|
|
75
74
|
|
76
75
|
# Sort endpoints by number of placeholders, heighest first
|
77
76
|
def sorted_endpoints
|
78
|
-
endpoints.sort{|a, b| b.placeholders.count <=> a.placeholders.count }
|
77
|
+
endpoints.sort { |a, b| b.placeholders.count <=> a.placeholders.count }
|
79
78
|
end
|
80
79
|
|
81
80
|
# Finds the base endpoint.
|
@@ -6,14 +6,14 @@ class LHS::Record
|
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
module ClassMethods
|
9
|
-
|
10
9
|
# Find a single uniqe record
|
11
10
|
def find(args)
|
12
|
-
data =
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
data =
|
12
|
+
if args.is_a? Hash
|
13
|
+
find_with_parameters(args)
|
14
|
+
else
|
15
|
+
find_by_id(args)
|
16
|
+
end
|
17
17
|
data._record_class.new(data)
|
18
18
|
end
|
19
19
|
|
@@ -6,12 +6,11 @@ class LHS::Record
|
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
module ClassMethods
|
9
|
-
|
10
9
|
# Fetch some record by parameters
|
11
10
|
def find_by(params = {})
|
12
11
|
_find_by(params)
|
13
|
-
|
14
|
-
|
12
|
+
rescue LHC::NotFound
|
13
|
+
nil
|
15
14
|
end
|
16
15
|
|
17
16
|
# Raise if no record was found
|
@@ -24,11 +23,12 @@ class LHS::Record
|
|
24
23
|
def _find_by(params)
|
25
24
|
params = params.dup.merge(limit: 1)
|
26
25
|
data = request(params: params)
|
27
|
-
data =
|
28
|
-
data.
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
data =
|
27
|
+
if data._proxy.is_a?(LHS::Collection)
|
28
|
+
data.first || fail(LHC::NotFound.new('No item was found.', data._request.response))
|
29
|
+
else
|
30
|
+
data
|
31
|
+
end
|
32
32
|
data._record_class.new(data)
|
33
33
|
end
|
34
34
|
end
|
@@ -6,7 +6,6 @@ class LHS::Record
|
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
module ClassMethods
|
9
|
-
|
10
9
|
def request(options)
|
11
10
|
if options.is_a? Array
|
12
11
|
multiple_requests(options)
|
@@ -29,7 +28,8 @@ class LHS::Record
|
|
29
28
|
def convert_option_to_endpoints(option)
|
30
29
|
new_options = option.dup
|
31
30
|
url = option[:url]
|
32
|
-
|
31
|
+
endpoint = LHS::Endpoint.for_url(url)
|
32
|
+
return unless endpoint
|
33
33
|
template = endpoint.url
|
34
34
|
new_options = new_options.merge(params: LHC::Endpoint.values_as_params(template, url))
|
35
35
|
new_options[:url] = template
|
@@ -50,23 +50,26 @@ class LHS::Record
|
|
50
50
|
|
51
51
|
def handle_includes(includes, data)
|
52
52
|
if includes.is_a? Hash
|
53
|
-
includes.each { |
|
53
|
+
includes.each { |included, sub_includes| handle_include(included, data, sub_includes) }
|
54
54
|
elsif includes.is_a? Array
|
55
|
-
includes.each { |
|
55
|
+
includes.each { |included| handle_includes(included, data) }
|
56
56
|
else
|
57
57
|
handle_include(includes, data)
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
def handle_include(
|
61
|
+
def handle_include(included, data, sub_includes = nil)
|
62
62
|
return unless data.present?
|
63
|
-
options =
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
63
|
+
options =
|
64
|
+
if data._proxy.is_a? LHS::Collection
|
65
|
+
options_for_multiple(data, included)
|
66
|
+
options_for_multiple(data, included)
|
67
|
+
else
|
68
|
+
url_option_for(data, included)
|
69
|
+
url_option_for(data, included)
|
70
|
+
end
|
68
71
|
addition = load_include(options, data, sub_includes)
|
69
|
-
extend_raw_data(data, addition,
|
72
|
+
extend_raw_data(data, addition, included)
|
70
73
|
end
|
71
74
|
|
72
75
|
# Load additional resources that are requested with include
|
@@ -89,9 +92,9 @@ class LHS::Record
|
|
89
92
|
end
|
90
93
|
|
91
94
|
def multiple_requests(options)
|
92
|
-
options = options.map { |
|
95
|
+
options = options.map { |option| process_options(option) }
|
93
96
|
responses = LHC.request(options)
|
94
|
-
data = responses.map{ |response| LHS::Data.new(response.body, nil, self, response.request) }
|
97
|
+
data = responses.map { |response| LHS::Data.new(response.body, nil, self, response.request) }
|
95
98
|
data = LHS::Data.new(data, nil, self)
|
96
99
|
handle_includes(including, data) if including
|
97
100
|
data
|
@@ -120,7 +123,8 @@ class LHS::Record
|
|
120
123
|
records = []
|
121
124
|
if options.is_a?(Array)
|
122
125
|
options.each do |option|
|
123
|
-
|
126
|
+
record = LHS::Record.for_url(option[:url])
|
127
|
+
next unless record
|
124
128
|
records.push(record)
|
125
129
|
end
|
126
130
|
fail 'Found more than one record that could be used to do the request' if records.uniq.count > 1
|
data/lib/lhs/data.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require File.join(__dir__, 'proxy.rb')
|
2
|
-
Dir[File.dirname(__FILE__) + '/concerns/data/*.rb'].each {|file| require file }
|
2
|
+
Dir[File.dirname(__FILE__) + '/concerns/data/*.rb'].each { |file| require file }
|
3
3
|
|
4
4
|
# Data provides functionalities to accesses information
|
5
5
|
class LHS::Data
|
@@ -51,7 +51,7 @@ class LHS::Data
|
|
51
51
|
|
52
52
|
def respond_to_missing?(name, include_all = false)
|
53
53
|
(root_item? && _root._record_class.instance_methods.include?(name)) ||
|
54
|
-
|
54
|
+
_proxy.respond_to?(name, include_all)
|
55
55
|
end
|
56
56
|
|
57
57
|
private
|
@@ -61,14 +61,13 @@ class LHS::Data
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def root_item
|
64
|
-
return if
|
64
|
+
return if _proxy.class != LHS::Item
|
65
65
|
root = root_item = self
|
66
66
|
loop do
|
67
67
|
root = root._parent
|
68
68
|
root_item = root if root && root._proxy.is_a?(LHS::Item)
|
69
69
|
if !(root && root._parent)
|
70
70
|
break
|
71
|
-
else
|
72
71
|
end
|
73
72
|
end
|
74
73
|
root_item
|
data/lib/lhs/endpoint.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# An endpoint is used as source to fetch objects
|
2
2
|
class LHS::Endpoint
|
3
|
-
|
3
|
+
|
4
4
|
def self.for_url(url)
|
5
5
|
template, record = LHS::Record::Endpoints.all.detect do |template, _record_class|
|
6
6
|
LHC::Endpoint.match?(url, template)
|
@@ -8,4 +8,3 @@ class LHS::Endpoint
|
|
8
8
|
record.endpoints.detect { |endpoint| endpoint.url == template } if record
|
9
9
|
end
|
10
10
|
end
|
11
|
-
|
data/lib/lhs/errors.rb
CHANGED
@@ -8,14 +8,14 @@ class LHS::Errors
|
|
8
8
|
@messages = messages_from_response(response)
|
9
9
|
@message = message_from_response(response)
|
10
10
|
@raw = response.body
|
11
|
-
|
11
|
+
rescue JSON::ParserError # rubocop:disable Lint/HandleExceptions
|
12
12
|
end
|
13
13
|
|
14
14
|
def include?(attribute)
|
15
15
|
messages[attribute].present?
|
16
16
|
end
|
17
|
-
alias
|
18
|
-
alias
|
17
|
+
alias has_key? include?
|
18
|
+
alias key? include?
|
19
19
|
|
20
20
|
def get(key)
|
21
21
|
messages[key]
|
@@ -25,9 +25,7 @@ class LHS::Errors
|
|
25
25
|
messages[key] = value
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
|
-
messages.delete(key)
|
30
|
-
end
|
28
|
+
delegate :delete, to: :messages
|
31
29
|
|
32
30
|
def [](attribute)
|
33
31
|
get(attribute.to_sym) || set(attribute.to_sym, [])
|
@@ -47,20 +45,16 @@ class LHS::Errors
|
|
47
45
|
values.flatten.size
|
48
46
|
end
|
49
47
|
|
50
|
-
|
51
|
-
messages.values
|
52
|
-
end
|
48
|
+
delegate :values, to: :messages
|
53
49
|
|
54
|
-
|
55
|
-
messages.keys
|
56
|
-
end
|
50
|
+
delegate :keys, to: :messages
|
57
51
|
|
58
52
|
def count
|
59
53
|
to_a.size
|
60
54
|
end
|
61
55
|
|
62
56
|
def empty?
|
63
|
-
all? { |
|
57
|
+
all? { |_k, v| v && v.empty? && !v.is_a?(String) }
|
64
58
|
end
|
65
59
|
|
66
60
|
private
|
data/lib/lhs/item.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require File.join(__dir__, 'proxy.rb')
|
2
|
-
Dir[File.dirname(__FILE__) + '/concerns/item/*.rb'].each {|file| require file }
|
2
|
+
Dir[File.dirname(__FILE__) + '/concerns/item/*.rb'].each { |file| require file }
|
3
3
|
|
4
4
|
# An item is a concrete record.
|
5
5
|
# It can be part of another proxy like collection.
|
@@ -14,13 +14,11 @@ class LHS::Item < LHS::Proxy
|
|
14
14
|
# prevent clashing with attributes of underlying data
|
15
15
|
attr_accessor :errors
|
16
16
|
|
17
|
-
|
18
|
-
_data._raw
|
19
|
-
end
|
17
|
+
delegate :_raw, to: :_data
|
20
18
|
|
21
19
|
protected
|
22
20
|
|
23
|
-
def method_missing(name, *args, &
|
21
|
+
def method_missing(name, *args, &_block)
|
24
22
|
return set(name, args.try(&:first)) if name.to_s[/=$/]
|
25
23
|
name = args.first if name == :[]
|
26
24
|
value = _data._raw[name.to_s]
|
@@ -36,7 +34,7 @@ class LHS::Item < LHS::Proxy
|
|
36
34
|
end
|
37
35
|
end
|
38
36
|
|
39
|
-
def respond_to_missing?(name,
|
37
|
+
def respond_to_missing?(name, _include_all = false)
|
40
38
|
# We accept every message that does not belong to set of keywords
|
41
39
|
BLACKLISTED_KEYWORDS.exclude?(name.to_s)
|
42
40
|
end
|
@@ -49,7 +47,7 @@ class LHS::Item < LHS::Proxy
|
|
49
47
|
def convert(value)
|
50
48
|
return value unless value.is_a?(String)
|
51
49
|
if date_time?(value)
|
52
|
-
|
50
|
+
Time.zone.parse(value)
|
53
51
|
elsif date?(value)
|
54
52
|
Date.parse(value)
|
55
53
|
else
|
@@ -72,8 +70,6 @@ class LHS::Item < LHS::Proxy
|
|
72
70
|
_data._raw[key.to_sym] = value
|
73
71
|
end
|
74
72
|
|
75
|
-
private
|
76
|
-
|
77
73
|
def date?(value)
|
78
74
|
value[date_time_regex, :date].presence
|
79
75
|
end
|
data/lib/lhs/record.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Dir[File.dirname(__FILE__) + '/concerns/record/*.rb'].each {|file| require file }
|
1
|
+
Dir[File.dirname(__FILE__) + '/concerns/record/*.rb'].each { |file| require file }
|
2
2
|
|
3
3
|
class LHS::Record
|
4
4
|
include All
|
@@ -18,15 +18,19 @@ class LHS::Record
|
|
18
18
|
data = LHS::Data.new({}, nil, self.class) unless data
|
19
19
|
data = LHS::Data.new(data, nil, self.class) unless data.is_a?(LHS::Data)
|
20
20
|
define_singleton_method(:_data) { data }
|
21
|
-
|
22
|
-
data.
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
instance_data =
|
22
|
+
if data._proxy.is_a?(LHS::Item) && data._raw.is_a?(Hash)
|
23
|
+
data._raw
|
24
|
+
elsif data._proxy.is_a?(LHS::Collection) && data._raw.is_a?(Hash)
|
25
|
+
data._raw.fetch(:items, [])
|
26
|
+
else
|
27
|
+
data._raw
|
28
|
+
end
|
29
|
+
instance_variable_set('@data', instance_data)
|
26
30
|
end
|
27
31
|
|
28
32
|
def self.build(data = nil)
|
29
|
-
|
33
|
+
new(data)
|
30
34
|
end
|
31
35
|
|
32
36
|
protected
|
@@ -37,6 +41,6 @@ class LHS::Record
|
|
37
41
|
|
38
42
|
def respond_to_missing?(name, include_all = false)
|
39
43
|
(_data.root_item? && _data._root._record_class.instance_methods.include?(name)) ||
|
40
|
-
|
44
|
+
_data._proxy.respond_to?(name, include_all)
|
41
45
|
end
|
42
46
|
end
|