forest_liana 7.0.0.beta.4 → 7.0.0.beta.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/forest_liana/actions_controller.rb +2 -2
  3. data/app/controllers/forest_liana/associations_controller.rb +2 -2
  4. data/app/controllers/forest_liana/resources_controller.rb +15 -6
  5. data/app/controllers/forest_liana/scopes_controller.rb +20 -0
  6. data/app/controllers/forest_liana/smart_actions_controller.rb +39 -3
  7. data/app/controllers/forest_liana/stats_controller.rb +5 -5
  8. data/app/services/forest_liana/filters_parser.rb +8 -4
  9. data/app/services/forest_liana/has_many_dissociator.rb +2 -2
  10. data/app/services/forest_liana/has_many_getter.rb +2 -2
  11. data/app/services/forest_liana/leaderboard_stat_getter.rb +20 -14
  12. data/app/services/forest_liana/line_stat_getter.rb +4 -2
  13. data/app/services/forest_liana/permissions_checker.rb +3 -4
  14. data/app/services/forest_liana/permissions_getter.rb +2 -2
  15. data/app/services/forest_liana/pie_stat_getter.rb +6 -3
  16. data/app/services/forest_liana/resource_getter.rb +6 -3
  17. data/app/services/forest_liana/resource_updater.rb +5 -2
  18. data/app/services/forest_liana/resources_getter.rb +6 -5
  19. data/app/services/forest_liana/scope_manager.rb +102 -0
  20. data/app/services/forest_liana/search_query_builder.rb +6 -3
  21. data/app/services/forest_liana/stat_getter.rb +2 -1
  22. data/app/services/forest_liana/value_stat_getter.rb +4 -2
  23. data/config/routes.rb +3 -0
  24. data/lib/forest_liana/version.rb +1 -1
  25. data/spec/dummy/app/controllers/forest/islands_controller.rb +5 -0
  26. data/spec/dummy/config/routes.rb +4 -0
  27. data/spec/dummy/lib/forest_liana/collections/island.rb +7 -0
  28. data/spec/requests/actions_controller_spec.rb +100 -12
  29. data/spec/requests/resources_spec.rb +2 -0
  30. data/spec/services/forest_liana/filters_parser_spec.rb +1 -1
  31. data/spec/services/forest_liana/has_many_getter_spec.rb +116 -0
  32. data/spec/services/forest_liana/line_stat_getter_spec.rb +14 -6
  33. data/spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb +1 -3
  34. data/spec/services/forest_liana/pie_stat_getter_spec.rb +114 -0
  35. data/spec/services/forest_liana/resource_updater_spec.rb +116 -0
  36. data/spec/services/forest_liana/resources_getter_spec.rb +68 -1
  37. data/spec/services/forest_liana/scope_manager_spec.rb +232 -0
  38. data/spec/services/forest_liana/value_stat_getter_spec.rb +96 -0
  39. metadata +18 -13
  40. data/app/services/forest_liana/scope_validator.rb +0 -98
  41. data/test/services/forest_liana/has_many_getter_test.rb +0 -75
  42. data/test/services/forest_liana/pie_stat_getter_test.rb +0 -29
  43. data/test/services/forest_liana/resource_updater_test.rb +0 -86
  44. data/test/services/forest_liana/scope_validator_test.rb +0 -185
  45. data/test/services/forest_liana/value_stat_getter_test.rb +0 -71
@@ -6,13 +6,21 @@ module ForestLiana
6
6
  let(:sort) { 'id' }
7
7
  let(:fields) { }
8
8
  let(:filters) { }
9
+ let(:scopes) { { } }
10
+ let(:rendering_id) { 13 }
11
+ let(:user) { { 'id' => '1', 'rendering_id' => rendering_id } }
9
12
 
10
13
  let(:getter) { described_class.new(resource, {
11
14
  page: { size: pageSize, number: pageNumber },
12
15
  sort: sort,
13
16
  fields: fields,
14
17
  filters: filters,
15
- })}
18
+ }, user) }
19
+
20
+ def init_scopes
21
+ ForestLiana::ScopeManager.invalidate_scope_cache(rendering_id)
22
+ allow(ForestLiana::ScopeManager).to receive(:fetch_scopes).and_return(scopes)
23
+ end
16
24
 
17
25
  before(:each) do
