mochigome 0.1.14 → 0.1.15
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.
- data/TODO +2 -1
- data/lib/mochigome_ver.rb +1 -1
- data/lib/model_extensions.rb +12 -7
- data/lib/query.rb +48 -39
- data/test/app_root/app/models/product.rb +5 -0
- data/test/unit/query_test.rb +9 -0
- metadata +4 -4
data/TODO
CHANGED
@@ -5,5 +5,6 @@
|
|
5
5
|
- Named subsets of different fields and agg fields on a single model
|
6
6
|
- Some kind of single-page preview on the edit screen would be cool. Maybe use FOP with fake data and the PNG output option?
|
7
7
|
- Automatically set default to 0 on sum and count aggregation
|
8
|
-
- Treat through-associations as hints for preferred paths
|
9
8
|
- Better handling of nil in subgroup fields
|
9
|
+
- Handle has_and_belongs_to_many correctly
|
10
|
+
- Deal with ignore_assoc properly in both directions and when we see :through assocs
|
data/lib/mochigome_ver.rb
CHANGED
data/lib/model_extensions.rb
CHANGED
@@ -6,9 +6,9 @@ module Mochigome
|
|
6
6
|
base.write_inheritable_attribute :mochigome_focus_settings, nil
|
7
7
|
base.class_inheritable_reader :mochigome_focus_settings
|
8
8
|
|
9
|
-
#
|
10
|
-
base.write_inheritable_attribute :
|
11
|
-
base.class_inheritable_reader :
|
9
|
+
# FIXME: Unclear on how this interacts with inheritance...
|
10
|
+
base.write_inheritable_attribute :mochigome_aggregation_settings_sets, {}
|
11
|
+
base.class_inheritable_reader :mochigome_aggregation_settings_sets
|
12
12
|
end
|
13
13
|
|
14
14
|
module ClassMethods
|
@@ -45,13 +45,18 @@ module Mochigome
|
|
45
45
|
|
46
46
|
# TODO: Split out aggregation stuff into its own module
|
47
47
|
|
48
|
-
def has_mochigome_aggregations
|
49
|
-
|
50
|
-
|
48
|
+
def has_mochigome_aggregations(name = :default)
|
49
|
+
name = name.to_sym
|
50
|
+
if mochigome_aggregation_settings_sets[name].try(:model) == self
|
51
|
+
raise Mochigome::ModelSetupError.new("Can't overwrite aggregation settings for #{self.name}")
|
51
52
|
end
|
52
53
|
settings = AggregationSettings.new(self)
|
53
54
|
yield settings if block_given?
|
54
|
-
|
55
|
+
mochigome_aggregation_settings_sets[name] = settings
|
56
|
+
end
|
57
|
+
|
58
|
+
def mochigome_aggregation_settings(name = :default)
|
59
|
+
mochigome_aggregation_settings_sets[name]
|
55
60
|
end
|
56
61
|
|
57
62
|
def assoc_condition(name)
|
data/lib/query.rb
CHANGED
@@ -17,9 +17,14 @@ module Mochigome
|
|
17
17
|
|
18
18
|
@aggregate_rels = ActiveSupport::OrderedHash.new
|
19
19
|
aggregate_sources.each do |a|
|
20
|
-
focus_model, data_model =
|
21
|
-
|
22
|
-
|
20
|
+
focus_model, data_model, agg_setting_name = nil, nil, nil
|
21
|
+
if a.is_a?(Array) then
|
22
|
+
focus_model = a.select{|e| e.is_a?(Class)}.first
|
23
|
+
data_model = a.select{|e| e.is_a?(Class)}.last
|
24
|
+
agg_setting_name = a.select{|e| e.is_a?(Symbol)}.first || :default
|
25
|
+
else
|
26
|
+
focus_model = data_model = a
|
27
|
+
agg_setting_name = :default
|
23
28
|
end
|
24
29
|
|
25
30
|
agg_rel = Relation.new(@layer_types)
|
@@ -28,15 +33,21 @@ module Mochigome
|
|
28
33
|
|
29
34
|
key_cols = @ids_rel.spine_layers.map{|m| m.arel_primary_key}
|
30
35
|
|
31
|
-
agg_fields = data_model.
|
36
|
+
agg_fields = data_model.
|
37
|
+
mochigome_aggregation_settings(agg_setting_name).
|
32
38
|
options[:fields].reject{|a| a[:in_ruby]}
|
33
39
|
agg_fields.each_with_index do |a, i|
|
34
40
|
d_expr = a[:value_proc].call(data_model.arel_table)
|
35
41
|
agg_rel.select_expr(d_expr.as("d%03u" % i))
|
36
42
|
end
|
37
43
|
|
38
|
-
|
39
|
-
|
44
|
+
agg_rel_key = {
|
45
|
+
:focus_model => focus_model,
|
46
|
+
:data_model => data_model,
|
47
|
+
:agg_setting_name => agg_setting_name
|
48
|
+
}
|
49
|
+
|
50
|
+
@aggregate_rels[agg_rel_key] = (0..key_cols.length).map{|n|
|
40
51
|
lambda {|cond|
|
41
52
|
data_rel = agg_rel.clone
|
42
53
|
data_rel.apply_condition(cond)
|
@@ -134,55 +145,53 @@ module Mochigome
|
|
134
145
|
end
|
135
146
|
|
136
147
|
def load_aggregate_data(node, cond)
|
137
|
-
@aggregate_rels.each do |
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
c = (c[group_id] ||= {})
|
155
|
-
end
|
156
|
-
c[group_values.last] = data_values
|
148
|
+
@aggregate_rels.each do |key, rel_funcs|
|
149
|
+
data_model = key[:data_model]
|
150
|
+
agg_name = key[:agg_setting_name]
|
151
|
+
agg_settings = data_model.mochigome_aggregation_settings(agg_name)
|
152
|
+
|
153
|
+
rel_funcs.each do |rel_func|
|
154
|
+
q = rel_func.call(cond)
|
155
|
+
data_tree = {}
|
156
|
+
@layer_types.first.connection.select_all(q.to_sql).each do |row|
|
157
|
+
group_values = row.keys.select{|k| k.start_with?("g")}.sort.map{|k| row[k]}
|
158
|
+
data_values = row.keys.select{|k| k.start_with?("d")}.sort.map{|k| row[k]}
|
159
|
+
if group_values.empty?
|
160
|
+
data_tree = data_values
|
161
|
+
else
|
162
|
+
c = data_tree
|
163
|
+
group_values.take(group_values.size-1).each do |group_id|
|
164
|
+
c = (c[group_id] ||= {})
|
157
165
|
end
|
166
|
+
c[group_values.last] = data_values
|
158
167
|
end
|
159
|
-
insert_aggregate_data_fields(node, data_tree, data_model)
|
160
168
|
end
|
169
|
+
insert_aggregate_data_fields(node, data_tree, agg_settings)
|
161
170
|
end
|
162
171
|
end
|
163
172
|
end
|
164
173
|
|
165
|
-
def insert_aggregate_data_fields(node, table,
|
174
|
+
def insert_aggregate_data_fields(node, table, agg_settings)
|
166
175
|
if table.is_a? Array
|
167
|
-
fields =
|
176
|
+
fields = agg_settings.options[:fields]
|
168
177
|
# Pre-fill the node with all fields in the right order
|
169
|
-
fields.each{|
|
170
|
-
agg_row = {} # Hold regular
|
171
|
-
fields.reject{|
|
172
|
-
v ||=
|
173
|
-
agg_row[
|
174
|
-
node[
|
178
|
+
fields.each{|fld| node[fld[:name]] = fld[:default] unless fld[:hidden] }
|
179
|
+
agg_row = {} # Hold regular results here to be used in ruby-based fields
|
180
|
+
fields.reject{|fld| fld[:in_ruby]}.zip(table).each do |fld, v|
|
181
|
+
v ||= fld[:default]
|
182
|
+
agg_row[fld[:name]] = v
|
183
|
+
node[fld[:name]] = v unless fld[:hidden]
|
175
184
|
end
|
176
|
-
fields.select{|
|
177
|
-
node[
|
185
|
+
fields.select{|fld| fld[:in_ruby]}.each do |fld|
|
186
|
+
node[fld[:name]] = fld[:ruby_proc].call(agg_row)
|
178
187
|
end
|
179
188
|
node.children.each do |c|
|
180
|
-
insert_aggregate_data_fields(c, [],
|
189
|
+
insert_aggregate_data_fields(c, [], agg_settings)
|
181
190
|
end
|
182
191
|
else
|
183
192
|
node.children.each do |c|
|
184
193
|
subtable = table[c[:id]] || []
|
185
|
-
insert_aggregate_data_fields(c, subtable,
|
194
|
+
insert_aggregate_data_fields(c, subtable, agg_settings)
|
186
195
|
end
|
187
196
|
end
|
188
197
|
end
|
@@ -9,6 +9,7 @@ class Product < ActiveRecord::Base
|
|
9
9
|
"Consonant"
|
10
10
|
).call(Product.arel_table)
|
11
11
|
end
|
12
|
+
|
12
13
|
has_mochigome_aggregations do |a|
|
13
14
|
a.fields [
|
14
15
|
:sum_price,
|
@@ -24,6 +25,10 @@ class Product < ActiveRecord::Base
|
|
24
25
|
a.fields_in_ruby [ {"Count squared" => lambda{|row| row["Secret count"].try(:**, 2)}} ]
|
25
26
|
end
|
26
27
|
|
28
|
+
has_mochigome_aggregations(:averaging) do |a|
|
29
|
+
a.fields [:average_price]
|
30
|
+
end
|
31
|
+
|
27
32
|
belongs_to :category
|
28
33
|
has_many :store_products
|
29
34
|
has_many :stores, :through => :store_products
|
data/test/unit/query_test.rb
CHANGED
@@ -275,6 +275,15 @@ describe Mochigome::Query do
|
|
275
275
|
assert_equal (2*@product_c.price).to_f.to_s, (data_node/1/0/0)['Gross'].to_f.to_s
|
276
276
|
end
|
277
277
|
|
278
|
+
it "can use a named aggregate data setting" do
|
279
|
+
q = Mochigome::Query.new(
|
280
|
+
[Owner],
|
281
|
+
:aggregate_sources => [[Product, :averaging]]
|
282
|
+
)
|
283
|
+
data_node = q.run
|
284
|
+
assert_equal ((19.95*4 + 5)/5).to_f.to_s, data_node['Products average price'].to_f.to_s
|
285
|
+
end
|
286
|
+
|
278
287
|
it "collects aggregate data in subgroups" do
|
279
288
|
q = Mochigome::Query.new(
|
280
289
|
[Mochigome::SubgroupModel.new(Owner, :last_name), Owner, Store, Product],
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mochigome
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 5
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 15
|
10
|
+
version: 0.1.15
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- David Mike Simon
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-06-
|
18
|
+
date: 2012-06-04 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|