lhs 25.0.0 → 25.1.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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rubocop.yml +27 -0
  3. data/.github/workflows/test-active-support-5.yml +27 -0
  4. data/.github/workflows/test.yml +27 -0
  5. data/.ruby-version +1 -1
  6. data/README.md +36 -0
  7. data/lib/lhs.rb +2 -0
  8. data/lib/lhs/collection.rb +1 -1
  9. data/lib/lhs/concerns/autoload_records.rb +4 -2
  10. data/lib/lhs/concerns/collection/internal_collection.rb +2 -2
  11. data/lib/lhs/concerns/data/extend.rb +18 -14
  12. data/lib/lhs/concerns/record/pagination.rb +2 -0
  13. data/lib/lhs/concerns/record/request.rb +33 -4
  14. data/lib/lhs/pagination/total_pages.rb +9 -0
  15. data/lib/lhs/version.rb +1 -1
  16. data/spec/dummy/app/models/concerns/dummy_customer/some_concern.rb +9 -0
  17. data/spec/dummy/app/models/dummy_customer.rb +1 -0
  18. data/spec/pagination/total_pages_spec.rb +52 -0
  19. data/spec/record/compact_spec.rb +5 -0
  20. data/spec/record/includes_after_expansion_spec.rb +72 -0
  21. data/spec/record/includes_missing_spec.rb +59 -0
  22. metadata +18 -19
  23. data/Gemfile.activesupport4 +0 -5
  24. data/cider-ci.yml +0 -6
  25. data/cider-ci/bin/bundle +0 -51
  26. data/cider-ci/bin/ruby_install +0 -8
  27. data/cider-ci/bin/ruby_version +0 -25
  28. data/cider-ci/jobs/rspec-activesupport-4.yml +0 -27
  29. data/cider-ci/jobs/rspec-activesupport-5.yml +0 -26
  30. data/cider-ci/jobs/rspec-activesupport-latest.yml +0 -24
  31. data/cider-ci/jobs/rubocop.yml +0 -18
  32. data/cider-ci/task_components/bundle.yml +0 -22
  33. data/cider-ci/task_components/rspec.yml +0 -37
  34. data/cider-ci/task_components/rubocop.yml +0 -29
  35. data/cider-ci/task_components/ruby.yml +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 75364b152de7b958acefbb09ab084ca96dd15f1daad2465ab80db56584f5f600
4
- data.tar.gz: 1456ffc9b3a696bc871248981364f7012deeb921647d88493041db4d40effea5
3
+ metadata.gz: 92e9ccdfc62407ecb0d4ba6b6ce18b28628ecaad229586f589eb7167fe8ff0de
4
+ data.tar.gz: 26924759db03d133fbfc8dee9be190e8238fa0fc3036f7b79b13636e881f785e
5
5
  SHA512:
