mochigome 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/.autotest +14 -0
  2. data/Gemfile +16 -0
  3. data/Gemfile.lock +71 -0
  4. data/LICENSE +674 -0
  5. data/README.rdoc +11 -0
  6. data/Rakefile +74 -0
  7. data/TODO +6 -0
  8. data/lib/data_node.rb +106 -0
  9. data/lib/exceptions.rb +6 -0
  10. data/lib/mochigome.rb +7 -0
  11. data/lib/mochigome_ver.rb +3 -0
  12. data/lib/model_extensions.rb +211 -0
  13. data/lib/query.rb +199 -0
  14. data/test/app_root/app/controllers/application_controller.rb +2 -0
  15. data/test/app_root/app/controllers/owners_controller.rb +2 -0
  16. data/test/app_root/app/models/boring_datum.rb +3 -0
  17. data/test/app_root/app/models/category.rb +7 -0
  18. data/test/app_root/app/models/owner.rb +17 -0
  19. data/test/app_root/app/models/product.rb +21 -0
  20. data/test/app_root/app/models/sale.rb +9 -0
  21. data/test/app_root/app/models/store.rb +13 -0
  22. data/test/app_root/app/models/store_product.rb +11 -0
  23. data/test/app_root/config/boot.rb +130 -0
  24. data/test/app_root/config/database-pg.yml +8 -0
  25. data/test/app_root/config/database.yml +6 -0
  26. data/test/app_root/config/environment.rb +14 -0
  27. data/test/app_root/config/environments/test.rb +20 -0
  28. data/test/app_root/config/offroad.yml +6 -0
  29. data/test/app_root/config/preinitializer.rb +20 -0
  30. data/test/app_root/config/routes.rb +4 -0
  31. data/test/app_root/db/migrate/20110817163830_create_tables.rb +66 -0
  32. data/test/app_root/vendor/plugins/mochigome/init.rb +2 -0
  33. data/test/factories.rb +39 -0
  34. data/test/test.watchr +6 -0
  35. data/test/test_helper.rb +66 -0
  36. data/test/unit/data_node_test.rb +144 -0
  37. data/test/unit/model_extensions_test.rb +367 -0
  38. data/test/unit/query_test.rb +202 -0
  39. metadata +143 -0
