mochigome 0.1.7 → 0.1.8

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/lib/mochigome_ver.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mochigome
2
- VERSION = "0.1.7"
2
+ VERSION = "0.1.8"
3
3
  end
@@ -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,7 @@
1
+ class Widget < ActiveRecord::Base
2
+ acts_as_mochigome_focus do |f|
3
+ f.name lambda {|r| "Widget #{r.number}"}
4
+ end
5
+
6
+ validates_presence_of :number
7
+ end
@@ -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
@@ -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: 21
4
+ hash: 11
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 7
10
- version: 0.1.7
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-02 00:00:00 Z
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