18
26
  users = ['Michel', 'Robert', 'Vince', 'Sandro', 'Olesya', 'Romain', 'Valentin', 'Jason', 'Arnaud', 'Jeff', 'Steve', 'Marc', 'Xavier', 'Paul', 'Mickael', 'Mike', 'Maxime', 'Gertrude', 'Monique', 'Mia', 'Rachid', 'Edouard', 'Sacha', 'Caro', 'Amand', 'Nathan', 'Noémie', 'Robin', 'Gaelle', 'Isabelle']
@@ -43,6 +51,7 @@ module ForestLiana
43
51
  ].map { |location| Location.create(coordinates: location[:coordinates], island: location[:island]) }
44
52
 
45
53
  reference = Reference.create()
54
+ init_scopes
46
55
  end
47
56
 
48
57
  after(:each) do
@@ -355,5 +364,63 @@ module ForestLiana
355
364
  )
356
365
  end
357
366
  end
367
+
368
+ describe 'when scopes are defined' do
369
+ let(:resource) { Island }
370
+ let(:pageSize) { 15 }
371
+ let(:fields) { }
372
+ let(:filters) { }
373
+ let(:scopes) {
374
+ {
375
+ 'Island' => {
376
+ 'scope'=> {
377
+ 'filter'=> {
378
+ 'aggregator' => 'and',
379
+ 'conditions' => [
380
+ { 'field' => 'name', 'operator' => 'contains', 'value' => 'u' }
381
+ ]
382
+ },
383
+ 'dynamicScopesValues' => { }
384
+ }
385
+ }
386
+ }
387
+ }
388
+
389
+ describe 'when there are NO filters already defined' do
390
+ it 'should get only the records matching the scope' do
391
+ getter.perform
392
+ records = getter.records
393
+ count = getter.count
394
+
395
+ expect(records.count).to eq 3
396
+ expect(count).to eq 3
397
+ expect(records.first.name).to eq 'Skull'
398
+ expect(records.second.name).to eq 'Muerta'
399
+ expect(records.third.name).to eq 'Treasure'
400
+ end
401
+ end
402
+
403
+ describe 'when there are filters already defined' do
404
+ let(:filters) { {
405
+ aggregator: 'and',
406
+ conditions: [{
407
+ field: 'name',
408
+ operator: 'contains',
409
+ value: 'a',
410
+ }]
411
+ }.to_json }
412
+
413
+ it 'should get only the records matching the scope' do
414
+ getter.perform
415
+ records = getter.records
416
+ count = getter.count
417
+
418
+ expect(records.count).to eq 2
419
+ expect(count).to eq 2
420
+ expect(records.first.name).to eq 'Muerta'
421
+ expect(records.second.name).to eq 'Treasure'
422
+ end
423
+ end
424
+ end
358
425
  end
359
426
  end
