activecube 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +1 -3
- data/lib/activecube/common/metrics.rb +5 -1
- data/lib/activecube/definition_methods.rb +2 -1
- data/lib/activecube/field.rb +22 -3
- data/lib/activecube/processor/composer.rb +2 -1
- data/lib/activecube/query/cube_query.rb +5 -7
- data/lib/activecube/query/ordering.rb +2 -1
- data/lib/activecube/query/selector.rb +1 -1
- data/lib/activecube/query/slice.rb +51 -30
- data/lib/activecube/query_methods.rb +2 -3
- data/lib/activecube/version.rb +1 -1
- 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: ef6448e22d9122edb34207112002802381c6f807a60a73150add0dfba415eff2
|
4
|
+
data.tar.gz: f1db99febe43eb9943f96c344bbd77c2c3a42e6619225b9266980b6b2e3c486b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4ea5bf5ac7fc108a1868cdffc4b12a7c916d34b4f93bc9c094f930a405dd27e989e60287d39ebe2ed136add74de86bd0849dcd47122e54489e5a02ddb9276ca
|
7
|
+
data.tar.gz: d67e1cd6832b0c4bbc1ce2669ca145359b34e31ba5182392ff25d5b7e13b9bc639ae4822121821739b52bb7c0f2b829d06fb76c51cbd15b346db5f8a1488a26a
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -132,9 +132,7 @@ The methods used to contruct the query:
|
|
132
132
|
- **slice** defines which dimensions slices the results
|
133
133
|
- **measure** defines what to measure
|
134
134
|
- **when** defines which selectors to apply
|
135
|
-
- **desc, asc,
|
136
|
-
|
137
|
-
(take and skip have aliases: offset and limit).
|
135
|
+
- **desc, asc, offset, limit** are for ordering and limiting result set
|
138
136
|
|
139
137
|
After the query contructed, the following methods can be applied:
|
140
138
|
|
@@ -12,7 +12,7 @@ module Activecube::Common
|
|
12
12
|
end
|
13
13
|
else
|
14
14
|
define_method fname do |model, arel_table, measure, cube_query|
|
15
|
-
column = arel_table
|
15
|
+
column = pre_aggregate_value model, arel_table, measure, cube_query
|
16
16
|
measure.selectors.empty? ? column.send(fname) : column.send(fname.to_s+'If', measure.condition_query(model, arel_table, cube_query))
|
17
17
|
end
|
18
18
|
end
|
@@ -21,5 +21,9 @@ module Activecube::Common
|
|
21
21
|
end
|
22
22
|
|
23
23
|
|
24
|
+
def pre_aggregate_value _model, arel_table, _measure, _cube_query
|
25
|
+
arel_table[self.class.column_name.to_sym]
|
26
|
+
end
|
27
|
+
|
24
28
|
end
|
25
29
|
end
|
data/lib/activecube/field.rb
CHANGED
@@ -2,11 +2,30 @@ module Activecube
|
|
2
2
|
class Field
|
3
3
|
|
4
4
|
attr_reader :name, :definition
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
|
6
|
+
def self.build name, arg
|
7
|
+
if arg.kind_of? String
|
8
|
+
Field.new name, arg
|
9
|
+
elsif arg.kind_of? Hash
|
10
|
+
Field.new name, arg.symbolize_keys
|
11
|
+
elsif arg.kind_of?(Class) && arg < Field
|
12
|
+
arg.new name
|
13
|
+
else
|
14
|
+
raise ArgumentError, "Unexpected field #{name} definition with #{arg.class.name}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize name, arg = nil
|
19
|
+
@name = name
|
20
|
+
@definition = arg
|
8
21
|
end
|
9
22
|
|
23
|
+
def expression _model, _arel_table, _slice, _cube_query
|
24
|
+
raise ArgumentError, "String expression expected for #{name} field, instead #{definition.class.name} is found" unless definition.kind_of?(String)
|
25
|
+
definition
|
26
|
+
end
|
10
27
|
|
11
28
|
end
|
29
|
+
|
30
|
+
|
12
31
|
end
|
@@ -70,7 +70,8 @@ module Activecube::Processor
|
|
70
70
|
@models = []
|
71
71
|
measure_tables.group_by(&:table).each_pair do |table, list|
|
72
72
|
@models << table.model
|
73
|
-
|
73
|
+
reduce_options = measure_tables.count==1 ? cube_query.options : []
|
74
|
+
reduced = cube_query.reduced list.map(&:measure), reduce_options
|
74
75
|
table_query = table.query reduced
|
75
76
|
composed_query = composed_query ? table.join(cube_query, composed_query, table_query) : table_query
|
76
77
|
end
|
@@ -49,22 +49,20 @@ module Activecube::Query
|
|
49
49
|
self
|
50
50
|
end
|
51
51
|
|
52
|
-
def
|
52
|
+
def offset *args
|
53
53
|
args.each{|arg|
|
54
54
|
options << Limit.new( arg, :skip)
|
55
55
|
}
|
56
56
|
self
|
57
57
|
end
|
58
58
|
|
59
|
-
def
|
59
|
+
def limit *args
|
60
60
|
args.each{|arg|
|
61
61
|
options << Limit.new( arg, :take)
|
62
62
|
}
|
63
63
|
self
|
64
64
|
end
|
65
65
|
|
66
|
-
alias_method :limit, :take
|
67
|
-
alias_method :offset, :skip
|
68
66
|
|
69
67
|
def query
|
70
68
|
composer = Activecube::Processor::Composer.new(self)
|
@@ -88,7 +86,7 @@ module Activecube::Query
|
|
88
86
|
(measures.map(&:selectors) + selectors).flatten.map(&:required_column_names).flatten.uniq
|
89
87
|
end
|
90
88
|
|
91
|
-
def reduced other_measures
|
89
|
+
def reduced other_measures, other_options
|
92
90
|
|
93
91
|
common_selectors = []
|
94
92
|
other_measures.each_with_index do |m,i|
|
@@ -115,11 +113,11 @@ module Activecube::Query
|
|
115
113
|
|
116
114
|
return self if (reduced_measures == self.measures) && (reduced_selectors == self.selectors)
|
117
115
|
|
118
|
-
CubeQuery.new cube, slices, reduced_measures, reduced_selectors
|
116
|
+
CubeQuery.new cube, slices, reduced_measures, reduced_selectors, other_options
|
119
117
|
end
|
120
118
|
|
121
119
|
def join_fields
|
122
|
-
slices.map{|s| s.
|
120
|
+
slices.map{|s| s.dimension.class.identity || s.key }.uniq
|
123
121
|
end
|
124
122
|
|
125
123
|
def orderings
|
@@ -9,7 +9,8 @@ module Activecube
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def append_query _model, _cube_query, _table, query
|
12
|
-
|
12
|
+
text = argument.to_s.split(',').map{|s| "`#{s}`"}.join(',')
|
13
|
+
query.order(::Arel.sql(text).send(direction))
|
13
14
|
end
|
14
15
|
|
15
16
|
end
|
@@ -44,7 +44,7 @@ module Activecube::Query
|
|
44
44
|
define_method(method) do |*args|
|
45
45
|
raise ArgumentError, "Selector for #{method} already set" if operator
|
46
46
|
if ARRAY_OPERATORS.include? method
|
47
|
-
@operator = Operator.new(method, args)
|
47
|
+
@operator = Operator.new(method, args.flatten)
|
48
48
|
elsif method=='between'
|
49
49
|
if args.kind_of?(Range)
|
50
50
|
@operator = Operator.new(method, args)
|
@@ -1,36 +1,59 @@
|
|
1
1
|
module Activecube::Query
|
2
2
|
class Slice < Item
|
3
3
|
|
4
|
-
attr_reader :
|
5
|
-
def initialize cube, key,
|
6
|
-
super cube, key,
|
7
|
-
@
|
8
|
-
@
|
9
|
-
|
4
|
+
attr_reader :dimension, :parent
|
5
|
+
def initialize cube, key, definition, parent = nil
|
6
|
+
super cube, key, definition
|
7
|
+
@dimension = parent ? parent.dimension : definition
|
8
|
+
@parent = parent
|
9
|
+
|
10
|
+
if parent
|
11
|
+
raise "Unexpected class #{definition.class.name}" unless definition.kind_of?(Activecube::Field)
|
12
|
+
field_methods! if definition.class < Activecube::Field
|
13
|
+
end
|
14
|
+
|
10
15
|
end
|
11
16
|
|
12
|
-
def
|
13
|
-
|
14
|
-
raise "Field #{key} is not defined for #{definition.name}"
|
15
|
-
end
|
16
|
-
Slice.new cube, key, definition, field
|
17
|
+
def required_column_names
|
18
|
+
dimension.class.column_names || []
|
17
19
|
end
|
18
20
|
|
19
|
-
def
|
20
|
-
|
21
|
+
def [] arg
|
22
|
+
|
23
|
+
key = arg.to_sym
|
24
|
+
|
25
|
+
child = if definition.kind_of? Activecube::Dimension
|
26
|
+
definition.class.fields[key]
|
27
|
+
elsif definition.kind_of?(Activecube::Field) && (hash = definition.definition).kind_of?(Hash)
|
28
|
+
hash[key]
|
29
|
+
end
|
30
|
+
|
31
|
+
raise "Field #{key} is not defined for #{definition}" unless child
|
32
|
+
|
33
|
+
if child.kind_of?(Class) && child <= Activecube::Field
|
34
|
+
child = child.new key
|
35
|
+
elsif !child.kind_of?(Activecube::Field)
|
36
|
+
child = Activecube::Field.new(key, child)
|
37
|
+
end
|
38
|
+
|
39
|
+
Slice.new cube, key, child, self
|
40
|
+
|
21
41
|
end
|
22
42
|
|
23
|
-
def
|
24
|
-
|
43
|
+
def alias! new_key
|
44
|
+
self.class.new cube, new_key, definition, parent
|
25
45
|
end
|
26
46
|
|
27
|
-
def append_query
|
47
|
+
def append_query model, cube_query, table, query
|
28
48
|
|
29
49
|
attr_alias = "`#{key.to_s}`"
|
30
|
-
expr =
|
50
|
+
expr = parent ?
|
51
|
+
Arel.sql(definition.expression( model, table, self, cube_query) ) :
|
52
|
+
table[dimension.class.column_name]
|
53
|
+
|
31
54
|
query = query.project(expr.as(attr_alias))
|
32
55
|
|
33
|
-
if identity =
|
56
|
+
if identity = dimension.class.identity
|
34
57
|
query = query.project(table[identity]).group(table[identity])
|
35
58
|
else
|
36
59
|
query = query.group(attr_alias)
|
@@ -44,23 +67,21 @@ module Activecube::Query
|
|
44
67
|
end
|
45
68
|
|
46
69
|
def to_s
|
47
|
-
"Dimension #{super}"
|
70
|
+
parent ? "Dimension #{dimension}[#{super}]" : "Dimension #{super}"
|
48
71
|
end
|
49
|
-
|
50
|
-
|
51
|
-
private
|
52
|
-
|
72
|
+
|
53
73
|
def field_methods!
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
74
|
+
excluded = [:expression] + self.class.instance_methods(false)
|
75
|
+
definition.class.instance_methods(false).each do |name|
|
76
|
+
unless excluded.include?(name)
|
77
|
+
define_singleton_method name do |*args|
|
78
|
+
definition.send name, *args
|
79
|
+
self
|
80
|
+
end
|
61
81
|
end
|
62
82
|
end
|
63
83
|
end
|
84
|
+
|
64
85
|
|
65
86
|
end
|
66
87
|
end
|
@@ -5,7 +5,7 @@ module Activecube
|
|
5
5
|
|
6
6
|
attr_reader :database, :role
|
7
7
|
|
8
|
-
[:slice, :measure, :when, :
|
8
|
+
[:slice, :measure, :when, :desc, :asc, :limit, :offset].each do |method|
|
9
9
|
define_method(method) do |*args|
|
10
10
|
Query::CubeQuery.new(self).send method, *args
|
11
11
|
end
|
@@ -25,10 +25,9 @@ module Activecube
|
|
25
25
|
|
26
26
|
def super_model
|
27
27
|
raise ArgumentError, "No tables specified for cube #{name}" if tables.count==0
|
28
|
-
return tables.first.model if tables.count==1
|
29
28
|
|
30
29
|
tables.collect{ |t|
|
31
|
-
t.model.ancestors.select{|c| c
|
30
|
+
t.model.ancestors.select{|c| c < ActiveRecord::Base }
|
32
31
|
}.transpose.select{|c|
|
33
32
|
c.uniq.count==1
|
34
33
|
}.last.first
|
data/lib/activecube/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activecube
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aleksey Studnev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-02-
|
11
|
+
date: 2020-02-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|