mochigome 0.1.13 → 0.1.14
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 +1 -0
- data/lib/mochigome_ver.rb +1 -1
- data/lib/model_extensions.rb +25 -0
- data/lib/subgroup_model.rb +10 -4
- data/test/app_root/config/database-my.yml +1 -0
- data/test/app_root/db/migrate/20110817163830_create_tables.rb +1 -0
- data/test/factories.rb +1 -0
- data/test/unit/query_test.rb +18 -5
- metadata +14 -14
data/TODO
CHANGED
@@ -6,3 +6,4 @@
|
|
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
8
|
- Treat through-associations as hints for preferred paths
|
9
|
+
- Better handling of nil in subgroup fields
|
data/lib/mochigome_ver.rb
CHANGED
data/lib/model_extensions.rb
CHANGED
@@ -96,6 +96,9 @@ module Mochigome
|
|
96
96
|
# for this kind of stuff and also put the standard aggregation functions
|
97
97
|
# in there?
|
98
98
|
|
99
|
+
# FIXME All this lambda{|t| stuff is just needlessly confusing for
|
100
|
+
# the little good that it accomplishes.
|
101
|
+
|
99
102
|
def self.null_unless(pred, value_func)
|
100
103
|
case_expr(
|
101
104
|
lambda {|t| pred.call(value_func.call(t))},
|
@@ -114,6 +117,28 @@ module Mochigome
|
|
114
117
|
}
|
115
118
|
end
|
116
119
|
|
120
|
+
def self.multi_case_expr(cond_results, else_val = nil)
|
121
|
+
lambda {|t|
|
122
|
+
Arel::Nodes::SqlLiteral.new(
|
123
|
+
"(CASE " +
|
124
|
+
cond_results.map{|cond, result|
|
125
|
+
"WHEN #{arel_exprify(cond, t)} THEN #{arel_exprify(result, t)}"
|
126
|
+
} +
|
127
|
+
(else_val ? "ELSE #{arel_exprify(else_val, t)}" : "") +
|
128
|
+
"END)"
|
129
|
+
)
|
130
|
+
}
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.sql_bool_to_string(attr, prefix = "")
|
134
|
+
case_expr(
|
135
|
+
Arel::Nodes::NamedFunction.new('lower', [attr]).
|
136
|
+
in(["true", "t", 1, "1", "y", "yes"]),
|
137
|
+
"#{prefix}Yes",
|
138
|
+
"#{prefix}No"
|
139
|
+
)
|
140
|
+
end
|
141
|
+
|
117
142
|
private
|
118
143
|
|
119
144
|
def self.arel_exprify(e, t = nil)
|
data/lib/subgroup_model.rb
CHANGED
@@ -8,10 +8,15 @@ module Mochigome
|
|
8
8
|
def initialize(model, attr)
|
9
9
|
@model = model
|
10
10
|
@attr = attr
|
11
|
-
|
12
|
-
|
13
|
-
# @attr_expr will just be nil if there's no custom subgroup expr here
|
11
|
+
s = @model.mochigome_focus_settings
|
12
|
+
if s && s.options[:custom_subgroup_exprs][attr]
|
14
13
|
@attr_expr = s.options[:custom_subgroup_exprs][attr]
|
14
|
+
elsif @model.columns_hash[@attr.to_s].try(:type) == :boolean
|
15
|
+
@attr_expr = Mochigome::sql_bool_to_string(
|
16
|
+
model.arel_table[@attr], "#{human_name.titleize}: "
|
17
|
+
).call(model.arel_table)
|
18
|
+
else
|
19
|
+
@attr_expr = nil
|
15
20
|
end
|
16
21
|
@focus_settings = Mochigome::ReportFocusSettings.new(@model)
|
17
22
|
@focus_settings.type_name "#{@model.human_name} #{@attr.to_s.humanize}"
|
@@ -23,7 +28,8 @@ module Mochigome
|
|
23
28
|
end
|
24
29
|
|
25
30
|
def human_name
|
26
|
-
|
31
|
+
# Get rid of duplicate words (i.e. School$school_type)
|
32
|
+
"#{@model.human_name} #{@attr.to_s.humanize}".split.map(&:downcase).uniq.join(" ")
|
27
33
|
end
|
28
34
|
|
29
35
|
def real_model?
|
data/test/factories.rb
CHANGED
data/test/unit/query_test.rb
CHANGED
@@ -15,7 +15,8 @@ describe Mochigome::Query do
|
|
15
15
|
@john = create(:owner, :first_name => "John", :last_name => "Smith")
|
16
16
|
@store_x = create(:store, :name => "John's Store", :owner => @john)
|
17
17
|
|
18
|
-
@jane = create(:owner, :first_name => "Jane", :last_name => "Doe"
|
18
|
+
@jane = create(:owner, :first_name => "Jane", :last_name => "Doe",
|
19
|
+
:is_awesome => true)
|
19
20
|
@store_y = create(:store, :name => "Jane's Store (North)", :owner => @jane)
|
20
21
|
@store_z = create(:store, :name => "Jane's Store (South)", :owner => @jane)
|
21
22
|
|
@@ -180,6 +181,18 @@ describe Mochigome::Query do
|
|
180
181
|
assert_equal "Product A", (data_node/1/0/0/0).name
|
181
182
|
end
|
182
183
|
|
184
|
+
it "can subgroup layers by boolean attributes" do
|
185
|
+
q = Mochigome::Query.new(
|
186
|
+
[Mochigome::SubgroupModel.new(Owner, :is_awesome), Owner, Store, Product]
|
187
|
+
)
|
188
|
+
data_node = q.run
|
189
|
+
assert_equal "Owner Is Awesome: No", (data_node/0).name
|
190
|
+
assert_equal "John Smith", (data_node/0/0).name
|
191
|
+
assert_equal "John's Store", (data_node/0/0/0).name
|
192
|
+
assert_equal "Product A", (data_node/0/0/0/0).name
|
193
|
+
assert_equal "Owner Is Awesome: Yes", (data_node/1).name
|
194
|
+
end
|
195
|
+
|
183
196
|
it "can subgroup layers by attributes without including layer model" do
|
184
197
|
q = Mochigome::Query.new(
|
185
198
|
[Mochigome::SubgroupModel.new(Owner, :last_name)],
|
@@ -247,7 +260,7 @@ describe Mochigome::Query do
|
|
247
260
|
# Store X, Product C
|
248
261
|
assert_equal "Product C", (data_node/0/0/1).name
|
249
262
|
assert_equal 3, (data_node/0/0/1)['Sales count']
|
250
|
-
assert_equal (3*@product_c.price).to_s, (data_node/0/0/1)['Gross'].to_s
|
263
|
+
assert_equal (3*@product_c.price).to_f.to_s, (data_node/0/0/1)['Gross'].to_f.to_s
|
251
264
|
# Store Z, Product C
|
252
265
|
assert_equal "Product C", (data_node/1/1/0).name
|
253
266
|
assert_equal 2, (data_node/1/1/0)['Sales count']
|
@@ -259,7 +272,7 @@ describe Mochigome::Query do
|
|
259
272
|
# Store Z, Product C
|
260
273
|
assert_equal "Product C", (data_node/1/0/0).name
|
261
274
|
assert_equal 2, (data_node/1/0/0)['Sales count']
|
262
|
-
assert_equal (2*@product_c.price).to_s, (data_node/1/0/0)['Gross'].to_s
|
275
|
+
assert_equal (2*@product_c.price).to_f.to_s, (data_node/1/0/0)['Gross'].to_f.to_s
|
263
276
|
end
|
264
277
|
|
265
278
|
it "collects aggregate data in subgroups" do
|
@@ -369,8 +382,8 @@ describe Mochigome::Query do
|
|
369
382
|
data_node = q.run()
|
370
383
|
assert_equal "John's Store", (data_node/0/0).name
|
371
384
|
assert_equal 8, (data_node/0/0)['Sales count']
|
372
|
-
assert_equal (5*@product_a.price + 3*@product_c.price).to_s,
|
373
|
-
(data_node/0/0)['Gross'].to_s
|
385
|
+
assert_equal (5*@product_a.price + 3*@product_c.price).to_f.to_s,
|
386
|
+
(data_node/0/0)['Gross'].to_f.to_s
|
374
387
|
end
|
375
388
|
|
376
389
|
it "can do conditional counts" do
|
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: 7
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 14
|
10
|
+
version: 0.1.14
|
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-
|
18
|
+
date: 2012-06-03 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
@@ -28,10 +28,10 @@ dependencies:
|
|
28
28
|
- 2
|
29
29
|
- 1
|
30
30
|
version: "2.1"
|
31
|
-
requirement: *id001
|
32
|
-
prerelease: false
|
33
31
|
type: :runtime
|
32
|
+
requirement: *id001
|
34
33
|
name: arel
|
34
|
+
prerelease: false
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
version_requirements: &id002 !ruby/object:Gem::Requirement
|
37
37
|
none: false
|
@@ -42,10 +42,10 @@ dependencies:
|
|
42
42
|
segments:
|
43
43
|
- 0
|
44
44
|
version: "0"
|
45
|
-
requirement: *id002
|
46
|
-
prerelease: false
|
47
45
|
type: :runtime
|
46
|
+
requirement: *id002
|
48
47
|
name: ruport
|
48
|
+
prerelease: false
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
50
|
version_requirements: &id003 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
@@ -56,10 +56,10 @@ dependencies:
|
|
56
56
|
segments:
|
57
57
|
- 0
|
58
58
|
version: "0"
|
59
|
-
requirement: *id003
|
60
|
-
prerelease: false
|
61
59
|
type: :runtime
|
60
|
+
requirement: *id003
|
62
61
|
name: nokogiri
|
62
|
+
prerelease: false
|
63
63
|
- !ruby/object:Gem::Dependency
|
64
64
|
version_requirements: &id004 !ruby/object:Gem::Requirement
|
65
65
|
none: false
|
@@ -70,10 +70,10 @@ dependencies:
|
|
70
70
|
segments:
|
71
71
|
- 0
|
72
72
|
version: "0"
|
73
|
-
requirement: *id004
|
74
|
-
prerelease: false
|
75
73
|
type: :runtime
|
74
|
+
requirement: *id004
|
76
75
|
name: rgl
|
76
|
+
prerelease: false
|
77
77
|
- !ruby/object:Gem::Dependency
|
78
78
|
version_requirements: &id005 !ruby/object:Gem::Requirement
|
79
79
|
none: false
|
@@ -84,10 +84,10 @@ dependencies:
|
|
84
84
|
segments:
|
85
85
|
- 0
|
86
86
|
version: "0"
|
87
|
-
requirement: *id005
|
88
|
-
prerelease: false
|
89
87
|
type: :runtime
|
88
|
+
requirement: *id005
|
90
89
|
name: activerecord
|
90
|
+
prerelease: false
|
91
91
|
description: Report generator that graphs over ActiveRecord associations
|
92
92
|
email: david.mike.simon@gmail.com
|
93
93
|
executables: []
|