@@ -0,0 +1,232 @@
1
+ module ForestLiana
2
+ describe ScopeManager do
3
+ let(:rendering_id) { 13 }
4
+ let(:user) { { 'id' => '1', 'rendering_id' => rendering_id } }
5
+ let(:collection_name) { 'Users' }
6
+ let(:first_collection_scope) {
7
+ {
8
+ 'scope'=> {
9
+ 'filter'=> {
10
+ 'aggregator' => 'and',
11
+ 'conditions' => [
12
+ { 'field' => 'description', 'operator' => 'contains', 'value' => 'check' }
13
+ ]
14
+ },
15
+ 'dynamicScopesValues' => { }
16
+ }
17
+ }
18
+ }
19
+ let(:second_collection_scope) {
20
+ {
21
+ 'scope'=> {
22
+ 'filter'=> {
23
+ 'aggregator' => 'and',
24
+ 'conditions' => [
25
+ { 'field' => 'description', 'operator' => 'contains', 'value' => 'toto' }
26
+ ]
27
+ },
28
+ 'dynamicScopesValues' => { }
29
+ }
30
+ }
31
+ }
32
+ let(:first_json_scopes) { JSON.generate({ collection_name => first_collection_scope }) }
33
+ let(:second_json_scopes) { JSON.generate({ collection_name => second_collection_scope }) }
34
+ let(:first_scopes_api_call_response) { Net::HTTPOK.new({}, 200, first_json_scopes) }
35
+ let(:second_scopes_api_call_response) { Net::HTTPOK.new({}, 200, second_json_scopes) }
36
+
37
+ before do
38
+ described_class.invalidate_scope_cache(rendering_id)
39
+ allow(ForestLiana::ForestApiRequester).to receive(:get).and_return(first_scopes_api_call_response, second_scopes_api_call_response)
40
+ allow(first_scopes_api_call_response).to receive(:body).and_return(first_json_scopes)
41
+ allow(second_scopes_api_call_response).to receive(:body).and_return(second_json_scopes)
42
+ end
43
+
44
+ describe '#get_scope_for_user' do
45
+ describe 'with invalid inputs' do
46
+ it 'should raise an error on missing rendering_id' do
47
+ expect {
48
+ described_class.get_scope_for_user({}, collection_name)
49
+ }.to raise_error 'Missing required rendering_id'
50
+ end
51
+
52
+ it 'should raise an error on missing collection_name' do
53
+ expect {
54
+ described_class.get_scope_for_user(user, nil)
55
+ }.to raise_error 'Missing required collection_name'
56
+ end
57
+ end
58
+
59
+ describe 'when the backend return an errored response' do
60
+ let(:first_scopes_api_call_response) { Net::HTTPNotFound.new({}, 404, nil) }
61
+
62
+ it 'should raise an error' do
63
+ expect {
64
+ described_class.get_scope_for_user(user, collection_name)
65
+ }.to raise_error 'Unable to fetch scopes'
66
+ end
67
+ end
68
+
69
+ describe 'when retrieving scopes once with no cached value' do
70
+ let(:scope) { described_class.get_scope_for_user(user, collection_name) }
71
+
72
+ it 'should fetch the relevant scope and return it' do
73
+ expect(scope).to eq first_collection_scope['scope']['filter']
74
+ expect(ForestLiana::ForestApiRequester).to have_received(:get).once
75
+ expect(ForestLiana::ForestApiRequester).to have_received(:get).with('/liana/scopes', query: { 'renderingId' => rendering_id })
76
+ end
77
+ end
78
+
79
+ describe 'when retrieving scopes twice before the refresh cache delta' do
80
+ let(:scope_first_fetch) { described_class.get_scope_for_user(user, collection_name) }
81
+ let(:scope_second_fetch) { described_class.get_scope_for_user(user, collection_name) }
82
+
83
+ it 'should return the same value twice and have fetch the scopes from the backend only once' do
84
+ expect(scope_first_fetch).to eq first_collection_scope['scope']['filter']
85
+ expect(scope_second_fetch).to eq first_collection_scope['scope']['filter']
86
+ expect(ForestLiana::ForestApiRequester).to have_received(:get).once.with('/liana/scopes', query: { 'renderingId' => rendering_id })
87
+ end
88
+ end
89
+
90
+ describe 'when retrieving scopes twice after the refresh cache delta' do
91
+ let(:scope_first_fetch) { described_class.get_scope_for_user(user, collection_name) }
92
+ let(:scope_second_fetch) { described_class.get_scope_for_user(user, collection_name) }
93
+
94
+ it 'should return same value but trigger a fetch twice' do
95
+ expect(scope_first_fetch).to eq first_collection_scope['scope']['filter']
96
+ allow(Time).to receive(:now).and_return(Time.now + 20.minutes)
97
+ expect(scope_second_fetch).to eq first_collection_scope['scope']['filter']
98
+ # sleep to wait for the Thread to trigger the call to the `ForestApiRequester`
99
+ sleep(0.001)
100
+ expect(ForestLiana::ForestApiRequester).to have_received(:get).twice.with('/liana/scopes', query: { 'renderingId' => rendering_id })
101
+ end
102
+ end
103
+
104
+ describe 'when retrieving scopes three times after the refresh cache delta' do
105
+ let(:scope_first_fetch) { described_class.get_scope_for_user(user, collection_name) }
106
+ let(:scope_second_fetch) { described_class.get_scope_for_user(user, collection_name) }
107
+ let(:scope_third_fetch) { described_class.get_scope_for_user(user, collection_name) }
108
+
109
+ it 'should return a new value on third call and have fetch the scopes from the backend only twice' do
110
+ expect(scope_first_fetch).to eq first_collection_scope['scope']['filter']
111
+ allow(Time).to receive(:now).and_return(Time.now + 20.minutes)
112
+ expect(scope_second_fetch).to eq first_collection_scope['scope']['filter']
113
+ # sleep to wait for the Thread to update the cache
114
+ sleep(0.001)
115
+ expect(scope_third_fetch).to eq second_collection_scope['scope']['filter']
116
+ expect(ForestLiana::ForestApiRequester).to have_received(:get).twice.with('/liana/scopes', query: { 'renderingId' => rendering_id })
117
+ end
118
+ end
119
+
120
+ describe 'when scope contains dynamic values' do
121
+ let(:first_collection_scope) {
122
+ {
123
+ 'scope' => {
124
+ 'filter'=> {
125
+ 'aggregator' => 'and',
126
+ 'conditions' => [
127
+ { 'field' => 'description', 'operator' => 'contains', 'value' => '$currentUser.firstName' }
128
+ ]
129
+ },
130
+ 'dynamicScopesValues' => {
131
+ 'users' => { '1' => { '$currentUser.firstName' => 'Valentin' } }
132
+ }
133
+ }
134
+ }
135
+ }
136
+ let(:scope_filter) { described_class.get_scope_for_user(user, collection_name) }
137
+ let(:expected_filter) {
138
+ {
139
+ 'aggregator' => 'and',
140
+ 'conditions' => [
141
+ { 'field' => 'description', 'operator' => 'contains', 'value' => 'Valentin' }
142
+ ]
143
+ }
144
+ }
145
+
146
+ it 'should replace the dynamic values properly' do
147
+ expect(scope_filter).to eq expected_filter
148
+ expect(ForestLiana::ForestApiRequester).to have_received(:get).once
149
+ expect(ForestLiana::ForestApiRequester).to have_received(:get).with('/liana/scopes', query: { 'renderingId' => rendering_id })
150
+ end
151
+ end
152
+
153
+ describe 'when target collection has no scopes' do
154
+ let(:first_collection_scope) { { } }
155
+ let(:scope_filter) { described_class.get_scope_for_user(user, collection_name) }
156
+
157
+ it 'should return nil' do
158
+ expect(scope_filter).to eq nil
159
+ expect(ForestLiana::ForestApiRequester).to have_received(:get).once
160
+ expect(ForestLiana::ForestApiRequester).to have_received(:get).with('/liana/scopes', query: { 'renderingId' => rendering_id })
161
+ end
162
+ end
163
+
164
+ describe 'when target collection has no scopes' do
165
+ let(:first_collection_scope) { { } }
166
+ let(:scope_filter) { described_class.get_scope_for_user(user, collection_name) }
167
+
168
+ it 'should return nil' do
169
+ expect(scope_filter).to eq nil
170
+ expect(ForestLiana::ForestApiRequester).to have_received(:get).once
171
+ expect(ForestLiana::ForestApiRequester).to have_received(:get).with('/liana/scopes', query: { 'renderingId' => rendering_id })
172
+ end
173
+ end
174
+
175
+ describe 'when asking for filters as string' do
176
+ let(:scope) { described_class.get_scope_for_user(user, collection_name, as_string: true) }
177
+ let(:expected_filters) { "{\"aggregator\":\"and\",\"conditions\":[{\"field\":\"description\",\"operator\":\"contains\",\"value\":\"check\"}]}" }
178
+
179
+ it 'should fetch the relevant scope and return it as a string' do
180
+ expect(scope).to eq expected_filters
181
+ expect(ForestLiana::ForestApiRequester).to have_received(:get).once
182
+ expect(ForestLiana::ForestApiRequester).to have_received(:get).with('/liana/scopes', query: { 'renderingId' => rendering_id })
183
+ end
184
+ end
185
+ end
186
+
187
+ describe '#append_scope_for_user' do
188
+ let(:existing_filter) { "{\"aggregator\":\"and\",\"conditions\":[{\"field\":\"shipping_status\",\"operator\":\"equal\",\"value\":\"Shipped\"}]}" }
189
+ let(:first_collection_scope_filter_as_string) { "{\"aggregator\":\"and\",\"conditions\":[{\"field\":\"description\",\"operator\":\"contains\",\"value\":\"check\"}]}" }
190
+
191
+ describe 'when the target collection has NO scopes defined' do
192
+ let(:first_collection_scope) { { } }
193
+
194
+ describe 'when providing NO existing filters' do
195
+ let(:existing_filter) { nil }
196
+ let(:filters) { described_class.append_scope_for_user(existing_filter, user, collection_name) }
197
+
198
+ it 'should return nil' do
199
+ expect(filters).to eq nil
200
+ end
201
+ end
202
+
203
+ describe 'when providing existing filters' do
204
+ let(:filters) { described_class.append_scope_for_user(existing_filter, user, collection_name) }
205
+
206
+ it 'should return only the exisitng filters' do
207
+ expect(filters).to eq existing_filter
208
+ end
209
+ end
210
+ end
211
+
212
+ describe 'when the target collection has scopes defined' do
213
+ describe 'when providing NO existing filters' do
214
+ let(:existing_filter) { nil }
215
+ let(:filters) { described_class.append_scope_for_user(existing_filter, user, collection_name) }
216
+
217
+ it 'should return only the scope filters' do
218
+ expect(filters).to eq first_collection_scope_filter_as_string
219
+ end
220
+ end
221
+
222
+ describe 'when providing existing filters' do
223
+ let(:filters) { described_class.append_scope_for_user(existing_filter, user, collection_name) }
224
+
225
+ it 'should return the aggregation between the exisitng filters and the scope filters' do
226
+ expect(filters).to eq "{\"aggregator\":\"and\",\"conditions\":[#{existing_filter},#{first_collection_scope_filter_as_string}]}"
227
+ end
228
+ end
229
+ end
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,96 @@
1
+ module ForestLiana
2
+ describe ValueStatGetter do
3
+ let(:rendering_id) { 13 }
4
+ let(:user) { { 'id' => '1', 'rendering_id' => rendering_id } }
5
+
6
+ before(:each) do
7
+ ForestLiana::ScopeManager.invalidate_scope_cache(rendering_id)
8
+ allow(ForestLiana::ScopeManager).to receive(:fetch_scopes).and_return(scopes)
9
+
10
+ island = Island.create!(name: 'Númenor')
11
+ king = User.create!(title: :king, name: 'Aragorn')
12
+ villager = User.create!(title: :villager)
13
+ Tree.create!(name: 'Tree n1', age: 1, island: island, owner: king)
14
+ Tree.create!(name: 'Tree n2', age: 3, island: island, created_at: 3.day.ago, owner: villager)
15
+ Tree.create!(name: 'Tree n3', age: 4, island: island, owner: king, cutter: villager)
16
+ end
17
+
18
+ let(:params) {
19
+ {
20
+ type: "Value",
21
+ collection: collection,
22
+ timezone: "Europe/Paris",
23
+ aggregate: "Count",
24
+ filters: filters
25
+ }
26
+ }
27
+
28
+ subject { ValueStatGetter.new(model, params, user) }
29
+
30
+ describe 'with empty scopes' do
31
+ let(:scopes) { { } }
32
+
33
+ describe 'with a simple filter matching no entries' do
34
+ let(:model) { User }
35
+ let(:collection) { 'users' }
36
+ let(:filters) { { field: 'name', operator: 'in', value: ['Merry', 'Pippin'] }.to_json }
37
+
38
+ it 'should have a countCurrent of 0' do
39
+ subject.perform
40
+ expect(subject.record.value[:countCurrent]).to eq 0
41
+ end
42
+ end
43
+
44
+ describe 'with a filter on a belongs_to string field' do
45
+ let(:model) { Tree }
46
+ let(:collection) { 'trees' }
47
+ let(:filters) { { field: 'owner:name', operator: 'equal', value: 'Aragorn' }.to_json }
48
+
49
+ it 'should have a countCurrent of 2' do
50
+ subject.perform
51
+ expect(subject.record.value[:countCurrent]).to eq 2
52
+ end
53
+ end
54
+
55
+ describe 'with a filter on a belongs_to enum field' do
56
+ let(:model) { Tree }
57
+ let(:collection) { 'trees' }
58
+ let(:filters) { { field: 'owner:title', operator: 'equal', value: 'villager' }.to_json }
59
+
60
+ it 'should have a countCurrent of 1' do
61
+ subject.perform
62
+ expect(subject.record.value[:countCurrent]).to eq 1
63
+ end
64
+ end
65
+ end
66
+
67
+ describe 'with scopes' do
68
+ let(:scopes) {
69
+ {
70
+ 'User' => {
71
+ 'scope'=> {
72
+ 'filter'=> {
73
+ 'aggregator' => 'and',
74
+ 'conditions' => [
75
+ { 'field' => 'title', 'operator' => 'not_equal', 'value' => 'villager' }
76
+ ]
77
+ },
78
+ 'dynamicScopesValues' => { }
79
+ }
80
+ }
81
+ }
82
+ }
83
+
84
+ describe 'with a filter on a belongs_to enum field' do
85
+ let(:model) { User }
86
+ let(:collection) { 'users' }
87
+ let(:filters) { { field: 'title', operator: 'equal', value: 'villager' }.to_json }
88
+
89
+ it 'should have a countCurrent of 0' do
90
+ subject.perform
91
+ expect(subject.record.value[:countCurrent]).to eq 0
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forest_liana
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.0.beta.4
4
+ version: 7.0.0.beta.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sandro Munda
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-06 00:00:00.000000000 Z
11
+ date: 2021-07-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -218,6 +218,7 @@ files:
218
218
  - app/controllers/forest_liana/mixpanel_controller.rb
