forest_liana 7.8.1 → 7.8.2
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.
- checksums.yaml +4 -4
- data/app/services/forest_liana/stat_getter.rb +9 -1
- data/app/services/forest_liana/value_stat_getter.rb +7 -6
- data/lib/forest_liana/version.rb +1 -1
- data/spec/services/forest_liana/line_stat_getter_spec.rb +13 -0
- data/spec/services/forest_liana/pie_stat_getter_spec.rb +90 -67
- data/spec/services/forest_liana/value_stat_getter_spec.rb +78 -55
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c535f5719b2f62c0ff1e2bde402a0c57b099f4120b5c6b3232d8ea0343c84eaf
|
|
4
|
+
data.tar.gz: b609b22af960f63d0b03e8a99597cf6d202da15414826d6dca1b836b7a672676
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 502270b809bf91474ce0bd977a767ee93325c70cfb7aa2ccc0b807ec54fb70a2c447e58eac44a9beca1b9bde7720e214c855f794834c9ec46eb871c60b259a7a
|
|
7
|
+
data.tar.gz: 581fe22c160e4f10a2ed8a866261b2362a31ffb03b5817433794d19f4c1a3a55878a9350e81b95088aeaf4f2b8d6c58a69ad4c1179b8252f6070afb077d52f85
|
|
@@ -6,7 +6,15 @@ module ForestLiana
|
|
|
6
6
|
@resource = resource
|
|
7
7
|
@params = params
|
|
8
8
|
@user = forest_user
|
|
9
|
-
|
|
9
|
+
|
|
10
|
+
validate_params
|
|
11
|
+
compute_includes
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def validate_params
|
|
15
|
+
if @params.key?(:aggregate) && !%w[count sum avg max min].include?(@params[:aggregate].downcase)
|
|
16
|
+
raise ForestLiana::Errors::HTTP422Error.new('Invalid aggregate function')
|
|
17
|
+
end
|
|
10
18
|
end
|
|
11
19
|
|
|
12
20
|
def get_resource
|
|
@@ -19,24 +19,25 @@ module ForestLiana
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
@record = Model::Stat.new(value: {
|
|
22
|
-
countCurrent:
|
|
23
|
-
countPrevious: previous_value ?
|
|
22
|
+
countCurrent: aggregate(resource),
|
|
23
|
+
countPrevious: previous_value ? aggregate(previous_value) : nil
|
|
24
24
|
})
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
private
|
|
28
28
|
|
|
29
|
-
def
|
|
30
|
-
|
|
29
|
+
def aggregate(value)
|
|
30
|
+
aggregator = @params[:aggregate].downcase
|
|
31
|
+
uniq = aggregator == 'count'
|
|
31
32
|
|
|
32
33
|
if Rails::VERSION::MAJOR >= 4
|
|
33
34
|
if uniq
|
|
34
35
|
# NOTICE: uniq is deprecated since Rails 5.0
|
|
35
36
|
value = Rails::VERSION::MAJOR >= 5 ? value.distinct : value.uniq
|
|
36
37
|
end
|
|
37
|
-
value.send(
|
|
38
|
+
value.send(aggregator, aggregate_field)
|
|
38
39
|
else
|
|
39
|
-
value.send(
|
|
40
|
+
value.send(aggregator, aggregate_field, distinct: uniq)
|
|
40
41
|
end
|
|
41
42
|
end
|
|
42
43
|
|
data/lib/forest_liana/version.rb
CHANGED
|
@@ -10,6 +10,19 @@ module ForestLiana
|
|
|
10
10
|
Owner.delete_all
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
describe 'with not allowed aggregator' do
|
|
14
|
+
it 'should raise an error' do
|
|
15
|
+
expect {
|
|
16
|
+
LineStatGetter.new(Owner, {
|
|
17
|
+
timezone: "Europe/Paris",
|
|
18
|
+
aggregate: "eval",
|
|
19
|
+
time_range: "Week",
|
|
20
|
+
group_by_date_field: "`ls`",
|
|
21
|
+
}, user)
|
|
22
|
+
}.to raise_error(ForestLiana::Errors::HTTP422Error, 'Invalid aggregate function')
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
13
26
|
describe 'Check client_timezone function' do
|
|
14
27
|
describe 'with a SQLite database' do
|
|
15
28
|
it 'should return false' do
|
|
@@ -23,90 +23,113 @@ module ForestLiana
|
|
|
23
23
|
}
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
{
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
describe 'with not allowed aggregator' do
|
|
27
|
+
let(:scopes) { { } }
|
|
28
|
+
let(:model) { Tree }
|
|
29
|
+
let(:collection) { 'trees' }
|
|
30
|
+
let(:params) {
|
|
31
|
+
{
|
|
32
|
+
type: 'Pie',
|
|
33
|
+
collection: collection,
|
|
34
|
+
timezone: 'Europe/Paris',
|
|
35
|
+
aggregate: 'eval',
|
|
36
|
+
group_by_field: '`ls`'
|
|
37
|
+
}
|
|
35
38
|
}
|
|
36
|
-
}
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
it 'should raise an error' do
|
|
41
|
+
expect {
|
|
42
|
+
PieStatGetter.new(model, params, user)
|
|
43
|
+
}.to raise_error(ForestLiana::Errors::HTTP422Error, 'Invalid aggregate function')
|
|
44
|
+
end
|
|
45
|
+
end
|
|
39
46
|
|
|
40
|
-
describe 'with
|
|
41
|
-
let(:
|
|
47
|
+
describe 'with valid aggregate function' do
|
|
48
|
+
let(:model) { Tree }
|
|
49
|
+
let(:collection) { 'trees' }
|
|
50
|
+
let(:params) {
|
|
51
|
+
{
|
|
52
|
+
type: 'Pie',
|
|
53
|
+
collection: collection,
|
|
54
|
+
timezone: 'Europe/Paris',
|
|
55
|
+
aggregate: 'Count',
|
|
56
|
+
group_by_field: group_by_field
|
|
57
|
+
}
|
|
58
|
+
}
|
|
42
59
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
subject { PieStatGetter.new(model, params, user) }
|
|
61
|
+
|
|
62
|
+
describe 'with empty scopes' do
|
|
63
|
+
let(:scopes) { { } }
|
|
64
|
+
|
|
65
|
+
describe 'with an aggregate on the name field' do
|
|
66
|
+
let(:group_by_field) { 'name' }
|
|
67
|
+
|
|
68
|
+
it 'should be as many categories as records count' do
|
|
69
|
+
subject.perform
|
|
70
|
+
expect(subject.record.value).to match_array([
|
|
71
|
+
{:key => "Old Tree n1", :value => 1},
|
|
72
|
+
{:key => "Old Tree n2", :value => 1},
|
|
73
|
+
{:key => "Old Tree n3", :value => 1},
|
|
74
|
+
{:key => "Old Tree n4", :value => 1},
|
|
75
|
+
{:key => "Young Tree n1", :value => 1},
|
|
76
|
+
{:key => "Young Tree n2", :value => 1},
|
|
77
|
+
{:key => "Young Tree n3", :value => 1},
|
|
78
|
+
{:key => "Young Tree n4", :value => 1},
|
|
79
|
+
{:key => "Young Tree n5", :value => 1}
|
|
80
|
+
])
|
|
81
|
+
end
|
|
59
82
|
end
|
|
60
|
-
end
|
|
61
83
|
|
|
62
|
-
|
|
63
|
-
|
|
84
|
+
describe 'with an aggregate on the age field' do
|
|
85
|
+
let(:group_by_field) { 'age' }
|
|
64
86
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
87
|
+
it 'should be as many categories as different ages among records' do
|
|
88
|
+
subject.perform
|
|
89
|
+
expect(subject.record.value).to eq [{ :key => 3, :value => 5}, { :key => 15, :value => 4 }]
|
|
90
|
+
end
|
|
68
91
|
end
|
|
69
92
|
end
|
|
70
|
-
end
|
|
71
93
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
94
|
+
describe 'with scopes' do
|
|
95
|
+
let(:scopes) {
|
|
96
|
+
{
|
|
97
|
+
'Tree' => {
|
|
98
|
+
'scope'=> {
|
|
99
|
+
'filter'=> {
|
|
100
|
+
'aggregator' => 'and',
|
|
101
|
+
'conditions' => [
|
|
102
|
+
{ 'field' => 'age', 'operator' => 'less_than', 'value' => 10 }
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
'dynamicScopesValues' => { }
|
|
106
|
+
}
|
|
84
107
|
}
|
|
85
108
|
}
|
|
86
109
|
}
|
|
87
|
-
}
|
|
88
110
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
111
|
+
describe 'with an aggregate on the name field' do
|
|
112
|
+
let(:group_by_field) { 'name' }
|
|
113
|
+
|
|
114
|
+
it 'should be as many categories as records inside the scope' do
|
|
115
|
+
subject.perform
|
|
116
|
+
expect(subject.record.value).to match_array([
|
|
117
|
+
{:key => "Young Tree n1", :value => 1},
|
|
118
|
+
{:key => "Young Tree n2", :value => 1},
|
|
119
|
+
{:key => "Young Tree n3", :value => 1},
|
|
120
|
+
{:key => "Young Tree n4", :value => 1},
|
|
121
|
+
{:key => "Young Tree n5", :value => 1}
|
|
122
|
+
])
|
|
123
|
+
end
|
|
101
124
|
end
|
|
102
|
-
end
|
|
103
125
|
|
|
104
|
-
|
|
105
|
-
|
|
126
|
+
describe 'with an aggregate on the age field' do
|
|
127
|
+
let(:group_by_field) { 'age' }
|
|
106
128
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
129
|
+
it 'should be only one category' do
|
|
130
|
+
subject.perform
|
|
131
|
+
expect(subject.record.value).to eq [{ :key => 3, :value => 5}]
|
|
132
|
+
end
|
|
110
133
|
end
|
|
111
134
|
end
|
|
112
135
|
end
|
|
@@ -15,80 +15,103 @@ module ForestLiana
|
|
|
15
15
|
Tree.create!(name: 'Tree n3', age: 4, island: island, owner: king, cutter: villager)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
{
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
describe 'with not allowed aggregator' do
|
|
19
|
+
let(:model) { User }
|
|
20
|
+
let(:collection) { 'users' }
|
|
21
|
+
let(:scopes) { { } }
|
|
22
|
+
let(:params) {
|
|
23
|
+
{
|
|
24
|
+
type: "Value",
|
|
25
|
+
collection: collection,
|
|
26
|
+
timezone: "Europe/Paris",
|
|
27
|
+
aggregate: "eval",
|
|
28
|
+
aggregate_field: "`ls`"
|
|
29
|
+
}
|
|
25
30
|
}
|
|
26
|
-
}
|
|
27
31
|
|
|
28
|
-
|
|
32
|
+
it 'should raise an error' do
|
|
33
|
+
expect {
|
|
34
|
+
ValueStatGetter.new(model, params, user)
|
|
35
|
+
}.to raise_error(ForestLiana::Errors::HTTP422Error, 'Invalid aggregate function')
|
|
36
|
+
end
|
|
37
|
+
end
|
|
29
38
|
|
|
30
|
-
describe 'with
|
|
31
|
-
let(:
|
|
39
|
+
describe 'with valid aggregate function' do
|
|
40
|
+
let(:params) {
|
|
41
|
+
{
|
|
42
|
+
type: "Value",
|
|
43
|
+
collection: collection,
|
|
44
|
+
timezone: "Europe/Paris",
|
|
45
|
+
aggregate: "Count",
|
|
46
|
+
filters: filters
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
subject { ValueStatGetter.new(model, params, user) }
|
|
32
51
|
|
|
33
|
-
describe 'with
|
|
34
|
-
let(:
|
|
35
|
-
let(:collection) { 'users' }
|
|
36
|
-
let(:filters) { { field: 'name', operator: 'in', value: ['Merry', 'Pippin'] }.to_json }
|
|
52
|
+
describe 'with empty scopes' do
|
|
53
|
+
let(:scopes) { { } }
|
|
37
54
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
55
|
+
describe 'with a simple filter matching no entries' do
|
|
56
|
+
let(:model) { User }
|
|
57
|
+
let(:collection) { 'users' }
|
|
58
|
+
let(:filters) { { field: 'name', operator: 'in', value: ['Merry', 'Pippin'] }.to_json }
|
|
59
|
+
|
|
60
|
+
it 'should have a countCurrent of 0' do
|
|
61
|
+
subject.perform
|
|
62
|
+
expect(subject.record.value[:countCurrent]).to eq 0
|
|
63
|
+
end
|
|
41
64
|
end
|
|
42
|
-
end
|
|
43
65
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
66
|
+
describe 'with a filter on a belongs_to string field' do
|
|
67
|
+
let(:model) { Tree }
|
|
68
|
+
let(:collection) { 'trees' }
|
|
69
|
+
let(:filters) { { field: 'owner:name', operator: 'equal', value: 'Aragorn' }.to_json }
|
|
48
70
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
71
|
+
it 'should have a countCurrent of 2' do
|
|
72
|
+
subject.perform
|
|
73
|
+
expect(subject.record.value[:countCurrent]).to eq 2
|
|
74
|
+
end
|
|
52
75
|
end
|
|
53
|
-
end
|
|
54
76
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
77
|
+
describe 'with a filter on a belongs_to enum field' do
|
|
78
|
+
let(:model) { Tree }
|
|
79
|
+
let(:collection) { 'trees' }
|
|
80
|
+
let(:filters) { { field: 'owner:title', operator: 'equal', value: 'villager' }.to_json }
|
|
59
81
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
82
|
+
it 'should have a countCurrent of 1' do
|
|
83
|
+
subject.perform
|
|
84
|
+
expect(subject.record.value[:countCurrent]).to eq 1
|
|
85
|
+
end
|
|
63
86
|
end
|
|
64
87
|
end
|
|
65
|
-
end
|
|
66
88
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
89
|
+
describe 'with scopes' do
|
|
90
|
+
let(:scopes) {
|
|
91
|
+
{
|
|
92
|
+
'User' => {
|
|
93
|
+
'scope'=> {
|
|
94
|
+
'filter'=> {
|
|
95
|
+
'aggregator' => 'and',
|
|
96
|
+
'conditions' => [
|
|
97
|
+
{ 'field' => 'title', 'operator' => 'not_equal', 'value' => 'villager' }
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
'dynamicScopesValues' => { }
|
|
101
|
+
}
|
|
79
102
|
}
|
|
80
103
|
}
|
|
81
104
|
}
|
|
82
|
-
}
|
|
83
105
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
106
|
+
describe 'with a filter on a belongs_to enum field' do
|
|
107
|
+
let(:model) { User }
|
|
108
|
+
let(:collection) { 'users' }
|
|
109
|
+
let(:filters) { { field: 'title', operator: 'equal', value: 'villager' }.to_json }
|
|
88
110
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
111
|
+
it 'should have a countCurrent of 0' do
|
|
112
|
+
subject.perform
|
|
113
|
+
expect(subject.record.value[:countCurrent]).to eq 0
|
|
114
|
+
end
|
|
92
115
|
end
|
|
93
116
|
end
|
|
94
117
|
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.8.
|
|
4
|
+
version: 7.8.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sandro Munda
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-
|
|
11
|
+
date: 2023-12-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|