mochigome 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/test/test_helper.rb CHANGED
@@ -1,67 +1,67 @@
1
1
  ENV['RAILS_ENV'] = 'test'
2
2
 
3
- prev_dir = Dir.getwd
4
3
  begin
5
- Dir.chdir("#{File.dirname(__FILE__)}/..")
6
-
7
- begin
8
- # Used when running test files directly
9
- $LOAD_PATH << File.dirname(__FILE__)
10
- $LOAD_PATH << "#{File.dirname(__FILE__)}/../lib"
11
- require "#{File.dirname(__FILE__)}/app_root/config/environment"
12
- rescue LoadError
13
- # This is needed for root-level rake task 'test'
14
- require "app_root/config/environment"
15
- end
16
- ensure
17
- Dir.chdir(prev_dir)
4
+ # Used when running test files directly
5
+ d = File.expand_path File.dirname(__FILE__)
6
+ $LOAD_PATH << d
7
+ $LOAD_PATH << "#{d}/../lib"
8
+ $LOAD_PATH << "#{d}/app_root/config"
9
+ require "environment"
10
+ rescue LoadError
11
+ # This is needed for root-level rake task 'test'
12
+ require "app_root/config/environment"
18
13
  end
19
14
 
20
15
  require 'rubygems'
21
- require 'minitest/autorun'
22
- require 'redgreen'
23
16
 
24
- module MiniTest
25
- def self.filter_backtrace(backtrace)
26
- backtrace = backtrace.select do |e|
27
- if ENV['FULL_BACKTRACE']
28
- true
29
- else
30
- !(e.include?("/ruby/") || e.include?("/gems/"))
17
+ if ENV['NO_MINITEST']
18
+ ActiveRecord::Migration.verbose = false
19
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate") # Migrations in the test app
20
+ else
21
+ require 'minitest/autorun'
22
+ require 'redgreen'
23
+
24
+ module MiniTest
25
+ def self.filter_backtrace(backtrace)
26
+ backtrace = backtrace.select do |e|
27
+ if ENV['FULL_BACKTRACE']
28
+ true
29
+ else
30
+ !(e.include?("/ruby/") || e.include?("/gems/"))
31
+ end
31
32
  end
32
- end
33
33
 
34
- common_prefix = nil
35
- backtrace.each do |elem|
36
- next if elem.start_with? "./"
37
- if common_prefix
38
- until elem.start_with? common_prefix
39
- common_prefix.chop!
34
+ common_prefix = nil
35
+ backtrace.each do |elem|
36
+ next if elem.start_with? "./"
37
+ if common_prefix
38
+ until elem.start_with? common_prefix
39
+ common_prefix.chop!
40
+ end
41
+ else
42
+ common_prefix = String.new(elem)
40
43
  end
41
- else
42
- common_prefix = String.new(elem)
43
44
  end
44
- end
45
45
 
46
- return backtrace.map do |element|
47
- if element.start_with? common_prefix && common_prefix.size < element.size
48
- element[common_prefix.size, element.size]
49
- elsif element.start_with? "./"
50
- element[2, element.size]
51
- elsif element.start_with?(Dir.getwd)
52
- element[Dir.getwd.size+1, element.size]
53
- else
54
- element
46
+ return backtrace.map do |element|
47
+ if element.start_with? common_prefix && common_prefix.size < element.size
48
+ element[common_prefix.size, element.size]
49
+ elsif element.start_with? "./"
50
+ element[2, element.size]
51
+ elsif element.start_with?(Dir.getwd)
52
+ element[Dir.getwd.size+1, element.size]
53
+ else
54
+ element
55
+ end
55
56
  end
56
57
  end
57
58
  end
58
- end
59
-
60
59
 
61
- require 'factories'
62
- MiniTest::Unit::TestCase.send(:include, Factory::Syntax::Methods)
60
+ require 'factories'
61
+ MiniTest::Unit::TestCase.send(:include, Factory::Syntax::Methods)
63
62
 
64
- MiniTest::Unit::TestCase.add_setup_hook do
65
- ActiveRecord::Migration.verbose = false
66
- ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate") # Migrations in the test app
63
+ MiniTest::Unit::TestCase.add_setup_hook do
64
+ ActiveRecord::Migration.verbose = false
65
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate") # Migrations in the test app
66
+ end
67
67
  end