219
219
  - app/controllers/forest_liana/resources_controller.rb
220
220
  - app/controllers/forest_liana/router.rb
221
+ - app/controllers/forest_liana/scopes_controller.rb
221
222
  - app/controllers/forest_liana/smart_actions_controller.rb
222
223
  - app/controllers/forest_liana/stats_controller.rb
223
224
  - app/controllers/forest_liana/stripe_controller.rb
@@ -280,7 +281,7 @@ files:
280
281
  - app/services/forest_liana/resources_getter.rb
281
282
  - app/services/forest_liana/schema_adapter.rb
282
283
  - app/services/forest_liana/schema_utils.rb
283
- - app/services/forest_liana/scope_validator.rb
284
+ - app/services/forest_liana/scope_manager.rb
284
285
  - app/services/forest_liana/search_query_builder.rb
285
286
  - app/services/forest_liana/smart_action_field_validator.rb
286
287
  - app/services/forest_liana/stat_getter.rb
@@ -324,6 +325,7 @@ files:
324
325
  - spec/dummy/app/assets/stylesheets/application.css
325
326
  - spec/dummy/app/config/routes.rb
326
327
  - spec/dummy/app/controllers/application_controller.rb
328
+ - spec/dummy/app/controllers/forest/islands_controller.rb
327
329
  - spec/dummy/app/helpers/application_helper.rb
