forest_liana 9.1.10 → 9.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/app/services/forest_liana/ability/permission/smart_action_checker.rb +1 -1
  3. data/app/services/forest_liana/filters_parser.rb +1 -5
  4. data/app/services/forest_liana/leaderboard_stat_getter.rb +1 -1
  5. data/app/services/forest_liana/line_stat_getter.rb +1 -1
  6. data/app/services/forest_liana/pie_stat_getter.rb +1 -1
  7. data/app/services/forest_liana/scope_manager.rb +34 -58
  8. data/app/services/forest_liana/utils/context_variables.rb +41 -0
  9. data/app/services/forest_liana/utils/context_variables_injector.rb +53 -0
  10. data/app/services/forest_liana/value_stat_getter.rb +1 -1
  11. data/lib/forest_liana/version.rb +1 -1
  12. data/spec/requests/actions_controller_spec.rb +32 -4
  13. data/spec/requests/count_spec.rb +1 -1
  14. data/spec/requests/resources_spec.rb +6 -7
  15. data/spec/requests/stats_spec.rb +29 -28
  16. data/spec/services/forest_liana/filters_parser_spec.rb +35 -35
  17. data/spec/services/forest_liana/has_many_getter_spec.rb +13 -11
  18. data/spec/services/forest_liana/line_stat_getter_spec.rb +1 -1
  19. data/spec/services/forest_liana/pie_stat_getter_spec.rb +11 -11
  20. data/spec/services/forest_liana/resource_updater_spec.rb +25 -21
  21. data/spec/services/forest_liana/resources_getter_spec.rb +10 -10
  22. data/spec/services/forest_liana/scope_manager_spec.rb +243 -152
  23. data/spec/services/forest_liana/utils/context_variables_injector_spec.rb +107 -0
  24. data/spec/services/forest_liana/utils/context_variables_spec.rb +43 -0
  25. data/spec/services/forest_liana/value_stat_getter_spec.rb +11 -11
  26. metadata +12 -6
@@ -5,7 +5,7 @@ module ForestLiana
5
5
  let(:timezone) { 'Europe/Paris' }
6
6
  let(:resource) { Tree }
7
7
  let(:filters) { {} }
8
- let(:filter_parser) { described_class.new(filters.to_json, resource, timezone) }
8
+ let(:filter_parser) { described_class.new(filters, resource, timezone) }
9
9
  let(:simple_condition_1) { { 'field' => 'name', 'operator' => 'contains', 'value' => 'Tree' } }
10
10
  let(:simple_condition_2) { { 'field' => 'name', 'operator' => 'ends_with', 'value' => '3' } }
11
11
  let(:simple_condition_3) { { 'field' => 'age', 'operator' => 'greater_than', 'value' => 2 } }
@@ -34,91 +34,91 @@ module ForestLiana
34
34
  let(:parsed_filters) { filter_parser.apply_filters }
35
35
 
36
36
  context 'on valid filters' do
37
- context 'single condtions' do
37
+ context 'single conditions' do
38
38
  context 'not_equal' do
39
- let(:filters) { { field: 'age', operator: 'not_equal', value: 4 } }
39
+ let(:filters) { { 'field' => 'age', 'operator' => 'not_equal', 'value' => 4 } }
40
40
  it { expect(parsed_filters.count).to eq 2 }
41
41
  end
42
42
 
43
43
  context 'equal' do
44
- let(:filters) { { field: 'age', operator: 'equal', value: 4 } }
44
+ let(:filters) { { 'field' => 'age', 'operator' => 'equal', 'value' => 4 } }
45
45
  it { expect(parsed_filters.count).to eq 1 }
46
46
  end
47
47
 
48
48
  context 'greater_than' do
49
- let(:filters) { { field: 'age', operator: 'greater_than', value: 2 } }
49
+ let(:filters) { { 'field' => 'age', 'operator' => 'greater_than', 'value' => 2 } }
50
50
  it { expect(parsed_filters.count).to eq 2 }
51
51
  end
52
52
 
53
53
  context 'less_than' do
54
- let(:filters) { { field: 'age', operator: 'less_than', value: 2 } }
54
+ let(:filters) { { 'field' => 'age', 'operator' => 'less_than', 'value' => 2 } }
55
55
  it { expect(parsed_filters.count).to eq 1 }