6
- metadata.gz: c271c49bce686c2686ef1d80b535433aba05f1cd58dc98b2265cc8cc63149faa9b3094e0cf82acf8f0afd80721fbbfa5369aea1ffb091e0b14ce35120bc400fc
7
- data.tar.gz: a24a6debcbe0866a73167eee9b44a3adc7cda111bcd4971e77982d14d44e2bda3cce3eaa63666e257f60f5653a3e013321eb622ca2d6e152cae9b03fce79839d
6
+ metadata.gz: 4186ce186f51e95872532c943c93a402b1d23160d35b123f2fa4c01a1e589ffc863b5f6345c8071c606545539e91e789d75bed7efefcef0546677fe852a56d3d
7
+ data.tar.gz: b31b7ab8443d71a735397127f389d8dda1f9add35fa318e92ba0172f65172d21928181120a56c953227d0051778646745c8c510c04967e17ba0c24ddd60723ea
@@ -0,0 +1,27 @@
1
+ name: Rubocop
2
+
3
+ on: push
4
+
5
+ jobs:
6
+ rubocop:
7
+ runs-on: ubuntu-latest
8
+
9
+ steps:
10
+ - uses: actions/checkout@v2
11
+ - uses: actions/setup-ruby@v1
12
+ with:
13
+ ruby-version: 2.7.2
14
+ - name: Cache Ruby Gems
15
+ uses: actions/cache@v2
16
+ with:
17
+ path: /.tmp/vendor/bundle
18
+ key: ${{ runner.os }}-gems-latest-${{ hashFiles('**/Gemfile.lock') }}
19
+ restore-keys: |
20
+ ${{ runner.os }}-gems-latest-
21
+ - name: Bundle Install
22
+ run: |
23
+ bundle config path /.tmp/vendor/bundle
24
+ bundle install --jobs 4 --retry 3
25
+ - name: Run Rubocop
26
+ run: |
27
+ bundle exec rubocop
@@ -0,0 +1,27 @@
1
+ name: Test ActiveSupport v5
2
+
3
+ on: push
4
+
5
+ jobs:
6
+ rspec:
7
+ runs-on: ubuntu-latest
8
+
9
+ steps:
10
+ - uses: actions/checkout@v2
11
+ - uses: actions/setup-ruby@v1
12
+ with:
13
+ ruby-version: 2.7.2
14
+ - name: Cache Ruby Gems
15
+ uses: actions/cache@v2
16
+ with:
17
+ path: /.tmp/vendor/bundle
18
+ key: ${{ runner.os }}-gems-v5-${{ hashFiles('**/Gemfile.lock') }}
19
+ restore-keys: |
20
+ ${{ runner.os }}-gems-v5-
21
+ - name: Bundle Install ActiveSupport v5
22
+ run: |
23
+ bundle config path /.tmp/vendor/bundle
24
+ BUNDLE_GEMFILE=Gemfile.activesupport5 bundle install --jobs 4 --retry 3
25
+ - name: Run Tests
26
+ run: |
27
+ BUNDLE_GEMFILE=Gemfile.activesupport5 bundle exec rspec
@@ -0,0 +1,27 @@
1
+ name: Test
2
+
3
+ on: push
4
+
5
+ jobs:
6
+ rspec:
7
+ runs-on: ubuntu-latest
8
+
9
+ steps:
10
+ - uses: actions/checkout@v2
11
+ - uses: actions/setup-ruby@v1
12
+ with:
13
+ ruby-version: 2.7.2
14
+ - name: Cache Ruby Gems
15
+ uses: actions/cache@v2
16
+ with:
17
+ path: /.tmp/vendor/bundle
18
+ key: ${{ runner.os }}-gems-latest-${{ hashFiles('**/Gemfile.lock') }}
19
+ restore-keys: |
20
+ ${{ runner.os }}-gems-latest-
21
+ - name: Bundle Install
22
+ run: |
23
+ bundle config path /.tmp/vendor/bundle
24
+ bundle install --jobs 4 --retry 3
25
+ - name: Run Tests
26
+ run: |
27
+ bundle exec rspec
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-2.6.5
1
+ ruby-2.7.2
data/README.md CHANGED
@@ -80,6 +80,7 @@ record.review # "Lunch was great
80
80
  * [Pagination strategy](#pagination-strategy)
81
81
  * [Pagination strategy: offset (default)](#pagination-strategy-offset-default)
82
82
  * [Pagination strategy: page](#pagination-strategy-page)
83
+ * [Pagination strategy: total_pages](#pagination-strategy-total-pages)
83
84
  * [Pagination strategy: start](#pagination-strategy-start)
84
85
  * [Pagination strategy: link](#pagination-strategy-link)
85
86
  * [Pagination keys](#pagination-keys)
@@ -1253,6 +1254,41 @@ In parallel:
1253
1254
  GET https://service.example.com/records?limit=100&page=3
1254
1255
  ```
1255
1256
 
1257
+ ##### Pagination strategy: total_pages
1258
+
1259
+ The `total_pages` strategy is based on the `page` strategy with the only difference
1260
+ that the responding api provides `total_pages` over `total_items`.
1261
+
1262
+ ```ruby
1263
+ # app/models/transaction.rb
1264
+
1265
+ class Transaction < LHS::Record
1266
+ configuration pagination_strategy: 'total_pages', pagination_key: 'page', total_key: 'total_pages'
1267
+
1268
+ endpoint '{+service}/transactions'
1269
+ end
1270
+ ```
1271
+
1272
+ ```ruby
1273
+ # app/controllers/some_controller.rb
1274
+
1275
+ Record.all
1276
+
1277
+ ```
1278
+ ```
1279
+ GET https://service.example.com/transactions?limit=100
1280
+ {
1281
+ items: [{...}, ...],
1282
+ total_pages: 3,
1283
+ limit: 100,
1284
+ page: 1
1285
+ }
1286
+ In parallel:
1287
+ GET https://service.example.com/records?limit=100&page=2
1288
+ GET https://service.example.com/records?limit=100&page=3
1289
+ ```
1290
+
1291
+
1256
1292
  ##### Pagination strategy: start
1257
1293
 
1258
1294
  In comparison to the `offset` strategy, the `start` strategy indicates with which item the current page starts.
data/lib/lhs.rb CHANGED
@@ -58,6 +58,8 @@ module LHS
58
58
  'lhs/pagination/offset'
59
59
  autoload :Page,
60
60
  'lhs/pagination/page'
61
+ autoload :TotalPages,
62
+ 'lhs/pagination/total_pages'
61
63
  autoload :Start,
62
64
  'lhs/pagination/start'
63
65
  autoload :Link,
@@ -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])
@@ -22,6 +22,8 @@ class LHS::Record
22
22
  case pagination_strategy.to_sym
23
23
  when :page
24
24
  LHS::Pagination::Page
25
+ when :total_pages
26
+ LHS::Pagination::TotalPages
25
27
  when :start
26
28
  LHS::Pagination::Start
27
29
  when :link
@@ -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)
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class LHS::Pagination::TotalPages < LHS::Pagination::Page
4
+
5
+ def total
6
+ (data._raw.dig(*_record.total_key) || 0) * limit
7
+ end
8
+ alias count total
9
+ end
data/lib/lhs/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LHS
4
- VERSION = '25.0.0'
4
+ VERSION = '25.1.0'
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
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Record do
6
+ context 'pagination' do
7
+
8
+ let(:page_1_json) do
9
+ {
10
+ items: [1, 2],
11
+ total_pages: 3,
12
+ page: 1,
13
+ limit: 2
14
+ }.to_json
15
+ end
16
+
17
+ let(:page_2_json) do
18
+ {
19
+ items: [3, 4],
20
+ total_pages: 3,
21
+ page: 2,
22
+ limit: 2
23
+ }.to_json
24
+ end
25
+
26
+ let(:page_3_json) do
27
+ {
28
+ items: [5, 6],
29
+ total_pages: 3,
30
+ page: 3,
31
+ limit: 2
32
+ }.to_json
33
+ end
34
+
35
+ before do
36
+ class Feedback < LHS::Record
37
+ configuration pagination_strategy: :total_pages, total_key: :total_pages, pagination_key: :page
38
+ endpoint 'http://local.ch/v2/feedbacks'
39
+ end
40
+ stub_request(:get, 'http://local.ch/v2/feedbacks?limit=100').to_return(body: page_1_json)
41
+ stub_request(:get, 'http://local.ch/v2/feedbacks?limit=2&page=2').to_return(body: page_2_json)
42
+ stub_request(:get, 'http://local.ch/v2/feedbacks?limit=2&page=3').to_return(body: page_3_json)
43
+ end
44
+
45
+ it 'responds to limit_value' do
46
+ feedbacks = Feedback.all.fetch
47
+ expect(feedbacks.length).to eq 6
48
+ expect(feedbacks.count).to eq 6
49
+ expect(feedbacks.items.as_json).to eq [1, 2, 3, 4, 5, 6]
50
+ end
51
+ end
52
+ 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: 25.0.0
4
+ version: 25.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - https://github.com/local-ch/lhs/graphs/contributors
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-07 00:00:00.000000000 Z
11
+ date: 2021-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -241,28 +241,18 @@ extensions: []
241
241
  extra_rdoc_files: []
242
242
  files:
243
243
  - ".bundler-version"
244
+ - ".github/workflows/rubocop.yml"
245
+ - ".github/workflows/test-active-support-5.yml"
246
+ - ".github/workflows/test.yml"
244
247
  - ".gitignore"
245
248
  - ".rubocop.localch.yml"
246
249
  - ".rubocop.yml"
247
250
  - ".ruby-version"
248
251
  - Gemfile
249
- - Gemfile.activesupport4
250
252
  - Gemfile.activesupport5
251
253
  - LICENSE
252
254
  - README.md
253
255
  - Rakefile
254
- - cider-ci.yml
255
- - cider-ci/bin/bundle
256
- - cider-ci/bin/ruby_install
257
- - cider-ci/bin/ruby_version
258
- - cider-ci/jobs/rspec-activesupport-4.yml
259
- - cider-ci/jobs/rspec-activesupport-5.yml
260
- - cider-ci/jobs/rspec-activesupport-latest.yml
261
- - cider-ci/jobs/rubocop.yml
262
- - cider-ci/task_components/bundle.yml
263
- - cider-ci/task_components/rspec.yml
264
- - cider-ci/task_components/rubocop.yml
265
- - cider-ci/task_components/ruby.yml
266
256
  - docs/accessing-data-in-lhs.png
267
257
  - friday.yml
268
258
  - lhs.gemspec
@@ -331,6 +321,7 @@ files:
331
321
  - lib/lhs/pagination/offset.rb
332
322
  - lib/lhs/pagination/page.rb
333
323
  - lib/lhs/pagination/start.rb
324
+ - lib/lhs/pagination/total_pages.rb
334
325
  - lib/lhs/problems/base.rb
335
326
  - lib/lhs/problems/errors.rb
336
327
  - lib/lhs/problems/nested/base.rb
@@ -389,6 +380,7 @@ files:
389
380
  - spec/dummy/app/mailers/.keep
390
381
  - spec/dummy/app/models/.keep
391
382
  - spec/dummy/app/models/concerns/.keep
383
+ - spec/dummy/app/models/concerns/dummy_customer/some_concern.rb
392
384
  - spec/dummy/app/models/dummy_customer.rb
393
385
  - spec/dummy/app/models/dummy_record.rb
394
386
  - spec/dummy/app/models/dummy_record_with_auto_oauth_provider.rb
@@ -465,6 +457,7 @@ files:
465
457
  - spec/pagination/link/total_spec.rb
466
458
  - spec/pagination/offset/pages_left_spec.rb
467
459
  - spec/pagination/parameters_spec.rb
460
+ - spec/pagination/total_pages_spec.rb
468
461
  - spec/proxy/create_sub_resource_spec.rb
469
462
  - spec/proxy/load_spec.rb
470
463
  - spec/proxy/record_identification_spec.rb
@@ -504,8 +497,10 @@ files:
504
497
  - spec/record/href_for_spec.rb
505
498
  - spec/record/ignore_errors_spec.rb
506
499
  - spec/record/immutable_chains_spec.rb
500
+ - spec/record/includes_after_expansion_spec.rb
507
501
  - spec/record/includes_expanded_spec.rb
508
502
  - spec/record/includes_first_page_spec.rb
503
+ - spec/record/includes_missing_spec.rb
509
504
  - spec/record/includes_spec.rb
510
505
  - spec/record/includes_warning_spec.rb
511
506
  - spec/record/item_key_spec.rb
@@ -554,7 +549,7 @@ homepage: https://github.com/local-ch/lhs
554
549
  licenses:
555
550
  - GPL-3.0
556
551
  metadata: {}
557
- post_install_message:
552
+ post_install_message:
558
553
  rdoc_options: []
559
554
  require_paths:
560
555
  - lib
@@ -570,8 +565,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
570
565
  version: '0'
571
566
  requirements:
572
567
  - Ruby >= 2.3.0
573
- rubygems_version: 3.0.6
574
- signing_key:
568
+ rubygems_version: 3.1.4
569
+ signing_key:
575
570
  specification_version: 4
576
571
  summary: 'REST services accelerator: Rails gem providing an easy, active-record-like
577
572
  interface for http (hypermedia) json services'
@@ -619,6 +614,7 @@ test_files:
619
614
  - spec/dummy/app/mailers/.keep
620
615
  - spec/dummy/app/models/.keep
621
616
  - spec/dummy/app/models/concerns/.keep
617
+ - spec/dummy/app/models/concerns/dummy_customer/some_concern.rb
622
618
  - spec/dummy/app/models/dummy_customer.rb
623
619
  - spec/dummy/app/models/dummy_record.rb
624
620
  - spec/dummy/app/models/dummy_record_with_auto_oauth_provider.rb
@@ -695,6 +691,7 @@ test_files:
695
691
  - spec/pagination/link/total_spec.rb
696
692
  - spec/pagination/offset/pages_left_spec.rb
697
693
  - spec/pagination/parameters_spec.rb
694
+ - spec/pagination/total_pages_spec.rb
698
695
  - spec/proxy/create_sub_resource_spec.rb
699
696
  - spec/proxy/load_spec.rb
700
697
  - spec/proxy/record_identification_spec.rb
@@ -734,8 +731,10 @@ test_files:
734
731
  - spec/record/href_for_spec.rb
735
732
  - spec/record/ignore_errors_spec.rb
736
733
  - spec/record/immutable_chains_spec.rb
734
+ - spec/record/includes_after_expansion_spec.rb
737
735
  - spec/record/includes_expanded_spec.rb
738
736
  - spec/record/includes_first_page_spec.rb
737
+ - spec/record/includes_missing_spec.rb
739
738
  - spec/record/includes_spec.rb
740
739
  - spec/record/includes_warning_spec.rb
741
740
  - spec/record/item_key_spec.rb
@@ -1,5 +0,0 @@
1
- source 'https://rubygems.org/'
2
-
3
- gemspec
4
- gem 'activesupport', '~> 4.2.11'
5
- gem 'bundler', '~> 1.17.3'
data/cider-ci.yml DELETED
@@ -1,6 +0,0 @@
1
- jobs:
2
- include:
3
- - cider-ci/jobs/rspec-activesupport-4.yml
4
- - cider-ci/jobs/rspec-activesupport-5.yml
5
- - cider-ci/jobs/rspec-activesupport-latest.yml
6
- - cider-ci/jobs/rubocop.yml
data/cider-ci/bin/bundle DELETED
@@ -1,51 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -eux
3
-
4
- export PATH=~/.rubies/$RUBY/bin:$PATH
5
- rm -f .bundle/config
6
-
7
- if [ ! -f ~/.rubies/$RUBY/bin/bundle ]; then
8
- gem install bundler
9
- fi
10
-
11
- # install bundler v. 1.17.3 in order to be able to run the tests with
12
- # ACTIVESUPPORT=4 because rails (= 4.2.0) depends on bundler (< 2.0, >= 1.3.0)
13
- gem install bundler:1.17.3
14
-
15
- sed "s/^source 'https:\/\/rubygems\.intra\.local\.ch'*/source 'http\:\/\/52.29.7.59:9292'/g" Gemfile > Gemfile.tmp
16
- mv Gemfile.tmp Gemfile
17
-
18
- DIGEST=$(git ls-tree HEAD --\
19
- cider-ci.yml cider-ci Gemfile.lock \
20
- | openssl dgst -sha1 | cut -d ' ' -f 2)
21
-
22
- if [ ! -z ${ACTIVESUPPORT:-} ]; then
23
- DIGEST=$(echo "$DIGEST $ACTIVESUPPORT")
24
- fi
25
-
26
- DIGEST=$(echo "$DIGEST $PATH" \
27
- | openssl dgst -sha1 | cut -d ' ' -f 2)
28
-
29
- echo "DIGEST"
30
- echo "${DIGEST}"
31
-
32
- CACHE_SIGNATURE_FILE="/tmp/bundle_cache_signature_${DIGEST}"
33
-
34
- if [ ! -f $CACHE_SIGNATURE_FILE ] ; then
35
- if [ ! -z ${ACTIVESUPPORT:-} ]; then
36
- if [ ! -z ${BUNDLER:-} ]; then
37
- echo "BUNDLE_GEMFILE=Gemfile.activesupport$ACTIVESUPPORT bundle $BUNDLER install"
38
- BUNDLE_GEMFILE=Gemfile.activesupport$ACTIVESUPPORT bundle $BUNDLER install
39
- else
40
- echo "BUNDLE_GEMFILE=Gemfile.activesupport$ACTIVESUPPORT bundle install"
41
- BUNDLE_GEMFILE=Gemfile.activesupport$ACTIVESUPPORT bundle install
42
- fi
43
- else
44
- echo "bundle install"
45
- bundle $BUNDLER install
46
- fi
47
- touch $CACHE_SIGNATURE_FILE
48
- fi
49
-
50
- echo "bundle install"
51
- bundle $BUNDLER install
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -eux
3
-
4
- export PATH=~/.rubies/$RUBY/bin:$PATH
5
-
6
- if [ ! -d ~/.rubies/$RUBY ]; then
7
- ruby-install --no-install-deps $RUBY
8
- fi
@@ -1,25 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -eux
3
-
4
- if [ -f ./.ruby-version ]; then
5
- echo ".ruby-version file found"
6
- fi
7
-
8
- if [ ! -f ./.ruby-version ]; then
9
- echo ".ruby-version file not found"
10
- exit 1
11
- fi
12
-
13
- IFS='-' read -ra EXPLODED_RUBY <<< "$RUBY"
14
-
15
- if [ "${#EXPLODED_RUBY[@]}" == "1" ]; then
16
- echo 'No engine/version separator "-" found in .ruby-version file.'
17
- exit 1
18
- fi
19
-
20
- if [ "${#EXPLODED_RUBY[@]}" != "1" ] && [ "${#EXPLODED_RUBY[@]}" != "2" ]; then
21
- echo "Unknown format of .ruby-version file"
22
- exit 1
23
- fi
24
-
25
- echo $RUBY
@@ -1,27 +0,0 @@
1
- rspec-active-support-v4:
2
- name: 'rspec with ActiveSupport v4'
3
-
4
- run_when:
5
- 'some HEAD has been updated':
6
- type: branch
7
- include_match: ^.*$
8
-
9
- context:
10
-
11
- script_defaults:
12
- template_environment_variables: true
13
-
14
- task_defaults:
15
- environment_variables:
16
- ACTIVESUPPORT: '4'
17
- BUNDLER: '_1.17.3_'
18
- max_trials: 2
19
- dispatch_storm_delay_duration: 1 Seconds
20
- include:
21
- - cider-ci/task_components/ruby.yml
22
- - cider-ci/task_components/bundle.yml
23
- - cider-ci/task_components/rspec.yml
24
-
25
- tasks:
26
- all-rspec:
27
- name: All rspec tests, using ActiveSupport v4
@@ -1,26 +0,0 @@
1
- rspec-active-support-v5:
2
- name: 'rspec with ActiveSupport v5'
3
-
4
- run_when:
5
- 'some HEAD has been updated':
6
- type: branch
7
- include_match: ^.*$
8
-
9
- context:
10
-
11
- script_defaults:
12
- template_environment_variables: true
13
-
14
- task_defaults:
15
- environment_variables:
16
- ACTIVESUPPORT: '5'
17
- max_trials: 2
18
- dispatch_storm_delay_duration: 1 Seconds
19
- include:
20
- - cider-ci/task_components/ruby.yml
21
- - cider-ci/task_components/bundle.yml
22
- - cider-ci/task_components/rspec.yml
23
-
24
- tasks:
25
- all-rspec:
26
- name: All rspec tests, using ActiveSupport v5
@@ -1,24 +0,0 @@
1
- rspec-active-support-latest:
2
- name: 'rspec with ActiveSupport latest'
3
-
4
- run_when:
5
- 'some HEAD has been updated':
6
- type: branch
7
- include_match: ^.*$
8
-
9
- context:
10
-
11
- script_defaults:
12
- template_environment_variables: true
13
-
14
- task_defaults:
15
- max_trials: 2
16
- dispatch_storm_delay_duration: 1 Seconds
17
- include:
18
- - cider-ci/task_components/ruby.yml
19
- - cider-ci/task_components/bundle.yml
20
- - cider-ci/task_components/rspec.yml
21
-
22
- tasks:
23
- all-rspec:
24
- name: All rspec tests, using ActiveSupport latest
@@ -1,18 +0,0 @@
1
- rubocop:
2
- name: 'Rubocop'
3
-
4
- run_when:
5
- 'some HEAD has been updated':
6
- type: branch
7
- include_match: ^.*$
8
-
9
- context:
10
-
11
- tasks:
12
-
13
- rubocop:
14
-
15
- include:
16
- - cider-ci/task_components/ruby.yml
17
- - cider-ci/task_components/bundle.yml
18
- - cider-ci/task_components/rubocop.yml
@@ -1,22 +0,0 @@
1
- traits:
2
- ruby-install: true
3
- Bash: true
4
-
5
- trial_attachments:
6
- gemfile:
7
- include_match: Gemfile
8
- content_type: text/plain
9
-
10
- environment_variables:
11
- BUNDLER:
12
- read_and_replace_with: .bundler-version
13
-
14
- scripts:
15
-
16
- bundle:
17
- exclusive_executor_resource: ruby-install_{{$RUBY}}
18
- timeout: 20 Minutes
19
- body: cider-ci/bin/bundle
20
- start_when:
21
- 'ruby installed':
22
- script_key: ruby-install
@@ -1,37 +0,0 @@
1
- ports:
2
- CAPYBARA_PORT:
3
- min: 8000
4
- max: 8999
5
- PHANTOMJS_PORT:
6
- min: 44600
7
- max: 44999
8
-
9
- environment_variables:
10
- RUBY:
11
- read_and_replace_with: .ruby-version
12
- BUNDLER:
13
- read_and_replace_with: .bundler-version
14
-
15
- scripts:
16
- rspec:
17
- body: |
18
- #!/usr/bin/env bash
19
- set -eux
20
- mkdir -p tmp/cache
21
- export PATH=~/.rubies/$RUBY/bin:$PATH
22
- if [ ! -z ${ACTIVESUPPORT:-} ]; then BUNDLE_GEMFILE=Gemfile.activesupport$ACTIVESUPPORT bundle $BUNDLER exec rspec; else bundle exec rspec; fi
23
-
24
- start_when:
25
- 'bundled':
26
- script_key: bundle
27
-
28
- trial_attachments:
29
- logs:
30
- include_match: log\/.*\.log$
31
- content_type: text/plain
32
- image-screenshots:
33
- include_match: tmp\/capybara\/.*\.png$
34
- content_type: image/png
35
- html-screenshots:
36
- include_match: tmp\/capybara\/.*\.html$
37
- content_type: text/html
@@ -1,29 +0,0 @@
1
- trial_attachments:
2
- logs:
3
- include_match: tmp\/checkstyle.json$
4
- content_type: application/json
5
-
6
- tree_attachments:
7
- logs:
8
- include_match: tmp\/checkstyle.json$
9
- content_type: application/json
10
-
11
- environment_variables:
12
- RUBY:
13
- read_and_replace_with: .ruby-version
14
- RESULT_PATH: 'tmp/checkstyle.json'
15
-
16
- max_trials: 1
17
-
18
- scripts:
19
- rubocop:
20
- start_when:
21
- 'bundled':
22
- script_key: bundle
23
- body: |
24
- #!/usr/bin/env bash
25
- set -eux
26
- mkdir -p tmp/cache
27
- export PATH=~/.rubies/$RUBY/bin:$PATH
28
- bundle exec rubocop --config .rubocop.yml \
29
- --format json --out $RESULT_PATH --format progress
@@ -1,15 +0,0 @@
1
- environment_variables:
2
- RUBY:
3
- read_and_replace_with: .ruby-version
4
-
5
- scripts:
6
- ruby-version:
7
- body: cider-ci/bin/ruby_version
8
- ruby-install:
9
- exclusive_executor_resource: ruby-install_{{$RUBY}}
10
- timeout: 20 Minutes
11
- body: cider-ci/bin/ruby_install
12
- start_when:
13
- 'ruby version checked':
14
- script_key: ruby-version
15
-