328
330
  - spec/dummy/app/models/island.rb
329
331
  - spec/dummy/app/models/location.rb
@@ -366,6 +368,7 @@ files:
366
368
  - spec/dummy/db/migrate/20210511141752_create_owners.rb
367
369
  - spec/dummy/db/migrate/20210526084712_create_products.rb
368
370
  - spec/dummy/db/schema.rb
371
+ - spec/dummy/lib/forest_liana/collections/island.rb
369
372
  - spec/dummy/lib/forest_liana/collections/location.rb
370
373
  - spec/dummy/lib/forest_liana/collections/user.rb
371
374
  - spec/helpers/forest_liana/query_helper_spec.rb
@@ -379,6 +382,7 @@ files:
379
382
  - spec/requests/stats_spec.rb
380
383
  - spec/services/forest_liana/apimap_sorter_spec.rb
381
384
  - spec/services/forest_liana/filters_parser_spec.rb
385
+ - spec/services/forest_liana/has_many_getter_spec.rb
382
386
  - spec/services/forest_liana/ip_whitelist_checker_spec.rb
383
387
  - spec/services/forest_liana/line_stat_getter_spec.rb
384
388
  - spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb
@@ -386,9 +390,13 @@ files:
386
390
  - spec/services/forest_liana/permissions_checker_live_queries_spec.rb