@@ -77,6 +77,13 @@ describe Mochigome::DataNode do
77
77
  ]
78
78
  assert_equal @datanode.children.drop(1), new_children
79
79
  end
80
+
81
+ it "understands forward-slash to mean indexing in children" do
82
+ @datanode << Mochigome::DataNode.new(:subdata, :alice)
83
+ @datanode << Mochigome::DataNode.new(:subdata, :bob)
84
+ assert_equal @datanode.children[0], @datanode/0
85
+ assert_equal @datanode.children[1], @datanode/1
86
+ end
80
87
  end
81
88
 
82
89
  describe "when populated" do
@@ -1,31 +1,5 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
2
 
3
- describe "an input string" do
4
- it "will be converted by auto_numerify to an integer if appropriate" do
5
- [35, -35, 0].each do |n|
6
- result = Mochigome::ReportFocus.auto_numerify(n.to_s)
7
- assert_equal n, result
8
- assert_kind_of Integer, result
9
- end
10
- end
11
-
12
- it "will be converted by auto_numerify to a float if appropriate" do
13
- [-35.5, 35.5, 0.0].each do |n|
14
- result = Mochigome::ReportFocus.auto_numerify(n.to_s)
15
- assert_in_delta n, result
16
- assert_kind_of Float, result
17
- end
18
- end
19
-
20
- it "will remain a string if it is not numeric" do
21
- ["", "zero", "yeehah", "foo0.0" "9.2bar"].each do |s|
22
- result = Mochigome::ReportFocus.auto_numerify(s)
23
- assert_equal s, result
24
- assert_kind_of String, result
25
- end
26
- end
27
- end
28
-
29
3
  describe "an ActiveRecord model" do
30
4
  before do
31
5
  @model_class = Class.new(ActiveRecord::Base)
@@ -147,6 +121,27 @@ describe "an ActiveRecord model" do
147
121
  assert_equal "Moby Dick", i.mochigome_focus.name
148
122
  end
149
123
 
124
+ it "uses the primary key as the default ordering" do
125
+ @model_class.class_eval do
126
+ acts_as_mochigome_focus do |f|
127
+ f.name :last_name
128
+ end
129
+ end
130
+ assert_equal "id",
131
+ @model_class.mochigome_focus_settings.get_ordering
132
+ end
133
+
134
+ it "can specify a custom ordering" do
135
+ @model_class.class_eval do
136
+ acts_as_mochigome_focus do |f|
137
+ f.name :last_name
138
+ f.ordering :first_name
139
+ end
140
+ end
141
+ assert_equal "first_name",
142
+ @model_class.mochigome_focus_settings.get_ordering
143
+ end
144
+
150
145
  it "can specify fields" do
151
146
  @model_class.class_eval do
152
147
  acts_as_mochigome_focus do |f|
@@ -275,119 +270,141 @@ describe "an ActiveRecord model" do
275
270
  end
276
271
  end
277
272
 
278
- it "appears in Mochigome's global model list if it acts_as_mochigome_focus" do
279
- assert !Mochigome.reportFocusModels.include?(@model_class)
280
- @model_class.class_eval do
281
- acts_as_mochigome_focus
282
- end
283
- assert Mochigome.reportFocusModels.include?(@model_class)
284
- end
273
+ # Actual use of aggregations is tested in query_test.
285
274
 
286
275
  it "can specify aggregated data to be collected" do
287
276
  @model_class.class_eval do
288
- has_mochigome_aggregations [:average_x, :Count, "sum x"]
277
+ has_mochigome_aggregations do |a|
278
+ a.fields [
279
+ :average_x,
280
+ :Count,
281
+ {"bloo" => :sum_x}
282
+ ]
283
+ end
289
284
  end
