mochigome 0.1.7 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/mochigome_ver.rb +1 -1
- data/lib/model_extensions.rb +19 -2
- data/lib/model_graph.rb +12 -0
- data/test/app_root/app/models/widget.rb +7 -0
- data/test/app_root/app/models/widget_divisor.rb +12 -0
- data/test/app_root/db/migrate/20110817163830_create_tables.rb +8 -0
- data/test/unit/query_test.rb +43 -0
- metadata +6 -4
data/lib/mochigome_ver.rb
CHANGED
data/lib/model_extensions.rb
CHANGED
@@ -75,7 +75,7 @@ module Mochigome
|
|
75
75
|
end
|
76
76
|
|
77
77
|
if assoc.options[:as]
|
78
|
-
# FIXME Can we assume that this is the polymorphic type field?
|
78
|
+
# FIXME Can we really assume that this is the polymorphic type field?
|
79
79
|
cond = cond.and(ftable["#{assoc.options[:as]}_type"].eq(model.name))
|
80
80
|
end
|
81
81
|
|
@@ -156,6 +156,7 @@ module Mochigome
|
|
156
156
|
@options = {}
|
157
157
|
@options[:fields] = []
|
158
158
|
@options[:custom_subgroup_exprs] = {}
|
159
|
+
@options[:custom_assocs] = {}
|
159
160
|
end
|
160
161
|
|
161
162
|
def type_name(n)
|
@@ -200,6 +201,10 @@ module Mochigome
|
|
200
201
|
def custom_subgroup_expression(name, expr)
|
201
202
|
@options[:custom_subgroup_exprs][name] = expr
|
202
203
|
end
|
204
|
+
|
205
|
+
def custom_association(tgt_cls, expr)
|
206
|
+
@options[:custom_assocs][tgt_cls] = expr
|
207
|
+
end
|
203
208
|
end
|
204
209
|
|
205
210
|
class AggregationSettings
|
@@ -284,6 +289,12 @@ module Mochigome
|
|
284
289
|
:sum => lambda{|a| a.sum}
|
285
290
|
}
|
286
291
|
|
292
|
+
AGG_FUNC_DEFAULTS = {
|
293
|
+
:count => 0,
|
294
|
+
:distinct => 0,
|
295
|
+
:sum => 0
|
296
|
+
}
|
297
|
+
|
287
298
|
# Given an object, tries to coerce it into a proc that takes a node
|
288
299
|
# and returns an expression node to collect some aggregate data from it.
|
289
300
|
def self.aggregation_proc(obj)
|
@@ -330,9 +341,15 @@ module Mochigome
|
|
330
341
|
raise ModelSetupError.new "Wrong # of components for agg: #{obj.inspect}"
|
331
342
|
end
|
332
343
|
|
333
|
-
{
|
344
|
+
r = {
|
334
345
|
:agg_proc => aggregation_proc(vals[0]),
|
335
346
|
:value_proc => value_proc(vals[1])
|
336
347
|
}.merge(vals[2] || {})
|
348
|
+
|
349
|
+
if AGG_FUNC_DEFAULTS.has_key?(vals[0])
|
350
|
+
r[:default] = AGG_FUNC_DEFAULTS[vals[0]]
|
351
|
+
end
|
352
|
+
|
353
|
+
r
|
337
354
|
end
|
338
355
|
end
|
data/lib/model_graph.rb
CHANGED
@@ -114,6 +114,18 @@ module Mochigome
|
|
114
114
|
@assoc_graph.add_edge(*edge)
|
115
115
|
@edge_conditions[edge] = model.assoc_condition(name)
|
116
116
|
end
|
117
|
+
|
118
|
+
if model.acts_as_mochigome_focus?
|
119
|
+
model.mochigome_focus_settings.options[:custom_assocs].each do |t,e|
|
120
|
+
cond = e.call(model.arel_table, t.arel_table)
|
121
|
+
[[model, t], [t, model]]. each do |edge|
|
122
|
+
@assoc_graph.add_edge(*edge)
|
123
|
+
# This deliberately allows custom assocs to overwrite normal ones
|
124
|
+
@edge_conditions[edge] = cond
|
125
|
+
end
|
126
|
+
added_models << t unless added_models.include?(t)
|
127
|
+
end
|
128
|
+
end
|
117
129
|
end
|
118
130
|
|
119
131
|
added_models.each do |model|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class WidgetDivisor < ActiveRecord::Base
|
2
|
+
acts_as_mochigome_focus do |f|
|
3
|
+
f.name lambda {|r| "Divisor #{r.divisor}"}
|
4
|
+
f.custom_association Widget, lambda {|src_tbl,tgt_tbl|
|
5
|
+
# Argh, arel doesn't provide easy access to the modulus operator
|
6
|
+
((tgt_tbl[:number]/src_tbl[:divisor])*src_tbl[:divisor]).
|
7
|
+
eq(tgt_tbl[:number])
|
8
|
+
}
|
9
|
+
end
|
10
|
+
|
11
|
+
validates_presence_of :divisor
|
12
|
+
end
|
@@ -51,6 +51,14 @@ class CreateTables < ActiveRecord::Migration
|
|
51
51
|
t.string :foo
|
52
52
|
t.string :bar
|
53
53
|
end
|
54
|
+
|
55
|
+
# These models are for testing custom associations
|
56
|
+
create_table :widgets do |t|
|
57
|
+
t.integer :number
|
58
|
+
end
|
59
|
+
create_table :widget_divisors do |t|
|
60
|
+
t.integer :divisor
|
61
|
+
end
|
54
62
|
end
|
55
63
|
|
56
64
|
def self.down
|
data/test/unit/query_test.rb
CHANGED
@@ -38,6 +38,14 @@ describe Mochigome::Query do
|
|
38
38
|
].each do |sp, n|
|
39
39
|
n.times{create(:sale, :store_product => sp)}
|
40
40
|
end
|
41
|
+
|
42
|
+
(1..5).each do |div_num|
|
43
|
+
WidgetDivisor.create(:divisor => div_num)
|
44
|
+
end
|
45
|
+
|
46
|
+
(1..25).each do |num|
|
47
|
+
Widget.create(:number => num)
|
48
|
+
end
|
41
49
|
end
|
42
50
|
|
43
51
|
after do
|
@@ -47,6 +55,8 @@ describe Mochigome::Query do
|
|
47
55
|
Store.delete_all
|
48
56
|
StoreProduct.delete_all
|
49
57
|
Sale.delete_all
|
58
|
+
WidgetDivisor.delete_all
|
59
|
+
Widget.delete_all
|
50
60
|
end
|
51
61
|
|
52
62
|
# Convenience functions to check DataNode output validity
|
@@ -544,4 +554,37 @@ describe Mochigome::Query do
|
|
544
554
|
assert_equal 0, (dn/0)['Gross']
|
545
555
|
assert_equal 0, (dn/0/0)['Gross']
|
546
556
|
end
|
557
|
+
|
558
|
+
it "assumes 0 as a default value for appropriate simple aggregations" do
|
559
|
+
Sale.destroy_all
|
560
|
+
q = Mochigome::Query.new(
|
561
|
+
[Store, Product],
|
562
|
+
:aggregate_sources => [[Product, Sale]]
|
563
|
+
)
|
564
|
+
dn = q.run
|
565
|
+
assert_equal 3, dn.children.size
|
566
|
+
assert_equal 0, dn['Sales count']
|
567
|
+
assert_equal 0, (dn/0)['Sales count']
|
568
|
+
assert_equal 0, (dn/0/0)['Sales count']
|
569
|
+
end
|
570
|
+
|
571
|
+
it "can use custom associations to link records" do
|
572
|
+
q = Mochigome::Query.new([WidgetDivisor, Widget])
|
573
|
+
dn = q.run
|
574
|
+
assert_equal "Divisor 1", (dn/0).name
|
575
|
+
assert_equal 25, (dn/0).children.size
|
576
|
+
assert_equal "Divisor 2", (dn/1).name
|
577
|
+
assert_equal 12, (dn/1).children.size
|
578
|
+
assert_equal "Divisor 5", (dn/4).name
|
579
|
+
assert_equal 5, (dn/4).children.size
|
580
|
+
end
|
581
|
+
|
582
|
+
it "can follow custom associations in reverse" do
|
583
|
+
q = Mochigome::Query.new([Widget, WidgetDivisor])
|
584
|
+
dn = q.run
|
585
|
+
assert_equal "Widget 1", (dn/0).name
|
586
|
+
assert_equal 1, (dn/0).children.size
|
587
|
+
assert_equal "Widget 6", (dn/5).name
|
588
|
+
assert_equal 3, (dn/5).children.size
|
589
|
+
end
|
547
590
|
end
|
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: 11
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 8
|
10
|
+
version: 0.1.8
|
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-05-
|
18
|
+
date: 2012-05-07 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
@@ -124,6 +124,8 @@ files:
|
|
124
124
|
- test/app_root/app/models/sale.rb
|
125
125
|
- test/app_root/app/models/store.rb
|
126
126
|
- test/app_root/app/models/store_product.rb
|
127
|
+
- test/app_root/app/models/widget.rb
|
128
|
+
- test/app_root/app/models/widget_divisor.rb
|
127
129
|
- test/app_root/app/transforms/report.fo.via-html.xslt.haml
|
128
130
|
- test/app_root/app/transforms/report.html.xslt.haml
|
129
131
|
- test/app_root/app/views/layouts/application.html.haml
|