387
391
  - spec/services/forest_liana/permissions_formatter_spec.rb
388
392
  - spec/services/forest_liana/permissions_getter_spec.rb
393
+ - spec/services/forest_liana/pie_stat_getter_spec.rb
394
+ - spec/services/forest_liana/resource_updater_spec.rb
389
395
  - spec/services/forest_liana/resources_getter_spec.rb
390
396
  - spec/services/forest_liana/schema_adapter_spec.rb
397
+ - spec/services/forest_liana/scope_manager_spec.rb
391
398
  - spec/services/forest_liana/smart_action_field_validator_spec.rb
399
+ - spec/services/forest_liana/value_stat_getter_spec.rb
392
400
  - spec/spec_helper.rb
393
401
  - test/dummy/README.rdoc
394
402
  - test/dummy/Rakefile
@@ -474,13 +482,8 @@ files:
474
482
  - test/fixtures/tree.yml
475
483
  - test/forest_liana_test.rb
476
484
  - test/routing/route_test.rb
477
- - test/services/forest_liana/has_many_getter_test.rb
478
485
  - test/services/forest_liana/operator_date_interval_parser_test.rb
479
- - test/services/forest_liana/pie_stat_getter_test.rb
480
- - test/services/forest_liana/resource_updater_test.rb
481
486
  - test/services/forest_liana/schema_adapter_test.rb
