lhs 24.1.2 → 25.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9bf423437a22db27b055a47b11b77edad75d4fb22895330bb33b439c03d9e89f
4
- data.tar.gz: 228b803160ce5cfeaa801e25eac36a84fa75196ca906183336e649cd17c5604a
3
+ metadata.gz: cbf1bd4d4d3bec5d8264176e1b7806a4b04f56bceabd6b72f51efb50a0a49b46
4
+ data.tar.gz: f60fffae1148244ddb5d52c379668dbac292a3868baa1862f52362ecb7537ea5
5
5
  SHA512:
6
- metadata.gz: dd83a4d879c72a201b29420021562da78945a1ef731a87023c735efe90144f1d088318c293064d9361aa559df8405132d88af0011225c43e675144d1c5af7b5f
7
- data.tar.gz: 6da5e46c3e113bbf48a3821a02b88a6379bd54846889acb7cf77ce269be9645404d443656215979d7b3311ae1139ba07c00993542cacbd17562dc79b733af8eb
6
+ metadata.gz: 22e0045d22ae49e4537329ffb53d1db8ef070da54822ffda08315e85ed7fe6c6e66656e65f61d7d06a4aa2010f34a8a52d6f614c1da8ad13e88628538ebc0b4f
7
+ data.tar.gz: e297eabef047eed5cc42b102d13b6043c678ea7f2fc8c620d04a4b8b794ee0028459e65d80a3361cc7ea43ad2e17aa966323859b735a632847e77e376266fb9c
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
24
24
 
25
25
  s.add_dependency 'activemodel'
26
26
  s.add_dependency 'activesupport', '>= 4.2.11'
27
- s.add_dependency 'lhc', '>= 12.1.1', '< 13'
27
+ s.add_dependency 'lhc', '>= 12.1.1', '< 14'
28
28
  s.add_dependency 'local_uri'
29
29
 
30
30
  s.add_development_dependency 'capybara'
@@ -14,7 +14,7 @@ class LHS::Collection < LHS::Proxy
14
14
 
15
15
  METHOD_NAMES_EXLCUDED_FROM_WRAPPING = %w(to_a to_ary map).freeze
16
16
 
17
- delegate :select, :length, :size, to: :_collection
17
+ delegate :select, :length, :size, :insert, to: :_collection
18
18
  delegate :_record, :_raw, to: :_data
19
19
  delegate :limit, :count, :total, :offset, :current_page, :start,
20
20
  :next?, :previous?, to: :_pagination
@@ -32,7 +32,7 @@ module AutoloadRecords
32
32
  end
33
33
 
34
34
  def self.require_direct_inheritance
35
- model_files.map do |file|
35
+ model_files.sort.map do |file|
36
36
  next unless File.read(file).match('LHS::Record')
37
37
  require_dependency file
38
38
  file.split('models/').last.gsub('.rb', '').classify
@@ -41,7 +41,9 @@ module AutoloadRecords
41
41
 
42
42
  def self.require_inheriting_records(parents)
43
43
  model_files.each do |file|