56
56
  end
57
57
 
58
58
  context 'after' do
59
- let(:filters) { { field: 'created_at', operator: 'after', value: 1.day.ago } }
59
+ let(:filters) { { 'field' => 'created_at', 'operator' => 'after', 'value' => 1.day.ago } }
60
60
  it { expect(parsed_filters.count).to eq 2 }
61
61
  end
62
62
 
63
63
  context 'before' do
64
- let(:filters) { { field: 'created_at', operator: 'before', value: 1.day.ago } }
64
+ let(:filters) { { 'field' => 'created_at', 'operator' => 'before', 'value' => 1.day.ago } }
65
65
  it { expect(parsed_filters.count).to eq 1 }
66
66
  end
67
67
 
68
68
  context 'contains' do
69
- let(:filters) { { field: 'name', operator: 'contains', value: 'ree' } }
69
+ let(:filters) { { 'field' => 'name', 'operator' => 'contains', 'value' => 'ree' } }
70
70
  it { expect(parsed_filters.count).to eq 3 }
71
71
  end
72
72
 
73
73
  context 'not_contains' do
74
- let(:filters) { { field: 'name', operator: 'not_contains', value: ' ' } }
74
+ let(:filters) { { 'field' => 'name', 'operator' => 'not_contains', 'value' => ' ' } }
75
75
  it { expect(parsed_filters.count).to eq 0 }
76
76
  end
77
77
 
78
78
  context 'starts_with' do
79
- let(:filters) { { field: 'name', operator: 'starts_with', value: 'o' } }
79
+ let(:filters) { { 'field' => 'name', 'operator' => 'starts_with', 'value' => 'o' } }
80
80
  it { expect(parsed_filters.count).to eq 0 }
81
81
  end
82
82
 
83
83
  context 'ends_with' do
84
- let(:filters) { { field: 'name', operator: 'ends_with', value: '3' } }
84
+ let(:filters) { { 'field' => 'name', 'operator' => 'ends_with', 'value' => '3' } }
85
85
  it { expect(parsed_filters.count).to eq 1 }
86
86
  end
87
87
 
88
88
  context 'present' do
89
- let(:filters) { { field: 'cutter_id', operator: 'present', value: nil } }
89
+ let(:filters) { { 'field' => 'cutter_id', 'operator' => 'present', 'value' => nil } }
90
90
  it { expect(parsed_filters.count).to eq 1 }
91
91
  end
92
92
 
93
93
  context 'blank' do
94
- let(:filters) { { field: 'cutter_id', operator: 'blank', value: nil } }
94
+ let(:filters) { { 'field' => 'cutter_id', 'operator' => 'blank', 'value' => nil } }
95
95
  it { expect(parsed_filters.count).to eq 2 }
96
96
  end
97
97
  end
98
98
 
99
99
  context 'belongsTo conditions' do
100
100
  context 'not_equal' do
101
- let(:filters) { { field: 'cutter:title', operator: 'not_equal', value: 'king' } }
101
+ let(:filters) { { 'field' => 'cutter:title', 'operator' => 'not_equal', 'value' => 'king' } }
102
102
  it { expect(parsed_filters.count).to eq 1 }
103
103
  end
104
104
 
105
105
  context 'equal' do
106
- let(:filters) { { field: 'cutter:title', operator: 'equal', value: 'king' } }
106
+ let(:filters) { { 'field' => 'cutter:title', 'operator' => 'equal', 'value' => 'king' } }
107
107
  it { expect(parsed_filters.count).to eq 0 }
108
108
  end
109
109
 
110
110
  context 'contains' do
111
- let(:filters) { { field: 'owner:title', operator: 'contains', value: 'in' } }
111
+ let(:filters) { { 'field' => 'owner:title', 'operator' => 'contains', 'value' => 'in' } }
112
112
  it { expect(parsed_filters.count).to eq 3 }
113
113
  end
114
114
 
115
115
  context 'not_contains' do
116
- let(:filters) { { field: 'owner:title', operator: 'not_contains', value: 'g' } }
116
+ let(:filters) { { 'field' => 'owner:title', 'operator' => 'not_contains', 'value' => 'g' } }
117
117
  it { expect(parsed_filters.count).to eq 0 }
118
118
  end
119
119
 
120
120
  context 'starts_with' do
