lhs 24.0.0 → 24.1.2

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: e31a9b37f1bc0f12b3a6c87933b145781ed3054e08ea4ea347d5b27d00a069ea
4
- data.tar.gz: d67f414e70fdcae5567dcf5c81c2e2dec93237026e829c9dc9522df5eb778480
3
+ metadata.gz: 9bf423437a22db27b055a47b11b77edad75d4fb22895330bb33b439c03d9e89f
4
+ data.tar.gz: 228b803160ce5cfeaa801e25eac36a84fa75196ca906183336e649cd17c5604a
5
5
  SHA512:
6
- metadata.gz: f39832a96aa989660bfbaf051c53bd53c647d4e75f7b9fa3ca81ab1243ec94bd17828da931207f80fd57a9f98f38188cca659143912a01a4ffc5e197090f6b3a
7
- data.tar.gz: 19ea228303da96f4f4e831825c19c98ea9a81c15b76ad645b3ecbe23532f0a7336eb87d815f432f2d25ee5d6f0c07d98963ed0ba5388022cd79521cd0ae04424
6
+ metadata.gz: dd83a4d879c72a201b29420021562da78945a1ef731a87023c735efe90144f1d088318c293064d9361aa559df8405132d88af0011225c43e675144d1c5af7b5f
7
+ data.tar.gz: 6da5e46c3e113bbf48a3821a02b88a6379bd54846889acb7cf77ce269be9645404d443656215979d7b3311ae1139ba07c00993542cacbd17562dc79b733af8eb
data/README.md CHANGED
@@ -126,6 +126,7 @@ record.review # "Lunch was great
126
126
  * [Include various levels of linked data](#include-various-levels-of-linked-data)
127
127
  * [Identify and cast known records when including records](#identify-and-cast-known-records-when-including-records)
128
128
  * [Apply options for requests performed to fetch included records](#apply-options-for-requests-performed-to-fetch-included-records)
129
+ * [compact: Remove included resources that didn't return any records](#compact-remove-included-resources-that-didnt-return-any-records)
129
130
  * [Record batch processing](#record-batch-processing)
130
131
  * [all](#all-1)
131
132
  * [Using all, when endpoint does not implement response pagination meta data](#using-all-when-endpoint-does-not-implement-response-pagination-meta-data)
@@ -149,12 +150,15 @@ record.review # "Lunch was great
149
150
  * [Test query chains](#test-query-chains)
150
151
  * [By explicitly resolving the chain: fetch](#by-explicitly-resolving-the-chain-fetch)
151
152
  * [Without resolving the chain: where_values_hash](#without-resolving-the-chain-where_values_hash)
153
+ * [Extended developer documentation](#extended-developer-documentation)
154
+ * [Accessing data in LHS](#accessing-data-in-lhs)
152
155
  * [License](#license)
153
156
 
154
157
 
155
158
 
156
159
 
157
160
 
161
+
158
162
  ## Installation/Startup checklist
159
163
 
160
164
  - [ ] Install LHS gem, preferably via `Gemfile`
@@ -1698,7 +1702,7 @@ record.partial_update(recommended: true)
1698
1702
 
1699
1703
  ```
1700
1704
  ```
1701
- POST https://service.example.com/records/1z-5r1fkaj { body: "{ 'name': 'Starbucks', 'recommended': true }" }
1705
+ POST https://service.example.com/records/1z-5r1fkaj { body: "{ 'recommended': true }" }
1702
1706
  ```
1703
1707
 
1704
1708
  -> See [record validation](#record-validation) for how to handle validation errors when updating records.
@@ -2290,6 +2294,54 @@ feedback = Feedback
2290
2294
  .find(12345)
2291
2295
  ```
2292
2296
 
2297
+ #### compact: Remove included resources that didn't return any records
2298
+
2299
+ In case you include nested data and ignored errors while including, it can happen that you get back a collection that contains data based on response errors:
2300
+
2301
+ ```ruby
2302
+ # app/controllers/some_controller.rb
2303
+
2304
+ user = User
2305
+ .includes(:places)
2306
+ .references(places: { ignore: LHC::NotFound })
2307
+ .find(123)
2308
+ ```
2309
+
2310
+ ```
2311
+ GET http://service/users/123
2312
+ { "places": { "href": "http://service/users/123/places" } }
2313
+
2314
+ GET http://service/users/123/places
2315
+ { "items": [
2316
+ { "href": "http://service/places/1" },
2317
+ { "href": "http://service/places/2" }
2318
+ ] }
2319
+
2320
+ GET http://service/places/1
2321
+ 200 { "name": "Casa Ferlin" }
2322
+
2323
+ GET http://service/places/2
2324
+ 404 { "status": 404, "error": "not found" }
2325
+ ```
2326
+
2327
+ ```ruby
2328
+ user.places[1] # { "status": 404, "error": "not found" }
2329
+ ```
2330
+
2331
+ In order to exclude items from a collection which where not based on successful responses, use `.compact` or `.compact!`:
2332
+
2333
+ ```ruby
2334
+ # app/controllers/some_controller.rb
2335
+
2336
+ user = User
2337
+ .includes(:places)
2338
+ .references(places: { ignore: LHC::NotFound })
2339
+ .find(123)
2340
+ places = user.places.compact
2341
+
2342
+ places # { "items": [ { "href": "http://service/places/1", "name": "Casa Ferlin" } ] }
2343
+ ```
2344
+
2293
2345
  ### Record batch processing
2294
2346
 
2295
2347
  **Be careful using methods for batch processing. They could result in a lot of HTTP requests!**
@@ -2830,6 +2882,12 @@ expect(
2830
2882
  ).to eq {color: 'red', available: true}
2831
2883
  ```
2832
2884
 
2885
+ ## Extended developer documentation
2886
+
2887
+ ### Accessing data in LHS
2888
+
2889
+ ![diagram](docs/accessing-data-in-lhs.png)
2890
+
2833
2891
  ## License
2834
2892
 
2835
2893
  [GNU General Public License Version 3.](https://www.gnu.org/licenses/gpl-3.0.en.html)
@@ -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, :compact, to: :raw
17
+ :<<, :push, to: :raw
18
18
 
19
19
  def initialize(raw, parent, record)
20
20
  self.raw = raw
@@ -36,13 +36,37 @@ class LHS::Collection < LHS::Proxy
36
36
  end
37
37
  end
38
38
 
39
+ def compact
40
+ dup.tap do |collection|
41
+ collection.compact! if collection.raw.present?
42
+ end
43
+ end
44
+
45
+ def compact!
46
+ self.raw = raw.map do |item|
47
+ if item.is_a?(LHS::Data) && item._request && !item._request.response.success?
48
+ nil
49
+ else
50
+ cast_item(item)
51
+ end
52
+ end.compact
53
+ end
54
+
39
55
  private
40
56
 
41
57
  def cast_item(item)
42
- record_by_href = LHS::Record.for_url(item[:href]) if item[:href]
43
58
  data = LHS::Data.new(item, @parent, @record)
44
- return (record_by_href || @record).new(data) if record_by_href || @record
45
- data
59
+ (record_by_href(item) || @record)&.new(data) || data
60
+ end
61
+
62
+ def record_by_href(item)
63
+ return if plain_value?(item) || item[:href].blank?
64
+
65
+ LHS::Record.for_url(item[:href])
66
+ end
67
+
68
+ def plain_value?(item)
69
+ item.is_a?(String) || item.is_a?(Numeric) || item.is_a?(TrueClass) || item.is_a?(FalseClass)
46
70
  end
47
71
  end
48
72
  end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+
5
+ class LHS::Data
6
+
7
+ module Extend
8
+ extend ActiveSupport::Concern
9
+
10
+ # Extends already fetched data (self) with additionally
11
+ # fetched data (addition) using the given key
12
+ def extend!(addition, key)
13
+ addition = cast_relation_class_for_extension(addition, key)
14
+ if collection?
15
+ extend_collection!(addition, key)
16
+ elsif self[key]._raw.is_a? Array
17
+ extend_array!(addition, key)
18
+ elsif item?
19
+ extend_item!(addition, key)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def cast_relation_class_for_extension(addition, key)
26
+ return addition if _record.nil? || _record._relations.nil? || _record._relations[key].nil?
27
+ addition.becomes(_record._relations[key][:record_class_name].constantize, errors: addition.errors, warnings: addition.warnings)
28
+ end
29
+
30
+ def extend_collection!(addition, key)
31
+ map do |item|
32
+ item_raw = item._raw[key]
33
+ item_raw.blank? ? [nil] : item_raw
34
+ end
35
+ .flatten
36
+ .each_with_index do |item, index|
37
+ item_addition = addition[index]
38
+ next if item_addition.nil? || item.nil?
39
+ if item_addition._raw.is_a?(Array)
40
+ item[items_key] ||= []
41
+ item[items_key].concat(item_addition._raw)
42
+ else
43
+ item.merge! item_addition._raw
44
+ end
45
+ end
46
+ end
47
+
48
+ def extend_array!(addition, key)
49
+ self[key].zip(addition) do |item, additional_item|
50
+ item._raw.merge!(additional_item._raw) if additional_item.present?
51
+ end
52
+ end
53
+
54
+ def extend_item!(addition, key)
55
+ return if addition.nil?
56
+ if addition.collection?
57
+ extend_item_with_collection!(addition, key)
58
+ else # simple case merges hash into hash
59
+ _raw[key.to_sym].merge!(addition._raw)
60
+ end
61
+ end
62
+
63
+ def extend_item_with_collection!(addition, key)
64
+ target = self[key]
65
+ if target._raw.is_a? Array
66
+ self[key] = addition.map(&:_raw)
67
+ else # hash with items
68
+ extend_item_with_hash_containing_items!(target, addition)
69
+ end
70
+ end
71
+
72
+ def extend_item_with_hash_containing_items!(target, addition)
73
+ LHS::Collection.nest(input: target._raw, value: [], record: self) # inits the nested collection
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)
76
+ else
77
+ LHS::Collection.access(input: target._raw, record: self).each_with_index do |item, index|
78
+ item.merge!(addition[index])
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -98,74 +98,6 @@ class LHS::Record
98
98
  )
99
99
  end
100
100
 
101
- # Extends existing raw data with additionaly fetched data
102
- def extend_raw_data!(data, addition, key)
103
- if data.collection?
104
- extend_base_collection!(data, addition, key)
105
- elsif data[key]._raw.is_a? Array
106
- extend_base_array!(data, addition, key)
107
- elsif data.item?
108
- extend_base_item!(data, addition, key)
109
- end
110
- end
111
-
112
- def extend_base_collection!(data, addition, key)
113
- data.map do |item|
114
- item_raw = item._raw[key]
115
- item_raw.blank? ? [nil] : item_raw
116
- end
117
- .flatten
118
- .each_with_index do |item, index|
119
- item_addition = addition[index]
120
- next if item_addition.nil? || item.nil?
121
- if item_addition._raw.is_a?(Array)
122
- extend_base_collection_with_array!(item, item_addition._raw)
123
- else
124
- item.merge! item_addition._raw
125
- end
126
- end
127
- end
128
-
129
- def extend_base_collection_with_array!(item, addition)
130
- item[items_key] ||= []
131
- item[items_key].concat(addition)
132
- end
133
-
134
- def extend_base_array!(data, addition, key)
135
- data[key].zip(addition) do |item, additional_item|
136
- item._raw.merge!(additional_item._raw) if additional_item.present?
137
- end
138
- end
139
-
140
- def extend_base_item!(data, addition, key)
141
- return if addition.nil?
142
- if addition.collection?
143
- extend_base_item_with_collection!(data, addition, key)
144
- else # simple case merges hash into hash
145
- data._raw[key.to_sym].merge!(addition._raw)
146
- end
147
- end
148
-
149
- def extend_base_item_with_collection!(data, addition, key)
150
- target = data[key]
151
- if target._raw.is_a? Array
152
- data[key] = addition.map(&:_raw)
153
- else # hash with items
154
- extend_base_item_with_hash_of_items!(target, addition)
155
- end
156
- end
157
-
158
- def extend_base_item_with_hash_of_items!(target, addition)
159
- LHS::Collection.nest(input: target._raw, value: [], record: self)
160
- if LHS::Collection.access(input: target._raw, record: self).empty?
161
- LHS::Collection.nest(input: target._raw, value: addition.compact.map(&:_raw), record: self)
162
- else
163
- LHS::Collection.access(input: target._raw, record: self).each_with_index do |item, index|
164
- item.merge!(addition[index])
165
- end
166
- end
167
- end
168
-
169
101
  def handle_includes(includes, data, references = {})
170
102
  references ||= {}
171
103
  if includes.is_a? Hash
@@ -187,8 +119,8 @@ class LHS::Record
187
119
  options = options_for_data(data, included)
188
120
  options = extend_with_reference(options, reference)
189
121
  addition = load_include(options, data, sub_includes, reference)
190
- extend_raw_data!(data, addition, included)
191
- expand_addition!(data, included, options) unless expanded_data?(addition)
122
+ data.extend!(addition, included)
123
+ expand_addition!(data, included, reference) unless expanded_data?(addition)
192
124
  end
193
125
  end
194
126
 
@@ -210,7 +142,7 @@ class LHS::Record
210
142
  record = record_for_options(options) || self
211
143
  options = convert_options_to_endpoints(options) if record_for_options(options)
212
144
  expanded_data = record.request(options)
213
- extend_raw_data!(data, expanded_data, included)
145
+ data.extend!(expanded_data, included)
214
146
  end
215
147
 
216
148
  def expanded_data?(addition)
@@ -6,6 +6,8 @@ class LHS::Data
6
6
  'lhs/concerns/data/becomes'
7
7
  autoload :Equality,
8
8
  'lhs/concerns/data/equality'
9
+ autoload :Extend,
10
+ 'lhs/concerns/data/extend'
9
11
  autoload :Json,
10
12
  'lhs/concerns/data/json'
11
13
  autoload :ToHash,
@@ -13,6 +15,7 @@ class LHS::Data
13
15
 
14
16
  include Becomes
15
17
  include Equality
18
+ include Extend
16
19
  include Json
17
20
  include ToHash
18
21
  include LHS::Inspect
@@ -30,6 +33,7 @@ class LHS::Data
30
33
  self._proxy = proxy_from_input(input)
31
34
  self._request = request
32
35
  self._endpoint = endpoint
36
+ preserve_input_requests!(input)
33
37
  end
34
38
 
35
39
  # merging data
@@ -97,6 +101,17 @@ class LHS::Data
97
101
 
98
102
  private
99
103
 
104
+ def preserve_input_requests!(input)
105
+ if input.is_a?(LHS::Data)
106
+ _request = input._request if _request.nil?
107
+ elsif input.is_a?(Array) && input.first.is_a?(LHS::Data)
108
+ input.each_with_index do |item, index|
109
+ next if item.nil?
110
+ self[index]._request = item._request
111
+ end
112
+ end
113
+ end
114
+
100
115
  def collection_proxy?(input)
101
116
  (input.is_a?(Hash) && LHS::Collection.access(input: input, record: _record)) ||
102
117
  input.is_a?(Array) ||
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LHS
4
- VERSION = '24.0.0'
4
+ VERSION = '24.1.2'
5
5
  end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Record do
6
+ before do
7
+ class Place < LHS::Record
8
+ endpoint 'http://datastore/places/{id}'
9
+ endpoint 'http://datastore/users/{user_id}/places/{id}'
10
+
11
+ def display_name
12
+ "*#{name}*"
13
+ end
14
+ end
15
+
16
+ class User < LHS::Record
17
+ endpoint 'http://datastore/users/{id}'
18
+ end
19
+
20
+ stub_request(:get, 'http://datastore/users/123')
21
+ .to_return(status: 200, body: {
22
+ href: 'http://datastore/users/123',
23
+ places: { href: 'http://datastore/users/123/places' }
24
+ }.to_json)
25
+
26
+ stub_request(:get, 'http://datastore/users/123/places?limit=100')
27
+ .to_return(status: 200, body: {
28
+ href: 'http://datastore/users/123/places?offset=0&limit=100',
29
+ items: [
30
+ {
31
+ href: 'http://datastore/users/123/places/789'
32
+ }, {
33
+ href: 'http://datastore/users/123/places/790'
34
+ }
35
+ ],
36
+ total: 2,
37
+ offset: 0,
38
+ limit: 10
39
+ }.to_json)
40
+
41
+ stub_request(:get, 'http://datastore/users/123/places/789')
42
+ .to_return(
43
+ body: {
44
+ href: 'http://datastore/users/123/places/789?limit=100',
45
+ name: 'Mc Donalds'
46
+ }.to_json
47
+ )
48
+
49
+ stub_request(:get, 'http://datastore/users/123/places/790')
50
+ .to_return(
51
+ status: 404,
52
+ body: {
53
+ status: 404,
54
+ message: 'The requested resource does not exist.'
55
+ }.to_json
56
+ )
57
+
58
+ end
59
+
60
+ let(:places) do
61
+ User
62
+ .includes(:places)
63
+ .references(places: { ignore: LHC::NotFound })
64
+ .find('123')
65
+ .places
66
+ end
67
+
68
+ context '.compact' do
69
+ it 'removes linked resouces which could not get fetched' do
70
+ expect(places.compact.length).to eq 1
71
+ expect(places.length).not_to eq 1 # leaves the original intact
72
+ end
73
+ end
74
+
75
+ context 'record casting' do
76
+ let(:expected_display_name) { '*Mc Donalds*' }
77
+
78
+ it 'finds the right record class' do
79
+ expect(places.first.display_name).to eq expected_display_name
80
+ expect(places.compact.map(&:display_name)).to eq [expected_display_name]
81
+ end
82
+ end
83
+
84
+ context '.compact!' do
85
+ it 'removes linked resouces which could not get fetched' do
86
+ expect(places.compact!.length).to eq 1
87
+ expect(places.length).to eq 1 # and changes the original intact
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Record do
6
+ context 'includes all (expanded)' do
7
+ before do
8
+ class Record < LHS::Record
9
+ endpoint 'http://records/{id}'
10
+ end
11
+
12
+ stub_request(:get, "http://records/1")
13
+ .to_return(
14
+ body: {
15
+ car: { href: 'http://records/1/car' }
16
+ }.to_json
17
+ )
18
+
19
+ stub_request(:get, "http://records/1/car?color=blue&limit=100")
20
+ .to_return(
21
+ body: { href: 'http://records/cars/1' }.to_json
22
+ )
23
+
24
+ stub_request(:get, "http://records/cars/1?color=blue&limit=100")
25
+ .to_return(
26
+ body: { name: 'wrum wrum' }.to_json
27
+ )
28
+ end
29
+
30
+ it 'expands linked resources and forwards proper reference' do
31
+ record = Record.includes(:car).references(car: { params: { color: :blue } }).find(1)
32
+ expect(
33
+ record.car.name
34
+ ).to eq 'wrum wrum'
35
+ end
36
+ end
37
+ end
@@ -8,6 +8,14 @@ describe LHS::Record do
8
8
  class Customer < LHS::Record
9
9
  endpoint 'http://datastore/customers/{id}'
10
10
  end
11
+
12
+ class User < LHS::Record
13
+ endpoint 'http://datastore/users/{id}'
14
+ endpoint 'http://datastore/customers/{customer_id}/users/{id}'
15
+ def reversed_name
16
+ name.split.reverse.join(' ')
17
+ end
18
+ end
11
19
  end
12
20
 
13
21
  let!(:customer_request) do
@@ -18,6 +26,9 @@ describe LHS::Record do
18
26
  },
19
27
  'contact_addresses' => {
20
28
  'href' => "http://datastore/contact_addresses"
29
+ },
30
+ 'users' => {
31
+ 'href' => 'http://datastore/customers/1/users'
21
32
  }
22
33
  }.to_json)
23
34
  end
@@ -49,5 +60,37 @@ describe LHS::Record do
49
60
  assert_requested(electronic_addresses_request)
50
61
  assert_requested(contact_addresses_request)
51
62
  end
63
+
64
+ describe 'mapping related classes correctly' do
65
+ before do
66
+ stub_request(:get, 'http://datastore/customers/1/users?limit=100').to_return(
67
+ status: 200,
68
+ body: {
69
+ href: 'http://datastore/customers/1/users?offset=0&limit=100',
70
+ items: [
71
+ { href: 'http://datastore/customers/1/users/1' }
72
+ ],
73
+ total: 1,
74
+ offset: 0,
75
+ limit: 10
76
+ }.to_json
77
+ )
78
+
79
+ stub_request(:get, 'http://datastore/customers/1/users/1')
80
+ .with(headers: { 'Authentication' => 'Bearer 123' })
81
+ .to_return(body: { href: 'http://datastore/users/1', name: 'Elizabeth Baker' }.to_json)
82
+ end
83
+
84
+ it 'maps correctly' do
85
+ users = Customer
86
+ .includes(:users)
87
+ .references(users: referencing_options)
88
+ .find(1)
89
+ .users
90
+
91
+ expect(users.first.reversed_name).to be_present
92
+ end
93
+ end
94
+
52
95
  end
53
96
  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.0.0
4
+ version: 24.1.2
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-07-30 00:00:00.000000000 Z
11
+ date: 2020-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -263,6 +263,7 @@ files:
263
263
  - cider-ci/task_components/rspec.yml
264
264
  - cider-ci/task_components/rubocop.yml
265
265
  - cider-ci/task_components/ruby.yml
266
+ - docs/accessing-data-in-lhs.png
266
267
  - friday.yml
267
268
  - lhs.gemspec
268
269
  - lib/lhs.rb
@@ -274,6 +275,7 @@ files:
274
275
  - lib/lhs/concerns/configuration.rb
275
276
  - lib/lhs/concerns/data/becomes.rb
276
277
  - lib/lhs/concerns/data/equality.rb
278
+ - lib/lhs/concerns/data/extend.rb
277
279
  - lib/lhs/concerns/data/json.rb
278
280
  - lib/lhs/concerns/data/to_hash.rb
279
281
  - lib/lhs/concerns/inspect.rb
@@ -471,6 +473,7 @@ files:
471
473
  - spec/record/attribute_assignment_spec.rb
472
474
  - spec/record/build_spec.rb
473
475
  - spec/record/cast_nested_data_spec.rb
476
+ - spec/record/compact_spec.rb
474
477
  - spec/record/create_spec.rb
475
478
  - spec/record/creation_failed_spec.rb
476
479
  - spec/record/custom_setters_spec.rb
@@ -501,6 +504,7 @@ files:
501
504
  - spec/record/href_for_spec.rb
502
505
  - spec/record/ignore_errors_spec.rb
503
506
  - spec/record/immutable_chains_spec.rb
507
+ - spec/record/includes_expanded_spec.rb
504
508
  - spec/record/includes_first_page_spec.rb
505
509
  - spec/record/includes_spec.rb
506
510
  - spec/record/includes_warning_spec.rb
@@ -699,6 +703,7 @@ test_files:
699
703
  - spec/record/attribute_assignment_spec.rb
700
704
  - spec/record/build_spec.rb
701
705
  - spec/record/cast_nested_data_spec.rb
706
+ - spec/record/compact_spec.rb
702
707
  - spec/record/create_spec.rb
703
708
  - spec/record/creation_failed_spec.rb
704
709
  - spec/record/custom_setters_spec.rb
@@ -729,6 +734,7 @@ test_files:
729
734
  - spec/record/href_for_spec.rb
730
735
  - spec/record/ignore_errors_spec.rb
731
736
  - spec/record/immutable_chains_spec.rb
737
+ - spec/record/includes_expanded_spec.rb
732
738
  - spec/record/includes_first_page_spec.rb
733
739
  - spec/record/includes_spec.rb
734
740
  - spec/record/includes_warning_spec.rb