290
- # Peeking in past API to make sure it set the expressions correctly
291
285
  assert_equal [
292
- {:name => "Whales average x", :expr => "avg(x)"},
293
- {:name => "Whales Count", :expr => "count(*)"},
294
- {:name => "Whales sum x", :expr => "sum(x)"}
295
- ], @model_class.mochigome_aggregations
286
+ "Whales average x",
287
+ "Whales Count",
288
+ "bloo"
289
+ ], @model_class.mochigome_aggregation_settings.options[:fields].map{|a| a[:name]}
296
290
  end
297
291
 
298
292
  it "can specify aggregations with custom names" do
299
293
  @model_class.class_eval do
300
- has_mochigome_aggregations [{"Mean X" => "avg x"}]
294
+ has_mochigome_aggregations do |a|
295
+ a.fields [{"Mean X" => "avg x"}]
296
+ end
301
297
  end
302
298
  assert_equal [
303
- {:name => "Mean X", :expr => "avg(x)"}
304
- ], @model_class.mochigome_aggregations
299
+ "Mean X"
300
+ ], @model_class.mochigome_aggregation_settings.options[:fields].map{|a| a[:name]}
305
301
  end
306
302
 
307
- it "can specify aggregations with custom SQL expressions" do
303
+ it "can specify aggregations with custom arel expressions for value" do
308
304
  @model_class.class_eval do
309
- has_mochigome_aggregations [{"The Answer" => "7*6"}]
305
+ has_mochigome_aggregations do |a|
306
+ a.fields [{"The Answer" => [:sum, lambda{|t| t[:some_number_column]*2}]}]
307
+ end
310
308
  end
311
309
  assert_equal [
312
- {:name => "The Answer", :expr => "7*6"}
313
- ], @model_class.mochigome_aggregations
310
+ "The Answer"
311
+ ], @model_class.mochigome_aggregation_settings.options[:fields].map{|a| a[:name]}
314
312
  end
315
313
 
316
- it "can specify aggregations with custom conditions" do
314
+ it "can specify aggregations with custom arel expressions for aggregation" do
317
315
  @model_class.class_eval do
318
- has_mochigome_aggregations [{"Blue Sales" => ["count", "color='blue'"]}]
316
+ has_mochigome_aggregations do |a|
317
+ a.fields [{"The Answer" => [lambda{|a| a.sum}, :some_col]}]
318
+ end
319
319
  end
320
320
  assert_equal [
321
- {:name => "Blue Sales", :expr => "count(*)", :conditions => "color='blue'"}
322
- ], @model_class.mochigome_aggregations
321
+ "The Answer"
322
+ ], @model_class.mochigome_aggregation_settings.options[:fields].map{|a| a[:name]}
323
323
  end
324
324
 
325
- it "cannot call has_mochigome_aggregations with nonsense" do
325
+ it "cannot call aggregation fields method with nonsense" do
326
326
  assert_raises Mochigome::ModelSetupError do
327
327
  @model_class.class_eval do
328
- has_mochigome_aggregations 3
328
+ has_mochigome_aggregations do |a|
329
+ a.fields 3
330
+ end
329
331
  end
330
332
  end
331
333
  assert_raises Mochigome::ModelSetupError do
332
334
  @model_class.class_eval do
333
- has_mochigome_aggregations [42]
335
+ has_mochigome_aggregations do |a|
336
+ a.fields [42]
337
+ end
334
338
  end
335
339
  end
336
340
  end
337
341
 
338
- describe "with some aggregatable data" do
339
- before do
340
- @store1 = create(:store)
341
- @store2 = create(:store)
342
- @product_a = create(:product, :name => "Product A", :price => 30)
343
- @product_b = create(:product, :name => "Product B", :price => 50)
344
- @sp1A = create(:store_product, :store => @store1, :product => @product_a)
345
- @sp1B = create(:store_product, :store => @store1, :product => @product_b)
346
- @sp2A = create(:store_product, :store => @store2, :product => @product_a)
347
- @sp2B = create(:store_product, :store => @store2, :product => @product_b)
348
- [
349
- [2, @sp1A],
350
- [4, @sp1B],
351
- [7, @sp2A],
352
- [3, @sp2B]
353
- ].each do |num, sp|
354
- num.times { create(:sale, :store_product => sp) }
342
+ it "can specify hidden aggregation fields" do
343
+ @model_class.class_eval do
344
+ has_mochigome_aggregations do |a|
345
+ a.hidden_fields [:count]
355
346
  end