121
- let(:filters) { { field: 'cutter:title', operator: 'starts_with', value: 'v' } }
121
+ let(:filters) { { 'field' => 'cutter:title', 'operator' => 'starts_with', 'value' => 'v' } }
122
122
  it { expect(parsed_filters.count).to eq 1 }
123
123
  end
124
124
 
@@ -126,9 +126,9 @@ module ForestLiana
126
126
  context 'different fields' do
127
127
  let(:filters) {
128
128
  {
129
- aggregator: 'or', conditions: [
130
- { field: 'owner:name', operator: 'contains', value: 'E.' },
131
- { field: 'cutter:title', operator: 'starts_with', value: 'v' }
129
+ 'aggregator' => 'or', 'conditions' => [
130
+ { 'field' => 'owner:name', 'operator' => 'contains', 'value' => 'E.' },
131
+ { 'field' => 'cutter:title', 'operator' => 'starts_with', 'value' => 'v' }
132
132
  ]
133
133
  }
134
134
  }
@@ -138,9 +138,9 @@ module ForestLiana
138
138
  context 'same fields' do
139
139
  let(:filters) {
140
140
  {
141
- aggregator: 'and', conditions: [
142
- { field: 'owner:name', operator: 'contains', value: 'E.' },
143
- { field: 'owner:title', operator: 'starts_with', value: 'v' }
141
+ 'aggregator' => 'and', 'conditions' => [
142
+ { 'field' => 'owner:name', 'operator' => 'contains', 'value' => 'E.' },
143
+ { 'field' => 'owner:title', 'operator' => 'starts_with', 'value' => 'v' }
144
144
  ]
145
145
  }
146
146
  }
@@ -150,7 +150,7 @@ module ForestLiana
150
150
  end
151
151
 
152
152
  context 'and aggregator on simple conditions' do
153
- let(:filters) { { aggregator: 'and', conditions: [simple_condition_1, simple_condition_2] } }
153
+ let(:filters) { { 'aggregator' => 'and', 'conditions' => [simple_condition_1, simple_condition_2] } }
154
154
  it { expect(parsed_filters.count).to eq 1 }
155
155
  end
156
156
 
@@ -159,15 +159,15 @@ module ForestLiana
159
159
  context 'and aggregator on simple conditions' do
160
160
  let(:filters) {
161
161
  {
162
- aggregator: 'or',
163
- conditions: [
162
+ 'aggregator' => 'or',
163
+ 'conditions' => [
164
164
  {
165
- aggregator: 'and', conditions: [
166
- { aggregator: 'or', conditions: [date_condition_1, simple_condition_1] },
165
+ 'aggregator' => 'and', 'conditions' => [
166
+ { 'aggregator' => 'or', 'conditions' => [date_condition_1, simple_condition_1] },
167
167
  simple_condition_2
168
168
  ]
169
169
  },
170
- { field: 'cutter:title', operator: 'starts_with', value: 'v' }
170
+ { 'field' => 'cutter:title', 'operator' => 'starts_with', 'value' => 'v' }
171
171
  ]
172
172
  }
173
173
  }
@@ -199,28 +199,28 @@ module ForestLiana
199
199
  end
200
200
 
201
201
  context 'raw value in conditions' do
202
- let(:filters) { { aggregator: 'and', conditions: [4] } }
202
+ let(:filters) { { 'aggregator' => 'and', 'conditions' => [4] } }
203
203
  it {
204
204
  expect { parsed_filters }.to raise_error(ForestLiana::Errors::HTTP422Error, 'Filters cannot be a raw value')
205
205
  }
206
206
  end
207
207
 
208
208
  context 'bad field type' do
209
- let(:filters) { { field: 4, operator: 'oss 117', value: 'tuorp' } }
209
+ let(:filters) { { 'field' => 4, 'operator' => 'oss 117', 'value' => 'tuorp' } }
210
210
  it {
211
211
  expect { parsed_filters }.to raise_error(ForestLiana::Errors::HTTP422Error, 'Invalid condition format')
212
212
  }
213
213
  end
214
214
 
215
215
  context 'bad operator type' do
216
- let(:filters) { { field: 'magnetic', operator: true, value: 'tuorp' } }
216
+ let(:filters) { { 'field' => 'magnetic', 'operator' => true, 'value' => 'tuorp' } }
217
217
  it {
218
218
  expect { parsed_filters }.to raise_error(ForestLiana::Errors::HTTP422Error, 'Invalid condition format')
219
219
  }
220
220
  end
221
221
 
222
222
  context 'unexisting field' do
223
- let(:filters) { { field: 'magnetic', operator: 'archer', value: 'tuorp' } }
223
+ let(:filters) { { 'field' => 'magnetic', 'operator' => 'archer', 'value' => 'tuorp' } }
224
224
  it {
225
225
  expect { parsed_filters }.to raise_error(ForestLiana::Errors::HTTP422Error, 'Field \'magnetic\' not found')
226
226
  }
@@ -3,7 +3,7 @@ module ForestLiana
3
3
  describe 'when retrieving has many relationship related records' do
4
4
  let(:rendering_id) { 13 }
5
5
  let(:user) { { 'id' => '1', 'rendering_id' => rendering_id } }
6
- let(:scopes) { { } }
6
+ let(:scopes) { {'scopes' => {}, 'team' => {'id' => '1', 'name' => 'Operations'}} }
7
7
  let(:association) { Island.reflect_on_association(:trees) }
8
8
  let(:params) {
9
9
  {
@@ -87,19 +87,21 @@ module ForestLiana
87
87
  end
88
88
 
89
89
  describe 'with scopes' do
90
- let(:scopes) { {
91
- 'Tree' => {
92
- 'scope'=> {
93
- 'filter'=> {
94
- 'aggregator' => 'and',
95
- 'conditions' => [
96
- { 'field' => 'name', 'operator' => 'contains', 'value' => 'a' }
97
- ]
90
+ let(:scopes) {
91
+ {
92
+ 'scopes' =>
93
+ {
94
+ 'Tree' => {
95
+ 'aggregator' => 'and',
96
+ 'conditions' => [{'field' => 'name', 'operator' => 'contains', 'value' => 'a'}]
97
+ }
98
98
  },
99
- 'dynamicScopesValues' => { }
99
+ 'team' => {
100
+ 'id' => 43,
101
+ 'name' => 'Operations'
100
102
  }
101
103
  }
102
- } }
104
+ }
103
105
 
104
106
  describe 'when asking for all trees related to madagascar' do
105
107
  it 'should return trees belonging to madagascar and matching the scopes' do
@@ -2,7 +2,7 @@ module ForestLiana
2
2
  describe LineStatGetter do
3
3
  let(:rendering_id) { 13 }
4
4
  let(:user) { { 'id' => '1', 'rendering_id' => rendering_id } }
5
- let(:scopes) { { } }
5
+ let(:scopes) { {'scopes' => {}, 'team' => {'id' => '1', 'name' => 'Operations'}} }
6
6
 
7
7
  before(:each) do
8
8
  ForestLiana::ScopeManager.invalidate_scope_cache(rendering_id)
@@ -24,7 +24,7 @@ module ForestLiana
24
24
  end
25
25
 
26
26
  describe 'with not allowed aggregator' do
27
- let(:scopes) { { } }
27
+ let(:scopes) { {'scopes' => {}, 'team' => {'id' => '1', 'name' => 'Operations'}} }
28
28
  let(:model) { Tree }
29
29
  let(:collection) { 'trees' }
30
30
  let(:params) {
@@ -60,7 +60,7 @@ module ForestLiana
60
60
  subject { PieStatGetter.new(model, params, user) }
61
61
 
62
62
  describe 'with empty scopes' do
63
- let(:scopes) { { } }
63
+ let(:scopes) { {'scopes' => {}, 'team' => {'id' => '1', 'name' => 'Operations'}} }
64
64
 
65
65
  describe 'with an aggregate on the name field' do
66
66
  let(:groupByFieldName) { 'name' }
@@ -94,16 +94,16 @@ module ForestLiana
94
94
  describe 'with scopes' do
95
95
  let(:scopes) {
96
96
  {
97
- 'Tree' => {
98
- 'scope'=> {
99
- 'filter'=> {
97
+ 'scopes' =>
98
+ {
99
+ 'Tree' => {
100
100
  'aggregator' => 'and',
101
- 'conditions' => [
102
- { 'field' => 'age', 'operator' => 'less_than', 'value' => 10 }
103
- ]
104
- },
105
- 'dynamicScopesValues' => { }
106
- }
101
+ 'conditions' => [{'field' => 'age', 'operator' => 'less_than', 'value' => 10}]
102
+ }
103
+ },
104
+ 'team' => {
105
+ 'id' => 43,
106
+ 'name' => 'Operations'
107
107
  }
108
108
  }
109
109
  }
@@ -13,7 +13,7 @@ module ForestLiana
13
13
  }
14
14
  let(:rendering_id) { 13 }
15
15
  let(:user) { { 'id' => '1', 'rendering_id' => rendering_id } }
16
- let(:scopes) { { } }
16
+ let(:scopes) { {'scopes' => {}, 'team' => {'id' => '1', 'name' => 'Operations'}} }
17
17
 
18
18
  subject {
19
19
  described_class.new(User, params, user)
@@ -66,19 +66,21 @@ module ForestLiana
66
66
 
67
67
  describe 'with scope excluding target record' do
68
68
  let(:attributes) { { name: 'Gandalf' } }
69
- let(:scopes) { {
70
- 'User' => {
71
- 'scope'=> {
72
- 'filter'=> {
73
- 'aggregator' => 'and',
74
- 'conditions' => [
75
- { 'field' => 'id', 'operator' => 'greater_than', 'value' => 2 }
76
- ]
69
+ let(:scopes) {
70
+ {
71
+ 'scopes' =>
72
+ {
73
+ 'User' => {
74
+ 'aggregator' => 'and',
75
+ 'conditions' => [{'field' => 'id', 'operator' => 'greater_than', 'value' => 2}]
76
+ }
77
77
  },
78
- 'dynamicScopesValues' => { }
78
+ 'team' => {
79
+ 'id' => 43,
80
+ 'name' => 'Operations'
79
81
  }
80
82
  }
81
- } }
83
+ }
82
84
 
83
85
  it 'should not update the record name' do
84
86
  subject.perform
@@ -90,19 +92,21 @@ module ForestLiana
90
92
 
91
93
  describe 'with scope including target record' do
92
94
  let(:attributes) { { name: 'Gandalf' } }
93
- let(:scopes) { {
94
- 'User' => {
95
- 'scope'=> {
96
- 'filter'=> {
97
- 'aggregator' => 'and',
98
- 'conditions' => [
99
- { 'field' => 'id', 'operator' => 'less_than', 'value' => 2 }
100
- ]
95
+ let(:scopes) {
96
+ {
97
+ 'scopes' =>
98
+ {
99
+ 'User' => {
100
+ 'aggregator' => 'and',
101
+ 'conditions' => [{'field' => 'id', 'operator' => 'less_than', 'value' => 2}]
102
+ }
101
103
  },
102
- 'dynamicScopesValues' => { }
104
+ 'team' => {
105
+ 'id' => 43,
106
+ 'name' => 'Operations'
103
107
  }
104
108
  }
105
- } }
109
+ }
106
110
 
107
111
  it 'should not update the record name' do
108
112
  subject.perform
@@ -6,7 +6,7 @@ module ForestLiana
6
6
  let(:sort) { 'id' }
7
7
  let(:fields) {}
8
8
  let(:filters) {}
9
- let(:scopes) { {} }
9
+ let(:scopes) { {'scopes' => {}, 'team' => {'id' => '1', 'name' => 'Operations'}} }
10
10
  let(:rendering_id) { 13 }
11
11
  let(:user) { { 'id' => '1', 'rendering_id' => rendering_id } }
12
12
 
@@ -480,16 +480,16 @@ module ForestLiana
480
480
  let(:filters) { }
481
481
  let(:scopes) {
482
482
  {
483
- 'Island' => {
484
- 'scope'=> {
485
- 'filter'=> {
483
+ 'scopes' =>
484
+ {
485
+ 'Island' => {
486
486
  'aggregator' => 'and',
487
- 'conditions' => [
488
- { 'field' => 'name', 'operator' => 'contains', 'value' => 'u' }
489
- ]
490
- },
491
- 'dynamicScopesValues' => { }
492
- }
487
+ 'conditions' => [{'field' => 'name', 'operator' => 'contains', 'value' => 'u'}]
488
+ }
489
+ },
490
+ 'team' => {
491
+ 'id' => 43,
492
+ 'name' => 'Operations'
493
493
  }
494
494
  }
495
495
  }