@@ -0,0 +1,367 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ describe "an ActiveRecord model" do
4
+ before do
5
+ @model_class = Class.new(ActiveRecord::Base)
6
+ @model_class.class_eval do
7
+ set_table_name :fake
8
+ def name
9
+ "Moby"
10
+ end
11
+ def last_name
12
+ "Dick"
13
+ end
14
+ end
15
+ Whale = @model_class
16
+ end
17
+
18
+ after do
19
+ Object.send(:remove_const, :Whale)
20
+ end
21
+
22
+ it "indicates if it acts_as_mochigome_focus or not" do
23
+ refute @model_class.acts_as_mochigome_focus?
24
+ @model_class.class_eval do
25
+ acts_as_mochigome_focus
26
+ end
27
+ assert @model_class.acts_as_mochigome_focus?
28
+ end
29
+
30
+ it "cannot call acts_as_mochigome_focus more than once" do
31
+ @model_class.class_eval do
32
+ acts_as_mochigome_focus
33
+ end
34
+ assert_raises Mochigome::ModelSetupError do
35
+ @model_class.class_eval do
36
+ acts_as_mochigome_focus
37
+ end
38
+ end
39
+ end
40
+
41
+ it "inherits a parent's report focus settings" do
42
+ @model_class.class_eval do
43
+ acts_as_mochigome_focus do |f|
44
+ f.type_name "Foobar"
45
+ end
46
+ end
47
+ @sub_class = Class.new(@model_class)
48
+ i = @sub_class.new
49
+ assert_equal "Foobar", i.mochigome_focus.type_name
50
+ end
51
+
52
+ it "can override a parent's report focus settings" do
53
+ @model_class.class_eval do
54
+ acts_as_mochigome_focus do |f|
55
+ f.type_name "Foobar"
56
+ end
57
+ end
58
+ @sub_class = Class.new(@model_class)
59
+ @sub_class.class_eval do
60
+ acts_as_mochigome_focus do |f|
61
+ f.type_name "Narfbork"
62
+ end
63
+ end
64
+ i = @sub_class.new
65
+ assert_equal "Narfbork", i.mochigome_focus.type_name
66
+ end
67
+
68
+ it "uses its class name as the default type name" do
69
+ @model_class.class_eval do
70
+ acts_as_mochigome_focus
71
+ end
72
+ i = @model_class.new
73
+ assert_equal "Whale", i.mochigome_focus.type_name.split("::").last
74
+ end
75
+
76
+ it "can override the default type name" do
77
+ @model_class.class_eval do
78
+ acts_as_mochigome_focus do |f|
79
+ f.type_name "Thingie"
80
+ end
81
+ end
82
+ i = @model_class.new
83
+ assert_equal "Thingie", i.mochigome_focus.type_name
84
+ end
85
+
86
+ it "cannot specify a nonsense type name" do
87
+ assert_raises Mochigome::ModelSetupError do
88
+ @model_class.class_eval do
89
+ acts_as_mochigome_focus do |f|
90
+ f.type_name 12345
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ it "uses the attribute 'name' as the default focus name" do
97
+ @model_class.class_eval do
98
+ acts_as_mochigome_focus
99
+ end
100
+ i = @model_class.new
101
+ assert_equal "Moby", i.mochigome_focus.name
102
+ end
103
+
104
+ it "can override the focus name with another method_name" do
105
+ @model_class.class_eval do
106
+ acts_as_mochigome_focus do |f|
107
+ f.name :last_name
108
+ end
109
+ end
110
+ i = @model_class.new
111
+ assert_equal "Dick", i.mochigome_focus.name
112
+ end
113
+
114
+ it "can override the focus name with a custom implementation" do
115
+ @model_class.class_eval do
116
+ acts_as_mochigome_focus do |f|
117
+ f.name lambda {|obj| "#{obj.name} #{obj.last_name}"}
118
+ end
119
+ end
120
+ i = @model_class.new
121
+ assert_equal "Moby Dick", i.mochigome_focus.name
122
+ end
123
+
124
+ it "can specify fields" do
125
+ @model_class.class_eval do
126
+ acts_as_mochigome_focus do |f|
127
+ f.fields ["a", "b"]
128
+ end
129
+ end
130
+ i = @model_class.new(:a => "abc", :b => "xyz")
131
+ expected = ActiveSupport::OrderedHash.new
132
+ expected["a"] = "abc"
133
+ expected["b"] = "xyz"
134
+ assert_equal expected, i.mochigome_focus.field_data
135
+ end
136
+
137
+ it "has no report focus data if no fields are specified" do
138
+ @model_class.class_eval do
139
+ acts_as_mochigome_focus
140
+ end
141
+ i = @model_class.new(:a => "abc", :b => "xyz")
142
+ assert_empty i.mochigome_focus.field_data
143
+ end
144
+
145
+ it "can specify only some of its fields" do
146
+ @model_class.class_eval do
147
+ acts_as_mochigome_focus do |f|
148
+ f.fields ["b"]
149
+ end
150
+ end
151
+ i = @model_class.new(:a => "abc", :b => "xyz")
152
+ expected = ActiveSupport::OrderedHash.new
153
+ expected["b"] = "xyz"
154
+ assert_equal expected, i.mochigome_focus.field_data
155
+ end
156
+
157
+ it "can specify fields in a custom order" do
158
+ @model_class.class_eval do
159
+ acts_as_mochigome_focus do |f|
160
+ f.fields ["b", "a"]
161
+ end
162
+ end
163
+ i = @model_class.new(:a => "abc", :b => "xyz")
164
+ expected = ActiveSupport::OrderedHash.new
165
+ expected["b"] = "xyz"
166
+ expected["a"] = "abc"
167
+ assert_equal expected, i.mochigome_focus.field_data
168
+ end
169
+
170
+ it "can specify fields with multiple calls" do
171
+ @model_class.class_eval do
172
+ acts_as_mochigome_focus do |f|
173
+ f.fields ["a"]
174
+ f.fields ["b"]
175
+ end
176
+ end
177
+ i = @model_class.new(:a => "abc", :b => "xyz")
178
+ expected = ActiveSupport::OrderedHash.new
179
+ expected["a"] = "abc"
180
+ expected["b"] = "xyz"
181
+ assert_equal expected, i.mochigome_focus.field_data
182
+ end
183
+
184
+ it "can specify fields with custom names" do
185
+ @model_class.class_eval do
186
+ acts_as_mochigome_focus do |f|
187
+ f.fields [{:Abraham => :a}, {:Barcelona => :b}]
188
+ end
189
+ end
190
+ i = @model_class.new(:a => "abc", :b => "xyz")
191
+ expected = ActiveSupport::OrderedHash.new
192
+ expected["Abraham"] = "abc"
193
+ expected["Barcelona"] = "xyz"
194
+ assert_equal expected, i.mochigome_focus.field_data
195
+ end
196
+
197
+ it "can specify fields with custom implementations" do
198
+ @model_class.class_eval do
199
+ acts_as_mochigome_focus do |f|
200
+ f.fields [{:concat => lambda {|obj| obj.a + obj.b}}]
201
+ end
202
+ end
203
+ i = @model_class.new(:a => "abc", :b => "xyz")
204
+ expected = ActiveSupport::OrderedHash.new
205
+ expected["concat"] = "abcxyz"
206
+ assert_equal expected, i.mochigome_focus.field_data
207
+ end
208
+
209
+ it "cannot call f.fields with nonsense" do
210
+ assert_raises Mochigome::ModelSetupError do
211
+ @model_class.class_eval do
212
+ acts_as_mochigome_focus do |f|
213
+ f.fields 123
214
+ end
215
+ end
216
+ end
217
+ assert_raises Mochigome::ModelSetupError do
218
+ @model_class.class_eval do
219
+ acts_as_mochigome_focus do |f|
220
+ f.fields [789]
221
+ end
222
+ end
223
+ end
224
+ end
225
+
226
+ [:name, :id, :type, :internal_type].each do |n|
227
+ it "cannot specify fields named the same as reserved term '#{n}'" do
228
+ assert_raises Mochigome::ModelSetupError do
229
+ @model_class.class_eval do
230
+ acts_as_mochigome_focus do |f|
231
+ f.fields [n]
232
+ end
233
+ end
234
+ end
235
+ assert_raises Mochigome::ModelSetupError do
236
+ @model_class.class_eval do
237
+ acts_as_mochigome_focus do |f|
238
+ f.fields [n.to_s.titleize]
239
+ end
240
+ end
241
+ end
242
+ assert_raises Mochigome::ModelSetupError do
243
+ @model_class.class_eval do
244
+ acts_as_mochigome_focus do |f|
245
+ f.fields [{n => :foo}]
246
+ end
247
+ end
248
+ end
249
+ end
250
+ end
251
+
252
+ it "appears in Mochigome's global model list if it acts_as_mochigome_focus" do
253
+ assert !Mochigome.reportFocusModels.include?(@model_class)
254
+ @model_class.class_eval do
255
+ acts_as_mochigome_focus
256
+ end
257
+ assert Mochigome.reportFocusModels.include?(@model_class)
258
+ end
259
+
260
+ it "can specify aggregated data to be collected" do
261
+ @model_class.class_eval do
262
+ has_mochigome_aggregations [:average_x, :Count, "sum x"]
263
+ end
264
+ # Peeking in past API to make sure it set the expressions correctly
265
+ assert_equal [
266
+ {:name => "Whales average x", :expr => "avg(x)"},
267
+ {:name => "Whales Count", :expr => "count()"},
268
+ {:name => "Whales sum x", :expr => "sum(x)"}
269
+ ], @model_class.mochigome_aggregations
270
+ end
271
+
272
+ it "can specify aggregations with custom names" do
273
+ @model_class.class_eval do
274
+ has_mochigome_aggregations [{"Mean X" => "avg x"}]
275
+ end
276
+ assert_equal [
277
+ {:name => "Mean X", :expr => "avg(x)"}
278
+ ], @model_class.mochigome_aggregations
279
+ end
280
+
281
+ it "can specify aggregations with custom SQL expressions" do
282
+ @model_class.class_eval do
283
+ has_mochigome_aggregations [{"The Answer" => "7*6"}]
284
+ end
285
+ assert_equal [
286
+ {:name => "The Answer", :expr => "7*6"}
287
+ ], @model_class.mochigome_aggregations
288
+ end
289
+
290
+ it "can specify aggregations with custom conditions" do
291
+ @model_class.class_eval do
292
+ has_mochigome_aggregations [{"Blue Sales" => ["count", "color='blue'"]}]
293
+ end
294
+ assert_equal [
295
+ {:name => "Blue Sales", :expr => "count()", :conditions => "color='blue'"}
296
+ ], @model_class.mochigome_aggregations
297
+ end
298
+
299
+ it "cannot call has_mochigome_aggregations with nonsense" do
300
+ assert_raises Mochigome::ModelSetupError do
301
+ @model_class.class_eval do
302
+ has_mochigome_aggregations 3
303
+ end
304
+ end
305
+ assert_raises Mochigome::ModelSetupError do
306
+ @model_class.class_eval do
307
+ has_mochigome_aggregations [42]
308
+ end
309
+ end
310
+ end
311
+
312
+ describe "with some aggregatable data" do
313
+ before do
314
+ @store1 = create(:store)
315
+ @store2 = create(:store)
316
+ @product_a = create(:product, :name => "Product A", :price => 30)
317
+ @product_b = create(:product, :name => "Product B", :price => 50)
318
+ @sp1A = create(:store_product, :store => @store1, :product => @product_a)
319
+ @sp1B = create(:store_product, :store => @store1, :product => @product_b)
320
+ @sp2A = create(:store_product, :store => @store2, :product => @product_a)
321
+ @sp2B = create(:store_product, :store => @store2, :product => @product_b)
322
+ [
323
+ [2, @sp1A],
324
+ [4, @sp1B],
325
+ [7, @sp2A],
326
+ [3, @sp2B]
327
+ ].each do |num, sp|
328
+ num.times { create(:sale, :store_product => sp) }
329
+ end
330
+ end
331
+
332
+ it "can collect aggregate data from a report focus through an association" do
333
+ assert_equal 9, @product_a.mochigome_focus.aggregate_data('sales')['Sales count']
334
+ assert_equal 7, @product_b.mochigome_focus.aggregate_data('sales')['Sales count']
335
+ end
336
+
337
+ it "can collect aggregate data through all known associations with :all keyword" do
338
+ assert_equal 9, @product_a.mochigome_focus.aggregate_data(:all)['Sales count']
339
+ end
340
+
341
+ it "returns both field data and all aggregate data with the data method" do
342
+ data = @product_a.mochigome_focus.data
343
+ assert_equal 9, data['Sales count']
344
+ assert_equal 30, data['price']
345
+ end
346
+
347
+ it "can return data aggregated in the context of another class with similar assoc" do
348
+ focus = @product_a.mochigome_focus
349
+ assert_equal 2, focus.aggregate_data('sales', :context => [@sp1A])['Sales count']
350
+ end
351
+
352
+ it "can return data aggregated in the context through the data method" do
353
+ focus = @product_a.mochigome_focus
354
+ assert_equal 2, focus.data(:context => [@sp1A])['Sales count']
355
+ end
356
+
357
+ it "can return data aggregated using a custom sql expression" do
358
+ focus = @store1.mochigome_focus
359
+ assert_equal 9001, focus.data['Power level']
360
+ end
361
+
362
+ it "can return data aggregated using custom conditions" do
363
+ focus = @store1.mochigome_focus
364
+ assert_equal 1, focus.data['Expensive products']
365
+ end
366
+ end
367
+ end
@@ -0,0 +1,202 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ describe Mochigome::Query do
4
+ before do
5
+ @category1 = create(:category, :name => "Category 1")
6
+ @product_a = create(:product, :name => "Product A", :category => @category1)
7
+ @product_b = create(:product, :name => "Product B", :category => @category1)
8
+
9
+ # Belongs to a category, but fails Category's has_many(:products) conditions
10
+ @product_x = create(:product, :name => "Product X", :category => @category1, :categorized => false)
11
+
12
+ @category2 = create(:category, :name => "Category 2")
13
+ @product_c = create(:product, :name => "Product C", :category => @category2)
14
+ @product_d = create(:product, :name => "Product D", :category => @category2)
15
+
16
+ @product_e = create(:product, :name => "Product E") # No category
17
+
18
+ @john = create(:owner, :first_name => "John", :last_name => "Smith")
19
+ @store_x = create(:store, :name => "John's Store", :owner => @john)
20
+
21
+ @jane = create(:owner, :first_name => "Jane", :last_name => "Doe")
22
+ @store_y = create(:store, :name => "Jane's Store (North)", :owner => @jane)
23
+ @store_z = create(:store, :name => "Jane's Store (South)", :owner => @jane)
24
+
25
+ @sp_xa = create(:store_product, :store => @store_x, :product => @product_a)
26
+ @sp_xc = create(:store_product, :store => @store_x, :product => @product_c)
27
+ @sp_ya = create(:store_product, :store => @store_y, :product => @product_a)
28
+ @sp_yb = create(:store_product, :store => @store_y, :product => @product_b)
29
+ @sp_ye = create(:store_product, :store => @store_y, :product => @product_e)
30
+ @sp_zc = create(:store_product, :store => @store_z, :product => @product_c)
31
+ @sp_zd = create(:store_product, :store => @store_z, :product => @product_d)
32
+
33
+ [
34
+ [@sp_xa, 5],
35
+ [@sp_xc, 3],
36
+ [@sp_ya, 4],
37
+ [@sp_yb, 6],
38
+ [@sp_ye, 1],
39
+ [@sp_zc, 2],
40
+ [@sp_zd, 3]
41
+ ].each do |sp, n|
42
+ n.times{create(:sale, :store_product => sp)}
43
+ end
44
+ end
45
+
46
+ # Convenience function to check DataSet output validity
47
+ def assert_equal_objs(a, b)
48
+ assert_equal a.size, b.size
49
+ # Not checking aggregate data because we don't know about a's context here
50
+ a.zip(b).each do |obj, fields|
51
+ obj.mochigome_focus.field_data.each do |k,v|
52
+ assert_equal v, fields[k]
53
+ end
54
+ end
55
+ end
56
+
57
+ it "returns an empty DataNode if no objects given" do
58
+ q = Mochigome::Query.new([Category, Product])
59
+ data_node = q.run([])
60
+ assert_empty data_node
61
+ assert_empty data_node.children
62
+ end
63
+
64
+ it "can build a one-layer DataNode" do
65
+ q = Mochigome::Query.new([Product])
66
+ data_node = q.run(@product_a)
67
+ assert_equal_objs [@product_a], data_node.children
68
+ assert_empty data_node.children[0].children
69
+ end
70
+
71
+ it "uses the model focus's type name for the DataNode's type name" do
72
+ q = Mochigome::Query.new([Store])
73
+ data_node = q.run(@store_x)
74
+ assert_equal "Storefront", data_node.children[0].type_name.to_s
75
+ end
76
+
77
+ it "adds an internal_type attribute containing the model class's name" do
78
+ q = Mochigome::Query.new([Store])
79
+ data_node = q.run(@store_x)
80
+ assert_equal "Store", data_node.children[0][:internal_type]
81
+ end
82
+
83
+ it "can build a two-layer tree from a record with a belongs_to association" do
84
+ q = Mochigome::Query.new([Category, Product])
85
+ data_node = q.run(@product_a)
86
+ assert_equal_objs [@category1], data_node.children
87
+ assert_equal_objs [@product_a], data_node.children[0].children
88
+ assert_empty data_node.children[0].children[0].children
89
+ end
90
+
91
+ it "can build a two-layer tree from an array of records in the second layer" do
92
+ q = Mochigome::Query.new([Category, Product])
93
+ data_node = q.run([@product_a, @product_d, @product_b])
94
+ assert_equal_objs [@category1, @category2], data_node.children
95
+ assert_equal_objs [@product_a, @product_b], data_node.children[0].children
96
+ assert_equal_objs [@product_d], data_node.children[1].children
97
+ end
98
+
99
+ it "can build a two-layer tree from a record with a has_many association" do
100
+ q = Mochigome::Query.new([Category, Product])
101
+ data_node = q.run(@category1)
102
+ assert_equal_objs [@category1], data_node.children
103
+ assert_equal_objs [@product_a, @product_b], data_node.children[0].children
104
+ assert_empty data_node.children[0].children[0].children
105
+ end
106
+
107
+ it "cannot build a DataNode tree when given disconnected layers" do
108
+ q = Mochigome::Query.new([Category, BoringDatum])
109
+ assert_raises Mochigome::QueryError do
110
+ data_node = q.run(@category1)
111
+ end
112
+ end
113
+
114
+ it "can build a three-layer tree from any layer" do
115
+ q = Mochigome::Query.new([Owner, Store, Product])
116
+ [
117
+ [@john, @jane],
118
+ [@store_x, @store_y, @store_z],
119
+ [@product_a, @product_b, @product_c, @product_d, @product_e]
120
+ ].each do |tgt|
121
+ data_node = q.run(tgt)
122
+ assert_equal_objs [@john, @jane], data_node.children
123
+ assert_equal_objs [@store_x], data_node.children[0].children
124
+ assert_equal_objs [@store_y, @store_z], data_node.children[1].children
125
+ assert_equal_objs [@product_a, @product_c],
126
+ data_node.children[0].children[0].children
127
+ assert_equal_objs [@product_c, @product_d],
128
+ data_node.children[1].children[1].children
129
+ end
130
+ end
131
+
132
+ it "collects aggregate data in the context of all layers when traversing down" do
133
+ q = Mochigome::Query.new([Owner, Store, Product])
134
+ data_node = q.run([@john, @jane])
135
+ # Store X, Product C
136
+ assert_equal "Product C", data_node.children[0].children[0].children[1].name
137
+ assert_equal 3, data_node.children[0].children[0].children[1]['Sales count']
138
+ # Store Z, Product C
139
+ assert_equal "Product C", data_node.children[1].children[1].children[0].name
140
+ assert_equal 2, data_node.children[1].children[1].children[0]['Sales count']
141
+ end
142
+
143
+ it "collects aggregate data in the context of all layers when traversing up" do
144
+ q = Mochigome::Query.new([Owner, Store, Product])
145
+ data_node = q.run(@product_c)
146
+ # Store X, Product C
147
+ assert_equal "Product C", data_node.children[0].children[0].children[0].name
148
+ assert_equal 3, data_node.children[0].children[0].children[0]['Sales count']
149
+ # Store Z, Product C
150
+ assert_equal "Product C", data_node.children[1].children[0].children[0].name
151
+ assert_equal 2, data_node.children[1].children[0].children[0]['Sales count']
152
+ end
153
+
154
+ it "collects aggregate data in the context of distant layers" do
155
+ # TODO: Implement me! I think this is necessary to justify focus_data_node_objs passing obj_stack
156
+ end
157
+
158
+ it "puts a comment on the root node describing the query" do
159
+ q = Mochigome::Query.new([Owner, Store, Product])
160
+ data_node = q.run([@store_x, @store_y, @store_z])
161
+ c = data_node.comment
162
+ assert_match c, /^Mochigome Version: #{Mochigome::VERSION}\n/
163
+ assert_match c, /\nTime: \w{3} \w{3} \d+ .+\n/
164
+ assert_match c, /\nLayers: Owner => Store => Product\n/
165
+ assert_match c, /\nAR Association Path:\n\* <- Owner.+\n\* == Store.+\n\* -> Product.+\n/
166
+ end
167
+
168
+ it "puts a descriptive comment on the first node of each layer" do
169
+ q = Mochigome::Query.new([Owner, Store, Product])
170
+ data_node = q.run([@store_x, @store_y, @store_z])
171
+
172
+ owner_comment = data_node.children[0].comment
173
+ assert owner_comment
174
+ assert_nil data_node.children[1].comment # No comment on second owner
175
+
176
+ store_comment = data_node.children[0].children[0].comment
177
+ assert store_comment
178
+ assert_nil data_node.children[1].children[0].comment # No comment on second store
179
+
180
+ product_comment = data_node.children[0].children[0].children[0].comment
181
+ assert product_comment
182
+ assert_nil data_node.children[0].children[0].children[1].comment # No comment on 2nd product
183
+
184
+ [owner_comment, store_comment, product_comment].each do |comment|
185
+ assert_match comment, /^Context:\nOwner:#{@john.id}.*\n/ # Owner is always in context
186
+ end
187
+ end
188
+
189
+ it "will not allow a query on targets of different types" do
190
+ q = Mochigome::Query.new([Owner, Store, Product])
191
+ assert_raises Mochigome::QueryError do
192
+ q.run([@store_x, @john])
193
+ end
194
+ end
195
+
196
+ it "will not allow a query on targets not in the layer list" do
197
+ q = Mochigome::Query.new([Product])
198
+ assert_raises Mochigome::QueryError do
199
+ q.run(@category1)
200
+ end
201
+ end
202
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mochigome
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - David Mike Simon
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-11-14 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ requirement: &id001 !ruby/object:Gem::Requirement
22
+ none: false
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ hash: 3
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ version_requirements: *id001
31
+ name: ruport
32
+ prerelease: false
33
+ type: :runtime
34
+ - !ruby/object:Gem::Dependency
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ hash: 3
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ version_requirements: *id002
45
+ name: nokogiri
46
+ prerelease: false
47
+ type: :runtime
48
+ - !ruby/object:Gem::Dependency
49
+ requirement: &id003 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ hash: 3
55
+ segments:
56
+ - 0
57
+ version: "0"
58
+ version_requirements: *id003
59
+ name: rgl
60
+ prerelease: false
61
+ type: :runtime
62
+ description: Mochigome builds sophisticated report datasets from your ActiveRecord models
63
+ email: david.mike.simon@gmail.com
64
+ executables: []
65
+
66
+ extensions: []
67
+
68
+ extra_rdoc_files: []
69
+
70
+ files:
71
+ - .autotest
72
+ - Gemfile
73
+ - Gemfile.lock
74
+ - LICENSE
75
+ - README.rdoc
76
+ - Rakefile
77
+ - TODO
78
+ - lib/data_node.rb
79
+ - lib/exceptions.rb
80
+ - lib/mochigome.rb
81
+ - lib/mochigome_ver.rb
82
+ - lib/model_extensions.rb
83
+ - lib/query.rb
84
+ - test/app_root/app/controllers/application_controller.rb
85
+ - test/app_root/app/controllers/owners_controller.rb
86
+ - test/app_root/app/models/boring_datum.rb
87
+ - test/app_root/app/models/category.rb
88
+ - test/app_root/app/models/owner.rb
89
+ - test/app_root/app/models/product.rb
90
+ - test/app_root/app/models/sale.rb
91
+ - test/app_root/app/models/store.rb
92
+ - test/app_root/app/models/store_product.rb
93
+ - test/app_root/config/boot.rb
94
+ - test/app_root/config/database-pg.yml
95
+ - test/app_root/config/database.yml
96
+ - test/app_root/config/environment.rb
97
+ - test/app_root/config/environments/test.rb
98
+ - test/app_root/config/offroad.yml
99
+ - test/app_root/config/preinitializer.rb
100
+ - test/app_root/config/routes.rb
101
+ - test/app_root/db/migrate/20110817163830_create_tables.rb
102
+ - test/app_root/vendor/plugins/mochigome/init.rb
103
+ - test/factories.rb
104
+ - test/test.watchr
105
+ - test/test_helper.rb
106
+ - test/unit/data_node_test.rb
107
+ - test/unit/model_extensions_test.rb
108
+ - test/unit/query_test.rb
109
+ homepage: http://github.com/DavidMikeSimon/mochigome
110
+ licenses: []
111
+
112
+ post_install_message:
113
+ rdoc_options: []
114
+
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ hash: 3
123
+ segments:
124
+ - 0
125
+ version: "0"
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ hash: 3
132
+ segments:
133
+ - 0
134
+ version: "0"
135
+ requirements: []
136
+
137
+ rubyforge_project: "[none]"
138
+ rubygems_version: 1.8.6
139
+ signing_key:
140
+ specification_version: 3
141
+ summary: User-customizable report generator
142
+ test_files: []
143
+