356
347
  end
348
+ agg = @model_class.mochigome_aggregation_settings.options[:fields].first
349
+ assert_equal "Whales count", agg[:name]
350
+ assert agg[:hidden]
351
+ end
357
352
 
358
- it "can collect aggregate data from a report focus through an association" do
359
- assert_equal 9, @product_a.mochigome_focus.aggregate_data('sales')['Sales count']
360
- assert_equal 7, @product_b.mochigome_focus.aggregate_data('sales')['Sales count']
361
- end
362
-
363
- it "can collect aggregate data through all known associations with :all keyword" do
364
- assert_equal 9, @product_a.mochigome_focus.aggregate_data(:all)['Sales count']
353
+ it "can specify aggregation fields in ruby which post-process regular fields" do
354
+ @model_class.class_eval do
355
+ has_mochigome_aggregations do |a|
356
+ a.hidden_fields [:count]
357
+ a.fields_in_ruby [
358
+ {"Double count" => lambda{|row| row["Whales count"]*2}}
359
+ ]
360
+ end
365
361
  end
362
+ agg = @model_class.mochigome_aggregation_settings.options[:fields].last
363
+ assert_equal "Double count", agg[:name]
364
+ assert agg[:in_ruby]
365
+ end
366
366
 
367
- it "returns both field data and all aggregate data with the data method" do
368
- data = @product_a.mochigome_focus.data
369
- assert_equal 9, data['Sales count']
370
- assert_equal 30, data['price']
367
+ def assoc_query_words_match(assoc, words)
368
+ q = assoc.call(Arel::Table.new(:foo).project(Arel.star)).to_sql
369
+ cur_word = words.shift
370
+ q.split(/[ .]/).each do |s_word|
371
+ if s_word.gsub(/["'`]+/, '').downcase == cur_word.downcase
372
+ cur_word = words.shift
373
+ end
371
374
  end
375
+ return true if cur_word.nil?
376
+ raise "AQWM '#{q}': NO WORD MATCH ON '#{cur_word}'"
377
+ end
372
378
 
373
- it "can return data aggregated in the context of another class with similar assoc" do
374
- focus = @product_a.mochigome_focus
375
- assert_equal 2, focus.aggregate_data('sales', :context => [@sp1A])['Sales count']
379
+ it "can convert a belongs_to association into a lambda that processes an arel relation" do
380
+ @model_class.class_eval do
381
+ belongs_to :store
376
382
  end
383
+ assert assoc_query_words_match @model_class.arelified_assoc(:store),
384
+ %w{select * from foo join stores on fake store_id = stores id}
385
+ end
377
386
 
378
- it "can return data aggregated in the context through the data method" do
379
- focus = @product_a.mochigome_focus
380
- assert_equal 2, focus.data(:context => [@sp1A])['Sales count']
387
+ it "can convert a has_many association into an arel relation lambda" do
388
+ @model_class.class_eval do
389
+ has_many :stores
381
390
  end
391
+ assert assoc_query_words_match @model_class.arelified_assoc(:stores),
392
+ %w{select * from foo join stores on fake id = stores whale_id}
393
+ end
382
394
 
383
- it "can return data aggregated using a custom sql expression" do
384
- focus = @store1.mochigome_focus
385
- assert_equal 9001, focus.data['Power level']
395
+ it "can convert a has_one association into an arel relation lambda" do
396
+ @model_class.class_eval do
397
+ has_one :store
386
398
  end
399
+ assert assoc_query_words_match @model_class.arelified_assoc(:store),
400
+ %w{select * from foo join stores on fake id = stores whale_id}
401
+ end
387
402
 
388
- it "can return data aggregated using custom conditions" do
389
- focus = @store1.mochigome_focus
390
- assert_equal 1, focus.data['Expensive products']
403
+ it "raises AssociationError on attempting to arelify a non-extant assoc" do
404
+ assert_raises Mochigome::AssociationError do
405
+ Store.arelified_assoc(:dinosaurs)
391
406
  end
392
407
  end
408
+
409
+ # TODO: Test proper conditions used on polymorphic assocs
393
410
  end