44
- next if parents.none? { |parent| File.read(file).match(parent) }
44
+ file_content = File.read(file)
45
+ next if parents.none? { |parent| file_content.match(/\b#{parent}\b/) }
46
+ next if file_content.match?('extend ActiveSupport::Concern')
45
47
  require_dependency file
46
48
  end
47
49
  end
@@ -14,7 +14,7 @@ class LHS::Collection < LHS::Proxy
14
14
 
15
15
  attr_accessor :raw
16
16
  delegate :length, :size, :first, :last, :sample, :[], :present?, :blank?, :empty?,
17
- :<<, :push, to: :raw
17
+ :<<, :push, :insert, to: :raw
18
18
 
19
19
  def initialize(raw, parent, record)
20
20
  self.raw = raw
@@ -39,7 +39,7 @@ class LHS::Collection < LHS::Proxy
39
39
  def compact
40
40
  dup.tap do |collection|
41
41
  collection.compact! if collection.raw.present?
42
- end
42
+ end.as_json # do not return an internal collection!
43
43
  end
44
44
 
45
45
  def compact!
@@ -9,11 +9,11 @@ class LHS::Data
9
9
 
10
10
  # Extends already fetched data (self) with additionally
11
11
  # fetched data (addition) using the given key
12
- def extend!(addition, key)
12
+ def extend!(addition, key = nil)
13
13
  addition = cast_relation_class_for_extension(addition, key)
14
14
  if collection?
15
15
  extend_collection!(addition, key)
16
- elsif self[key]._raw.is_a? Array
16
+ elsif _raw.is_a?(Array) || self[key]._raw.is_a?(Array)
17
17
  extend_array!(addition, key)
18
18
  elsif item?
19
19
  extend_item!(addition, key)
@@ -22,14 +22,14 @@ class LHS::Data
22
22
 
23
23
  private
24
24
 
25
- def cast_relation_class_for_extension(addition, key)
26
- return addition if _record.nil? || _record._relations.nil? || _record._relations[key].nil?
25
+ def cast_relation_class_for_extension(addition, key = nil)
26
+ return addition if _record.nil? || key.nil? || _record._relations.nil? || _record._relations[key].nil?
27
27
  addition.becomes(_record._relations[key][:record_class_name].constantize, errors: addition.errors, warnings: addition.warnings)
28
28
  end
29
29
 
30
- def extend_collection!(addition, key)
30
+ def extend_collection!(addition, key = nil)
31
31
  map do |item|
32
- item_raw = item._raw[key]
32
+ item_raw = key ? item._raw[key] : item._raw
33
33
  item_raw.blank? ? [nil] : item_raw
34
34
  end
35
35
  .flatten
@@ -45,25 +45,25 @@ class LHS::Data
45
45
  end
46
46
  end
47
47
 
48
- def extend_array!(addition, key)
49
- self[key].zip(addition) do |item, additional_item|
48
+ def extend_array!(addition, key = nil)
49
+ (key ? self[key] : self).zip(addition) do |item, additional_item|
50
50
  item._raw.merge!(additional_item._raw) if additional_item.present?
51
51
  end
52
52
  end
53
53
 
54
- def extend_item!(addition, key)
54
+ def extend_item!(addition, key = nil)
55
55
  return if addition.nil?
56
56
  if addition.collection?
57
57
  extend_item_with_collection!(addition, key)
58
58
  else # simple case merges hash into hash
59
- _raw[key.to_sym].merge!(addition._raw)
59
+ (key ? _raw[key.to_sym] : _raw).merge!(addition._raw)
60
60
  end
61
61
  end
62
62
 
63
- def extend_item_with_collection!(addition, key)
64
- target = self[key]
63
+ def extend_item_with_collection!(addition, key = nil)
64
+ target = (key ? self[key] : self)
65
65
  if target._raw.is_a? Array
66
- self[key] = addition.map(&:_raw)
66
+ self[key] = addition.map(&:_raw) if key
67
67
  else # hash with items
68
68
  extend_item_with_hash_containing_items!(target, addition)
69
69
  end
@@ -72,7 +72,11 @@ class LHS::Data
72
72
  def extend_item_with_hash_containing_items!(target, addition)
73
73
  LHS::Collection.nest(input: target._raw, value: [], record: self) # inits the nested collection
74
74
  if LHS::Collection.access(input: target._raw, record: self).empty?
75
- LHS::Collection.nest(input: target._raw, value: addition.reject { |item| item.nil? }, record: self)
75
+ LHS::Collection.nest(
76
+ input: target._raw,
77
+ value: addition.reject { |item| item.nil? },
78
+ record: self
79
+ )
76
80
  else
77
81
  LHS::Collection.access(input: target._raw, record: self).each_with_index do |item, index|
78
82
  item.merge!(addition[index])
@@ -29,7 +29,10 @@ class LHS::Record
29
29
  if options.is_a?(Hash)
30
30
  options.deep_merge(LHS::OptionBlocks::CurrentOptionBlock.options)
31
31
  elsif options.is_a?(Array)
32
- options.map { |option| option.deep_merge(LHS::OptionBlocks::CurrentOptionBlock.options) }
32
+ options.map do |option|
33
+ return LHS::OptionBlocks::CurrentOptionBlock.options unless option
34
+ option.deep_merge(LHS::OptionBlocks::CurrentOptionBlock.options)
35
+ end
33
36
  end
34
37
  end
35
38
 
@@ -118,7 +121,7 @@ class LHS::Record
118
121
  else
119
122
  options = options_for_data(data, included)
120
123
  options = extend_with_reference(options, reference)
121
- addition = load_include(options, data, sub_includes, reference)
124
+ addition = load_existing_includes(options, data, sub_includes, reference)
122
125
  data.extend!(addition, included)
123
126
  expand_addition!(data, included, reference) unless expanded_data?(addition)
124
127
  end
@@ -277,6 +280,21 @@ class LHS::Record
277
280
  end
278
281
  end
279
282
 
283
+ def load_existing_includes(options, data, sub_includes, references)
284
+ if data.collection? && data.any?(&:blank?)
285
+ # filter only existing items
286
+ loaded_includes = load_include(options.compact, data.compact, sub_includes, references)
287
+ # fill up skipped items before returning
288
+ data.each_with_index do |item, index|
289
+ next if item.present?
290
+ loaded_includes.insert(index, {})
291
+ end
292
+ loaded_includes
293
+ else
294
+ load_include(options, data, sub_includes, references)
295
+ end
296
+ end
297
+
280
298
  # Load additional resources that are requested with include
281
299
  def load_include(options, _data, sub_includes, references)
282
300
  record = record_for_options(options) || self
@@ -303,11 +321,22 @@ class LHS::Record
303
321
  end
304
322
 
305
323
  # Continues loading included resources after one complete batch/level has been fetched
306
- def continue_including(data, including, referencing)
307
- handle_includes(including, data, referencing) if including.present? && data.present?
324
+ def continue_including(data, included, reference)
325
+ return data if included.blank? || data.blank?
326
+ expand_data!(data, included, reference) unless expanded_data?(data)
327
+ handle_includes(included, data, reference)
308
328
  data
309
329
  end
310
330
 
331
+ def expand_data!(data, _included, reference)
332
+ options = options_for_data(data)
333
+ options = extend_with_reference(options, reference)
334
+ record = record_for_options(options) || self
335
+ options = convert_options_to_endpoints(options) if record_for_options(options)
336
+ expanded_data = record.request(options)
337
+ data.extend!(expanded_data)
338
+ end
339
+
311
340
  # Loads all included/linked resources,
312
341
  # paginates itself to ensure all records are fetched
313
342
  def load_all_included!(record, options)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LHS
4
- VERSION = '24.1.2'
4
+ VERSION = '25.0.4'
5
5
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DummyCustomer < Providers::CustomerSystem
4
+ module SomeConcern
5
+ extend ActiveSupport::Concern
6
+
7
+ # dont auto load this again with LHS as it would raise an exception
8
+ end
9
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class DummyCustomer < Providers::CustomerSystem
4
+ include SomeConcern
4
5
  endpoint 'http://customers'
5
6
  endpoint 'http://customers/{id}'
6
7
  end
@@ -66,6 +66,11 @@ describe LHS::Record do
66
66
  end
67
67
 
68
68
  context '.compact' do
69
+
70
+ it 'does NOT return an internal data type, but the Record class' do
71
+ expect(places.compact.class).to eq User
72
+ end
73
+
69
74
  it 'removes linked resouces which could not get fetched' do
70
75
  expect(places.compact.length).to eq 1
71
76
  expect(places.length).not_to eq 1 # leaves the original intact
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Record do
6
+ context 'includes records after expansion' do
7
+
8
+ before do
9
+ class User < LHS::Record
10
+ endpoint 'http://users/{id}'
11
+ end
12
+
13
+ class Places < LHS::Record
14
+ endpoint 'http://users/{id}/places'
15
+ endpoint 'http://places/{id}'
16
+ end
17
+
18
+ class Contracts < LHS::Record
19
+ endpoint 'http://places/{place_id}/contracts'
20
+ end
21
+
22
+ stub_request(:get, 'http://users/1')
23
+ .to_return(
24
+ body: {
25
+ places: {
26
+ href: 'http://users/1/places'
27
+ }
28
+ }.to_json
29
+ )
30
+
31
+ stub_request(:get, 'http://users/1/places?limit=100')
32
+ .to_return(
33
+ body: {
34
+ items: [
35
+ { href: 'http://places/345' }
36
+ ],
37
+ total: 1,
38
+ offset: 0,
39
+ limit: 10
40
+ }.to_json
41
+ )
42
+
43
+ stub_request(:get, 'http://places/345')
44
+ .to_return(
45
+ body: {
46
+ contracts: {
47
+ href: "http://places/345/contracts?offset=0&limit=10"
48
+ }
49
+ }.to_json
50
+ )
51
+
52
+ stub_request(:get, 'http://places/345/contracts?offset=0&limit=10')
53
+ .to_return(
54
+ body: {
55
+ items: [
56
+ {
57
+ product: { name: 'OPL' }
58
+ }
59
+ ]
60
+ }.to_json
61
+ )
62
+
63
+ end
64
+
65
+ it 'includes resources after expanding plain links' do
66
+ user = User.includes(places: :contracts).find(1)
67
+ expect(
68
+ user.places.first.contracts.first.product.name
69
+ ).to eq 'OPL'
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Record do
6
+
7
+ context 'merge request options ' do
8
+ before do
9
+ class Record < LHS::Record
10
+ endpoint 'http://records/{id}'
11
+ end
12
+
13
+ stub_request(:get, 'http://records/1')
14
+ .to_return(body: {
15
+ place_attributes: [
16
+ { href: 'https://attributes/bar' },
17
+ { href: 'https://attributes/restaurant' },
18
+ { href: 'https://attributes/cafe' }
19
+ ]
20
+ }.to_json)
21
+
22
+ stub_request(:get, "https://attributes/restaurant?limit=100")
23
+ .to_return(body: {}.to_json)
24
+ stub_request(:get, "https://attributes/restaurant")
25
+ .to_return(body: {}.to_json)
26
+ stub_request(:get, "https://attributes/bar?limit=100")
27
+ .to_return(body: {
28
+ group: {
29
+ href: 'https://group/general'
30
+ }
31
+ }.to_json)
32
+ stub_request(:get, "https://attributes/cafe?limit=100")
33
+ .to_return(body: {
34
+ group: {
35
+ href: 'https://group/general'
36
+ }
37
+ }.to_json)
38
+ stub_request(:get, "https://group/general?limit=100&status=active")
39
+ .to_return(body: {
40
+ name: 'General'
41
+ }.to_json)
42
+ end
43
+
44
+ context 'missing referenced options due to none existance of include' do
45
+
46
+ it 'does not raise when trying to merge options with the options block' do
47
+ LHS.options(throttle: { break: '80%' }) do
48
+ record = Record
49
+ .references(place_attributes: { group: { params: { status: 'active' } } })
50
+ .includes([{ place_attributes: :group }])
51
+ .find(1)
52
+ expect(record.place_attributes[0].group.name).to eq 'General'
53
+ expect(record.place_attributes[1].group).to eq nil
54
+ expect(record.place_attributes[2].group.name).to eq 'General'
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lhs
3
3
  version: !ruby/object:Gem::Version
4
- version: 24.1.2
4
+ version: 25.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - https://github.com/local-ch/lhs/graphs/contributors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-20 00:00:00.000000000 Z
11
+ date: 2020-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -47,7 +47,7 @@ dependencies:
47
47
  version: 12.1.1
48
48
  - - "<"
49
49
  - !ruby/object:Gem::Version
50
- version: '13'
50
+ version: '14'
51
51
  type: :runtime
52
52
  prerelease: false
53
53
  version_requirements: !ruby/object:Gem::Requirement
@@ -57,7 +57,7 @@ dependencies:
57
57
  version: 12.1.1
58
58
  - - "<"
59
59
  - !ruby/object:Gem::Version
60
- version: '13'
60
+ version: '14'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: local_uri
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -389,6 +389,7 @@ files:
389
389
  - spec/dummy/app/mailers/.keep
390
390
  - spec/dummy/app/models/.keep
391
391
  - spec/dummy/app/models/concerns/.keep
392
+ - spec/dummy/app/models/concerns/dummy_customer/some_concern.rb
392
393
  - spec/dummy/app/models/dummy_customer.rb
393
394
  - spec/dummy/app/models/dummy_record.rb
394
395
  - spec/dummy/app/models/dummy_record_with_auto_oauth_provider.rb
@@ -504,8 +505,10 @@ files:
504
505
  - spec/record/href_for_spec.rb
505
506
  - spec/record/ignore_errors_spec.rb
506
507
  - spec/record/immutable_chains_spec.rb
508
+ - spec/record/includes_after_expansion_spec.rb
507
509
  - spec/record/includes_expanded_spec.rb
508
510
  - spec/record/includes_first_page_spec.rb
511
+ - spec/record/includes_missing_spec.rb
509
512
  - spec/record/includes_spec.rb
510
513
  - spec/record/includes_warning_spec.rb
511
514
  - spec/record/item_key_spec.rb
@@ -619,6 +622,7 @@ test_files:
619
622
  - spec/dummy/app/mailers/.keep
620
623
  - spec/dummy/app/models/.keep
621
624
  - spec/dummy/app/models/concerns/.keep
625
+ - spec/dummy/app/models/concerns/dummy_customer/some_concern.rb
622
626
  - spec/dummy/app/models/dummy_customer.rb
623
627
  - spec/dummy/app/models/dummy_record.rb
624
628
  - spec/dummy/app/models/dummy_record_with_auto_oauth_provider.rb
@@ -734,8 +738,10 @@ test_files:
734
738
  - spec/record/href_for_spec.rb
735
739
  - spec/record/ignore_errors_spec.rb
736
740
  - spec/record/immutable_chains_spec.rb
741
+ - spec/record/includes_after_expansion_spec.rb
737
742
  - spec/record/includes_expanded_spec.rb
738
743
  - spec/record/includes_first_page_spec.rb
744
+ - spec/record/includes_missing_spec.rb
739
745
  - spec/record/includes_spec.rb
740
746
  - spec/record/includes_warning_spec.rb
741
747
  - spec/record/item_key_spec.rb