482
- - test/services/forest_liana/scope_validator_test.rb
483
- - test/services/forest_liana/value_stat_getter_test.rb
484
487
  - test/test_helper.rb
485
488
  homepage: https://github.com/ForestAdmin/forest-rails
486
489
  licenses:
@@ -509,12 +512,7 @@ test_files:
509
512
  - test/routing/route_test.rb
510
513
  - test/forest_liana_test.rb
511
514
  - test/services/forest_liana/schema_adapter_test.rb
512
- - test/services/forest_liana/resource_updater_test.rb
513
- - test/services/forest_liana/scope_validator_test.rb
514
515
  - test/services/forest_liana/operator_date_interval_parser_test.rb
515
- - test/services/forest_liana/value_stat_getter_test.rb
516
- - test/services/forest_liana/has_many_getter_test.rb
517
- - test/services/forest_liana/pie_stat_getter_test.rb
518
516
  - test/fixtures/string_field.yml
519
517
  - test/fixtures/reference.yml
520
518
  - test/fixtures/has_one_field.yml
@@ -600,17 +598,22 @@ test_files:
600
598
  - test/test_helper.rb
601
599
  - spec/helpers/forest_liana/schema_helper_spec.rb
602
600
  - spec/helpers/forest_liana/query_helper_spec.rb
601
+ - spec/services/forest_liana/scope_manager_spec.rb
602
+ - spec/services/forest_liana/resource_updater_spec.rb
603
+ - spec/services/forest_liana/pie_stat_getter_spec.rb
603
604
  - spec/services/forest_liana/permissions_checker_live_queries_spec.rb
604
605
  - spec/services/forest_liana/ip_whitelist_checker_spec.rb
605
606
  - spec/services/forest_liana/line_stat_getter_spec.rb
606
607
  - spec/services/forest_liana/schema_adapter_spec.rb
607
608
  - spec/services/forest_liana/resources_getter_spec.rb
608
609
  - spec/services/forest_liana/smart_action_field_validator_spec.rb
610
+ - spec/services/forest_liana/has_many_getter_spec.rb
609
611
  - spec/services/forest_liana/apimap_sorter_spec.rb
610
612
  - spec/services/forest_liana/filters_parser_spec.rb
611
613
  - spec/services/forest_liana/permissions_checker_acl_enabled_spec.rb
612
614
  - spec/services/forest_liana/permissions_formatter_spec.rb
613
615
  - spec/services/forest_liana/permissions_getter_spec.rb
616
+ - spec/services/forest_liana/value_stat_getter_spec.rb
614
617
  - spec/services/forest_liana/permissions_checker_acl_disabled_spec.rb
615
618
  - spec/spec_helper.rb
616
619
  - spec/config/initializers/logger_spec.rb
@@ -652,6 +655,7 @@ test_files:
652
655
  - spec/dummy/config/initializers/forest_liana.rb
653
656
  - spec/dummy/config/routes.rb
654
657
  - spec/dummy/lib/forest_liana/collections/location.rb
658
+ - spec/dummy/lib/forest_liana/collections/island.rb
655
659
  - spec/dummy/lib/forest_liana/collections/user.rb
656
660
  - spec/dummy/app/models/location.rb
657
661
  - spec/dummy/app/models/island.rb
@@ -667,6 +671,7 @@ test_files:
667
671
  - spec/dummy/app/assets/stylesheets/application.css
668
672
  - spec/dummy/app/assets/config/manifest.js
669
673
  - spec/dummy/app/controllers/application_controller.rb
674
+ - spec/dummy/app/controllers/forest/islands_controller.rb
670
675
  - spec/dummy/bin/setup
671
676
  - spec/dummy/bin/bundle
672
677
  - spec/dummy/bin/rake