dm-aggregates 0.9.7 → 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1 +1,6 @@
1
+ === 0.9.8 / 2008-12-07
1
2
 
3
+ * 2 minor enhancements:
4
+
5
+ * Collection#size now uses #count if unloaded
6
+ * Added Model#size, which defers to #count
data/Manifest.txt CHANGED
@@ -12,6 +12,10 @@ lib/dm-aggregates/model.rb
12
12
  lib/dm-aggregates/repository.rb
13
13
  lib/dm-aggregates/support/symbol.rb
14
14
  lib/dm-aggregates/version.rb
15
- spec/integration/aggregates_spec.rb
15
+ spec/public/collection_spec.rb
16
+ spec/public/model_spec.rb
17
+ spec/public/shared/aggregate_shared_spec.rb
16
18
  spec/spec.opts
17
19
  spec/spec_helper.rb
20
+ tasks/install.rb
21
+ tasks/spec.rb
data/Rakefile CHANGED
@@ -1,58 +1,25 @@
1
- require 'rubygems'
2
- require 'spec'
3
- require 'spec/rake/spectask'
4
1
  require 'pathname'
2
+ require 'rubygems'
5
3
 
6
- ROOT = Pathname(__FILE__).dirname.expand_path
7
- require ROOT + 'lib/dm-aggregates/version'
8
-
9
- AUTHOR = "Foy Savas"
10
- EMAIL = "foysavas@gmail.com"
11
- GEM_NAME = "dm-aggregates"
12
- GEM_VERSION = DataMapper::More::Aggregates::VERSION
13
- GEM_DEPENDENCIES = [["dm-core", GEM_VERSION]]
14
- GEM_CLEAN = ["log", "pkg"]
15
- GEM_EXTRAS = { :has_rdoc => true, :extra_rdoc_files => %w[ README.txt LICENSE TODO ] }
16
-
17
- PROJECT_NAME = "datamapper"
18
- PROJECT_URL = "http://github.com/sam/dm-more/tree/master/dm-aggregates"
19
- PROJECT_DESCRIPTION = PROJECT_SUMMARY = "DataMapper plugin providing support for aggregates, functions on collections and datasets"
20
-
21
- require ROOT.parent + 'tasks/hoe'
22
-
23
- task :default => [ :spec ]
24
-
25
- WIN32 = (RUBY_PLATFORM =~ /win32|mingw|cygwin/) rescue nil
26
- SUDO = WIN32 ? '' : ('sudo' unless ENV['SUDOLESS'])
27
-
28
- desc "Install #{GEM_NAME} #{GEM_VERSION} (default ruby)"
29
- task :install => [ :package ] do
30
- sh "#{SUDO} gem install --local pkg/#{GEM_NAME}-#{GEM_VERSION} --no-update-sources", :verbose => false
31
- end
4
+ ROOT = Pathname(__FILE__).dirname.expand_path
5
+ JRUBY = RUBY_PLATFORM =~ /java/
6
+ WINDOWS = Gem.win_platform?
7
+ SUDO = (WINDOWS || JRUBY) ? '' : ('sudo' unless ENV['SUDOLESS'])
32
8
 
33
- desc "Uninstall #{GEM_NAME} #{GEM_VERSION} (default ruby)"
34
- task :uninstall => [ :clobber ] do
35
- sh "#{SUDO} gem uninstall #{GEM_NAME} -v#{GEM_VERSION} -I -x", :verbose => false
36
- end
9
+ require ROOT + 'lib/dm-aggregates/version'
37
10
 
38
- namespace :jruby do
39
- desc "Install #{GEM_NAME} #{GEM_VERSION} with JRuby"
40
- task :install => [ :package ] do
41
- sh %{#{SUDO} jruby -S gem install --local pkg/#{GEM_NAME}-#{GEM_VERSION} --no-update-sources}, :verbose => false
42
- end
43
- end
11
+ AUTHOR = 'Foy Savas'
12
+ EMAIL = 'foysavas [a] gmail [d] com'
13
+ GEM_NAME = 'dm-aggregates'
14
+ GEM_VERSION = DataMapper::Aggregates::VERSION
15
+ GEM_DEPENDENCIES = [['dm-core', "~>#{GEM_VERSION}"]]
16
+ GEM_CLEAN = %w[ log pkg coverage ]
17
+ GEM_EXTRAS = { :has_rdoc => true, :extra_rdoc_files => %w[ README.txt LICENSE TODO History.txt ] }
44
18
 
45
- desc 'Run specifications'
46
- Spec::Rake::SpecTask.new(:spec) do |t|
47
- t.spec_opts << '--options' << 'spec/spec.opts' if File.exists?('spec/spec.opts')
48
- t.spec_files = Pathname.glob((ROOT + 'spec/**/*_spec.rb').to_s)
19
+ PROJECT_NAME = 'datamapper'
20
+ PROJECT_URL = "http://github.com/sam/dm-more/tree/master/#{GEM_NAME}"
21
+ PROJECT_DESCRIPTION = PROJECT_SUMMARY = 'DataMapper plugin providing support for aggregates, functions on collections and datasets'
49
22
 
50
- begin
51
- t.rcov = ENV.has_key?('NO_RCOV') ? ENV['NO_RCOV'] != 'true' : true
52
- t.rcov_opts << '--exclude' << 'spec'
53
- t.rcov_opts << '--text-summary'
54
- t.rcov_opts << '--sort' << 'coverage' << '--sort-reverse'
55
- rescue Exception
56
- # rcov not installed
57
- end
23
+ [ ROOT, ROOT.parent ].each do |dir|
24
+ Pathname.glob(dir.join('tasks/**/*.rb').to_s).each { |f| require f }
58
25
  end
data/TODO CHANGED
@@ -1,6 +0,0 @@
1
- TODO
2
- ====
3
-
4
- ---
5
- TODO tickets may also be found in the DataMapper Issue Tracker:
6
- http://wm.lighthouseapp.com/projects/4819-datamapper/overview
@@ -2,6 +2,10 @@ module DataMapper
2
2
  class Collection
3
3
  include AggregateFunctions
4
4
 
5
+ def size
6
+ loaded? ? super : count
7
+ end
8
+
5
9
  private
6
10
 
7
11
  def property_by_name(property_name)
@@ -2,6 +2,10 @@ module DataMapper
2
2
  module Model
3
3
  include AggregateFunctions
4
4
 
5
+ def size
6
+ count
7
+ end
8
+
5
9
  private
6
10
 
7
11
  def property_by_name(property_name)
@@ -1,7 +1,5 @@
1
1
  module DataMapper
2
- module More
3
- module Aggregates
4
- VERSION = "0.9.7"
5
- end
2
+ module Aggregates
3
+ VERSION = '0.9.8'
6
4
  end
7
5
  end
data/lib/dm-aggregates.rb CHANGED
@@ -3,7 +3,7 @@ require 'rubygems'
3
3
  dir = Pathname(__FILE__).dirname.expand_path + 'dm-aggregates'
4
4
 
5
5
  require dir + 'version'
6
- gem 'dm-core', DataMapper::More::Aggregates::VERSION
6
+ gem 'dm-core', '~>0.9.8'
7
7
  require 'dm-core'
8
8
 
9
9
 
@@ -0,0 +1,15 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
3
+
4
+ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
5
+ describe DataMapper::Collection do
6
+ it_should_behave_like 'It Has Setup Resources'
7
+
8
+ before :all do
9
+ @dragons = Dragon.all
10
+ @countries = Country.all
11
+ end
12
+
13
+ it_should_behave_like 'An Aggregatable Class'
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
3
+
4
+ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
5
+ describe DataMapper::Model do
6
+ it_should_behave_like 'It Has Setup Resources'
7
+
8
+ before :all do
9
+ @dragons = Dragon
10
+ @countries = Country
11
+ end
12
+
13
+ it_should_behave_like 'An Aggregatable Class'
14
+ end
15
+ end
@@ -0,0 +1,327 @@
1
+ shared_examples_for 'It Has Setup Resources' do
2
+ before :all do
3
+ # A simplistic example, using with an Integer property
4
+ class Knight
5
+ include DataMapper::Resource
6
+
7
+ property :id, Serial
8
+ property :name, String
9
+ end
10
+
11
+ class Dragon
12
+ include DataMapper::Resource
13
+
14
+ property :id, Serial
15
+ property :name, String
16
+ property :is_fire_breathing, TrueClass
17
+ property :toes_on_claw, Integer
18
+ property :birth_at, DateTime
19
+ property :birth_on, Date
20
+ property :birth_time, Time
21
+
22
+ belongs_to :knight
23
+ end
24
+
25
+ # A more complex example, with BigDecimal and Float properties
26
+ # Statistics taken from CIA World Factbook:
27
+ # https://www.cia.gov/library/publications/the-world-factbook/
28
+ class Country
29
+ include DataMapper::Resource
30
+
31
+ property :id, Serial
32
+ property :name, String, :nullable => false
33
+ property :population, Integer
34
+ property :birth_rate, Float, :precision => 4, :scale => 2
35
+ property :gold_reserve_tonnes, Float, :precision => 6, :scale => 2
36
+ property :gold_reserve_value, BigDecimal, :precision => 15, :scale => 1 # approx. value in USD
37
+ end
38
+
39
+ DataMapper.auto_migrate!
40
+
41
+ @birth_at = DateTime.now
42
+ @birth_on = Date.parse(@birth_at.to_s)
43
+ @birth_time = Time.parse(@birth_at.to_s)
44
+
45
+ @chuck = Knight.create(:name => 'Chuck')
46
+ @larry = Knight.create(:name => 'Larry')
47
+
48
+ Dragon.create(:name => 'George', :is_fire_breathing => false, :toes_on_claw => 3, :birth_at => @birth_at, :birth_on => @birth_on, :birth_time => @birth_time, :knight => @chuck )
49
+ Dragon.create(:name => 'Puff', :is_fire_breathing => true, :toes_on_claw => 4, :birth_at => @birth_at, :birth_on => @birth_on, :birth_time => @birth_time, :knight => @larry )
50
+ Dragon.create(:name => nil, :is_fire_breathing => true, :toes_on_claw => 5, :birth_at => nil, :birth_on => nil, :birth_time => nil)
51
+
52
+ gold_kilo_price = 277738.70
53
+ @gold_tonne_price = gold_kilo_price * 10000
54
+
55
+ Country.create(:name => 'China',
56
+ :population => 1330044605,
57
+ :birth_rate => 13.71,
58
+ :gold_reserve_tonnes => 600.0,
59
+ :gold_reserve_value => 600.0 * @gold_tonne_price) # 32150000
60
+ Country.create(:name => 'United States',
61
+ :population => 303824646,
62
+ :birth_rate => 14.18,
63
+ :gold_reserve_tonnes => 8133.5,
64
+ :gold_reserve_value => 8133.5 * @gold_tonne_price)
65
+ Country.create(:name => 'Brazil',
66
+ :population => 191908598,
67
+ :birth_rate => 16.04,
68
+ :gold_reserve_tonnes => nil) # example of no stats available
69
+ Country.create(:name => 'Russia',
70
+ :population => 140702094,
71
+ :birth_rate => 11.03,
72
+ :gold_reserve_tonnes => 438.2,
73
+ :gold_reserve_value => 438.2 * @gold_tonne_price)
74
+ Country.create(:name => 'Japan',
75
+ :population => 127288419,
76
+ :birth_rate => 7.87,
77
+ :gold_reserve_tonnes => 765.2,
78
+ :gold_reserve_value => 765.2 * @gold_tonne_price)
79
+ Country.create(:name => 'Mexico',
80
+ :population => 109955400,
81
+ :birth_rate => 20.04,
82
+ :gold_reserve_tonnes => nil) # example of no stats available
83
+ Country.create(:name => 'Germany',
84
+ :population => 82369548,
85
+ :birth_rate => 8.18,
86
+ :gold_reserve_tonnes => 3417.4,
87
+ :gold_reserve_value => 3417.4 * @gold_tonne_price)
88
+
89
+ @approx_by = 0.000001
90
+ end
91
+ end
92
+
93
+ shared_examples_for 'An Aggregatable Class' do
94
+ describe '#size' do
95
+ it_should_behave_like 'count with no arguments'
96
+ end
97
+
98
+ describe '#count' do
99
+ it_should_behave_like 'count with no arguments'
100
+
101
+ describe 'with a property name' do
102
+ it 'should count the results' do
103
+ @dragons.count(:name).should == 2
104
+ end
105
+
106
+ it 'should count the results with conditions having operators' do
107
+ @dragons.count(:name, :toes_on_claw.gt => 3).should == 1
108
+ end
109
+
110
+ it 'should count the results with raw conditions' do
111
+ statement = 'is_fire_breathing = ?'
112
+ @dragons.count(:name, :conditions => [ statement, false ]).should == 1
113
+ @dragons.count(:name, :conditions => [ statement, true ]).should == 1
114
+ end
115
+ end
116
+ end
117
+
118
+ describe '#min' do
119
+ describe 'with no arguments' do
120
+ it 'should raise an error' do
121
+ lambda { @dragons.min }.should raise_error(ArgumentError)
122
+ end
123
+ end
124
+
125
+ describe 'with a property name' do
126
+ it 'should provide the lowest value of an Integer property' do
127
+ @dragons.min(:toes_on_claw).should == 3
128
+ @countries.min(:population).should == 82369548
129
+ end
130
+
131
+ it 'should provide the lowest value of a Float property' do
132
+ @countries.min(:birth_rate).should be_kind_of(Float)
133
+ @countries.min(:birth_rate).should >= 7.87 - @approx_by # approx match
134
+ @countries.min(:birth_rate).should <= 7.87 + @approx_by # approx match
135
+ end
136
+
137
+ it 'should provide the lowest value of a BigDecimal property' do
138
+ @countries.min(:gold_reserve_value).should be_kind_of(BigDecimal)
139
+ @countries.min(:gold_reserve_value).should == BigDecimal('1217050983400.0')
140
+ end
141
+
142
+ it 'should provide the lowest value of a DateTime property' do
143
+ @dragons.min(:birth_at).should be_kind_of(DateTime)
144
+ @dragons.min(:birth_at).to_s.should == @birth_at.to_s
145
+ end
146
+
147
+ it 'should provide the lowest value of a Date property' do
148
+ @dragons.min(:birth_on).should be_kind_of(Date)
149
+ @dragons.min(:birth_on).to_s.should == @birth_on.to_s
150
+ end
151
+
152
+ it 'should provide the lowest value of a Time property' do
153
+ @dragons.min(:birth_time).should be_kind_of(Time)
154
+ @dragons.min(:birth_time).to_s.should == @birth_time.to_s
155
+ end
156
+
157
+ it 'should provide the lowest value when conditions provided' do
158
+ @dragons.min(:toes_on_claw, :is_fire_breathing => true).should == 4
159
+ @dragons.min(:toes_on_claw, :is_fire_breathing => false).should == 3
160
+ end
161
+ end
162
+ end
163
+
164
+ describe '#max' do
165
+ describe 'with no arguments' do
166
+ it 'should raise an error' do
167
+ lambda { @dragons.max }.should raise_error(ArgumentError)
168
+ end
169
+ end
170
+
171
+ describe 'with a property name' do
172
+ it 'should provide the highest value of an Integer property' do
173
+ @dragons.max(:toes_on_claw).should == 5
174
+ @countries.max(:population).should == 1330044605
175
+ end
176
+
177
+ it 'should provide the highest value of a Float property' do
178
+ @countries.max(:birth_rate).should be_kind_of(Float)
179
+ @countries.max(:birth_rate).should >= 20.04 - @approx_by # approx match
180
+ @countries.max(:birth_rate).should <= 20.04 + @approx_by # approx match
181
+ end
182
+
183
+ it 'should provide the highest value of a BigDecimal property' do
184
+ @countries.max(:gold_reserve_value).should == BigDecimal('22589877164500.0')
185
+ end
186
+
187
+ it 'should provide the highest value of a DateTime property' do
188
+ @dragons.min(:birth_at).should be_kind_of(DateTime)
189
+ @dragons.min(:birth_at).to_s.should == @birth_at.to_s
190
+ end
191
+
192
+ it 'should provide the highest value of a Date property' do
193
+ @dragons.min(:birth_on).should be_kind_of(Date)
194
+ @dragons.min(:birth_on).to_s.should == @birth_on.to_s
195
+ end
196
+
197
+ it 'should provide the highest value of a Time property' do
198
+ @dragons.min(:birth_time).should be_kind_of(Time)
199
+ @dragons.min(:birth_time).to_s.should == @birth_time.to_s
200
+ end
201
+
202
+ it 'should provide the highest value when conditions provided' do
203
+ @dragons.max(:toes_on_claw, :is_fire_breathing => true).should == 5
204
+ @dragons.max(:toes_on_claw, :is_fire_breathing => false).should == 3
205
+ end
206
+ end
207
+ end
208
+
209
+ describe '#avg' do
210
+ describe 'with no arguments' do
211
+ it 'should raise an error' do
212
+ lambda { @dragons.avg }.should raise_error(ArgumentError)
213
+ end
214
+ end
215
+
216
+ describe 'with a property name' do
217
+ it 'should provide the average value of an Integer property' do
218
+ @dragons.avg(:toes_on_claw).should be_kind_of(Float)
219
+ @dragons.avg(:toes_on_claw).should == 4.0
220
+ end
221
+
222
+ it 'should provide the average value of a Float property' do
223
+ mean_birth_rate = (13.71 + 14.18 + 16.04 + 11.03 + 7.87 + 20.04 + 8.18) / 7
224
+ @countries.avg(:birth_rate).should be_kind_of(Float)
225
+ @countries.avg(:birth_rate).should >= mean_birth_rate - @approx_by # approx match
226
+ @countries.avg(:birth_rate).should <= mean_birth_rate + @approx_by # approx match
227
+ end
228
+
229
+ it 'should provide the average value of a BigDecimal property' do
230
+ mean_gold_reserve_value = ((600.0 + 8133.50 + 438.20 + 765.20 + 3417.40) * @gold_tonne_price) / 5
231
+ @countries.avg(:gold_reserve_value).should be_kind_of(BigDecimal)
232
+ @countries.avg(:gold_reserve_value).should == BigDecimal(mean_gold_reserve_value.to_s)
233
+ end
234
+
235
+ it 'should provide the average value when conditions provided' do
236
+ @dragons.avg(:toes_on_claw, :is_fire_breathing => true).should == 4.5
237
+ @dragons.avg(:toes_on_claw, :is_fire_breathing => false).should == 3
238
+ end
239
+ end
240
+ end
241
+
242
+ describe '#sum' do
243
+ describe 'with no arguments' do
244
+ it 'should raise an error' do
245
+ lambda { @dragons.sum }.should raise_error(ArgumentError)
246
+ end
247
+ end
248
+
249
+ describe 'with a property name' do
250
+ it 'should provide the sum of values for an Integer property' do
251
+ @dragons.sum(:toes_on_claw).should == 12
252
+
253
+ total_population = 1330044605 + 303824646 + 191908598 + 140702094 +
254
+ 127288419 + 109955400 + 82369548
255
+ @countries.sum(:population).should == total_population
256
+ end
257
+
258
+ it 'should provide the sum of values for a Float property' do
259
+ total_tonnes = 600.0 + 8133.5 + 438.2 + 765.2 + 3417.4
260
+ @countries.sum(:gold_reserve_tonnes).should be_kind_of(Float)
261
+ @countries.sum(:gold_reserve_tonnes).should >= total_tonnes - @approx_by # approx match
262
+ @countries.sum(:gold_reserve_tonnes).should <= total_tonnes + @approx_by # approx match
263
+ end
264
+
265
+ it 'should provide the sum of values for a BigDecimal property' do
266
+ @countries.sum(:gold_reserve_value).should == BigDecimal('37090059214100.0')
267
+ end
268
+
269
+ it 'should provide the average value when conditions provided' do
270
+ @dragons.sum(:toes_on_claw, :is_fire_breathing => true).should == 9
271
+ @dragons.sum(:toes_on_claw, :is_fire_breathing => false).should == 3
272
+ end
273
+ end
274
+ end
275
+
276
+ describe '#aggregate' do
277
+ describe 'with no arguments' do
278
+ it 'should raise an error' do
279
+ lambda { @dragons.aggregate }.should raise_error(ArgumentError)
280
+ end
281
+ end
282
+
283
+ describe 'with only aggregate fields specified' do
284
+ it 'should provide aggregate results' do
285
+ results = @dragons.aggregate(:all.count, :name.count, :toes_on_claw.min, :toes_on_claw.max, :toes_on_claw.avg, :toes_on_claw.sum)
286
+ results.should == [ 3, 2, 3, 5, 4.0, 12 ]
287
+ end
288
+ end
289
+
290
+ describe 'with aggregate fields and a property to group by' do
291
+ it 'should provide aggregate results' do
292
+ results = @dragons.aggregate(:all.count, :name.count, :toes_on_claw.min, :toes_on_claw.max, :toes_on_claw.avg, :toes_on_claw.sum, :is_fire_breathing)
293
+ results.should == [ [ 1, 1, 3, 3, 3.0, 3, false ], [ 2, 1, 4, 5, 4.5, 9, true ] ]
294
+ end
295
+ end
296
+ end
297
+
298
+ describe 'query path issue' do
299
+ it "should not break when a query path is specified" do
300
+ dragon = @dragons.first(Dragon.knight.name => 'Chuck')
301
+ dragon.name.should == 'George'
302
+ end
303
+ end
304
+ end
305
+
306
+ shared_examples_for 'count with no arguments' do
307
+ it 'should count the results' do
308
+ @dragons.count.should == 3
309
+
310
+ @countries.count.should == 7
311
+ end
312
+
313
+ it 'should count the results with conditions having operators' do
314
+ @dragons.count(:toes_on_claw.gt => 3).should == 2
315
+
316
+ @countries.count(:birth_rate.lt => 12).should == 3
317
+ @countries.count(:population.gt => 1000000000).should == 1
318
+ @countries.count(:population.gt => 2000000000).should == 0
319
+ @countries.count(:population.lt => 10).should == 0
320
+ end
321
+
322
+ it 'should count the results with raw conditions' do
323
+ dragon_statement = 'is_fire_breathing = ?'
324
+ @dragons.count(:conditions => [ dragon_statement, false ]).should == 1
325
+ @dragons.count(:conditions => [ dragon_statement, true ]).should == 2
326
+ end
327
+ end
data/spec/spec.opts CHANGED
@@ -1,2 +1 @@
1
- --format specdoc
2
1
  --colour
data/spec/spec_helper.rb CHANGED
@@ -1,20 +1,19 @@
1
- require 'rubygems'
2
1
  require 'pathname'
3
- require Pathname(__FILE__).dirname.expand_path.parent + 'lib/dm-aggregates'
2
+ require 'rubygems'
3
+
4
+ SPEC_ROOT = Pathname(__FILE__).dirname.expand_path
5
+ require SPEC_ROOT.parent + 'lib/dm-aggregates'
6
+ Pathname.glob((SPEC_ROOT + '{lib,*/shared}/**/*.rb').to_s).each { |f| require f }
4
7
 
5
8
  def load_driver(name, default_uri)
6
9
  return false if ENV['ADAPTER'] != name.to_s
7
10
 
8
- lib = "do_#{name}"
9
-
10
11
  begin
11
- gem lib, '~>0.9.7'
12
- require lib
13
12
  DataMapper.setup(name, ENV["#{name.to_s.upcase}_SPEC_URI"] || default_uri)
14
13
  DataMapper::Repository.adapters[:default] = DataMapper::Repository.adapters[name]
15
14
  true
16
- rescue Gem::LoadError => e
17
- warn "Could not load #{lib}: #{e}"
15
+ rescue LoadError => e
16
+ warn "Could not load do_#{name}: #{e}"
18
17
  false
19
18
  end
20
19
  end
data/tasks/install.rb ADDED
@@ -0,0 +1,13 @@
1
+ def sudo_gem(cmd)
2
+ sh "#{SUDO} #{RUBY} -S gem #{cmd}", :verbose => false
3
+ end
4
+
5
+ desc "Install #{GEM_NAME} #{GEM_VERSION}"
6
+ task :install => [ :package ] do
7
+ sudo_gem "install --local pkg/#{GEM_NAME}-#{GEM_VERSION} --no-update-sources"
8
+ end
9
+
10
+ desc "Uninstall #{GEM_NAME} #{GEM_VERSION}"
11
+ task :uninstall => [ :clobber ] do
12
+ sudo_gem "uninstall #{GEM_NAME} -v#{GEM_VERSION} -Ix"
13
+ end
data/tasks/spec.rb ADDED
@@ -0,0 +1,25 @@
1
+ begin
2
+ gem 'rspec', '~>1.1.11'
3
+ require 'spec'
4
+ require 'spec/rake/spectask'
5
+
6
+ task :default => [ :spec ]
7
+
8
+ desc 'Run specifications'
9
+ Spec::Rake::SpecTask.new(:spec) do |t|
10
+ t.spec_opts << '--options' << 'spec/spec.opts' if File.exists?('spec/spec.opts')
11
+ t.spec_files = Pathname.glob((ROOT + 'spec/**/*_spec.rb').to_s)
12
+
13
+ begin
14
+ gem 'rcov', '~>0.8'
15
+ t.rcov = JRUBY ? false : (ENV.has_key?('NO_RCOV') ? ENV['NO_RCOV'] != 'true' : true)
16
+ t.rcov_opts << '--exclude' << 'spec'
17
+ t.rcov_opts << '--text-summary'
18
+ t.rcov_opts << '--sort' << 'coverage' << '--sort-reverse'
19
+ rescue LoadError
20
+ # rcov not installed
21
+ end
22
+ end
23
+ rescue LoadError
24
+ # rspec not installed
25
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dm-aggregates
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.7
4
+ version: 0.9.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foy Savas
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-11-18 00:00:00 -08:00
12
+ date: 2008-12-07 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -18,23 +18,13 @@ dependencies:
18
18
  version_requirement:
19
19
  version_requirements: !ruby/object:Gem::Requirement
20
20
  requirements:
21
- - - "="
21
+ - - ~>
22
22
  - !ruby/object:Gem::Version
23
- version: 0.9.7
24
- version:
25
- - !ruby/object:Gem::Dependency
26
- name: hoe
27
- type: :development
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 1.8.2
23
+ version: 0.9.8
34
24
  version:
35
25
  description: DataMapper plugin providing support for aggregates, functions on collections and datasets
36
26
  email:
37
- - foysavas@gmail.com
27
+ - foysavas [a] gmail [d] com
38
28
  executables: []
39
29
 
40
30
  extensions: []
@@ -43,6 +33,7 @@ extra_rdoc_files:
43
33
  - README.txt
44
34
  - LICENSE
45
35
  - TODO
36
+ - History.txt
46
37
  files:
47
38
  - History.txt
48
39
  - LICENSE
@@ -58,9 +49,13 @@ files:
58
49
  - lib/dm-aggregates/repository.rb
59
50
  - lib/dm-aggregates/support/symbol.rb
60
51
  - lib/dm-aggregates/version.rb
61
- - spec/integration/aggregates_spec.rb
52
+ - spec/public/collection_spec.rb
53
+ - spec/public/model_spec.rb
54
+ - spec/public/shared/aggregate_shared_spec.rb
62
55
  - spec/spec.opts
63
56
  - spec/spec_helper.rb
57
+ - tasks/install.rb
58
+ - tasks/spec.rb
64
59
  has_rdoc: true
65
60
  homepage: http://github.com/sam/dm-more/tree/master/dm-aggregates
66
61
  post_install_message:
@@ -1,330 +0,0 @@
1
- require 'pathname'
2
- require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
3
-
4
- if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
5
- describe 'DataMapper::Resource' do
6
- before :all do
7
- # A simplistic example, using with an Integer property
8
- class Knight
9
- include DataMapper::Resource
10
-
11
- property :id, Serial
12
- property :name, String
13
- end
14
-
15
- class Dragon
16
- include DataMapper::Resource
17
-
18
- property :id, Serial
19
- property :name, String
20
- property :is_fire_breathing, TrueClass
21
- property :toes_on_claw, Integer
22
- property :birth_at, DateTime
23
- property :birth_on, Date
24
- property :birth_time, Time
25
-
26
- belongs_to :knight
27
- end
28
-
29
- # A more complex example, with BigDecimal and Float properties
30
- # Statistics taken from CIA World Factbook:
31
- # https://www.cia.gov/library/publications/the-world-factbook/
32
- class Country
33
- include DataMapper::Resource
34
-
35
- property :id, Serial
36
- property :name, String, :nullable => false
37
- property :population, Integer
38
- property :birth_rate, Float, :precision => 4, :scale => 2
39
- property :gold_reserve_tonnes, Float, :precision => 6, :scale => 2
40
- property :gold_reserve_value, BigDecimal, :precision => 15, :scale => 1 # approx. value in USD
41
- end
42
-
43
- [ Dragon, Country, Knight ].each { |m| m.auto_migrate! }
44
-
45
- @birth_at = DateTime.now
46
- @birth_on = Date.parse(@birth_at.to_s)
47
- @birth_time = Time.parse(@birth_at.to_s)
48
-
49
- @chuck = Knight.create(:name => 'Chuck')
50
- @larry = Knight.create(:name => 'Larry')
51
-
52
- Dragon.create(:name => 'George', :is_fire_breathing => false, :toes_on_claw => 3, :birth_at => @birth_at, :birth_on => @birth_on, :birth_time => @birth_time, :knight => @chuck )
53
- Dragon.create(:name => 'Puff', :is_fire_breathing => true, :toes_on_claw => 4, :birth_at => @birth_at, :birth_on => @birth_on, :birth_time => @birth_time, :knight => @larry )
54
- Dragon.create(:name => nil, :is_fire_breathing => true, :toes_on_claw => 5, :birth_at => nil, :birth_on => nil, :birth_time => nil)
55
-
56
- gold_kilo_price = 277738.70
57
- @gold_tonne_price = gold_kilo_price * 10000
58
-
59
- Country.create(:name => 'China',
60
- :population => 1330044605,
61
- :birth_rate => 13.71,
62
- :gold_reserve_tonnes => 600.0,
63
- :gold_reserve_value => 600.0 * @gold_tonne_price) # 32150000
64
- Country.create(:name => 'United States',
65
- :population => 303824646,
66
- :birth_rate => 14.18,
67
- :gold_reserve_tonnes => 8133.5,
68
- :gold_reserve_value => 8133.5 * @gold_tonne_price)
69
- Country.create(:name => 'Brazil',
70
- :population => 191908598,
71
- :birth_rate => 16.04,
72
- :gold_reserve_tonnes => nil) # example of no stats available
73
- Country.create(:name => 'Russia',
74
- :population => 140702094,
75
- :birth_rate => 11.03,
76
- :gold_reserve_tonnes => 438.2,
77
- :gold_reserve_value => 438.2 * @gold_tonne_price)
78
- Country.create(:name => 'Japan',
79
- :population => 127288419,
80
- :birth_rate => 7.87,
81
- :gold_reserve_tonnes => 765.2,
82
- :gold_reserve_value => 765.2 * @gold_tonne_price)
83
- Country.create(:name => 'Mexico',
84
- :population => 109955400,
85
- :birth_rate => 20.04,
86
- :gold_reserve_tonnes => nil) # example of no stats available
87
- Country.create(:name => 'Germany',
88
- :population => 82369548,
89
- :birth_rate => 8.18,
90
- :gold_reserve_tonnes => 3417.4,
91
- :gold_reserve_value => 3417.4 * @gold_tonne_price)
92
-
93
- @approx_by = 0.000001
94
- end
95
-
96
- def target(klass, target_type)
97
- target_type == :collection ? klass.all : klass
98
- end
99
-
100
- [ :model, :collection ].each do |target_type|
101
- describe ".count on a #{target_type}" do
102
- describe 'with no arguments' do
103
- it 'should count the results' do
104
- target(Dragon, target_type).count.should == 3
105
-
106
- target(Country, target_type).count.should == 7
107
- end
108
-
109
- it 'should count the results with conditions having operators' do
110
- target(Dragon, target_type).count(:toes_on_claw.gt => 3).should == 2
111
-
112
- target(Country, target_type).count(:birth_rate.lt => 12).should == 3
113
- target(Country, target_type).count(:population.gt => 1000000000).should == 1
114
- target(Country, target_type).count(:population.gt => 2000000000).should == 0
115
- target(Country, target_type).count(:population.lt => 10).should == 0
116
- end
117
-
118
- it 'should count the results with raw conditions' do
119
- dragon_statement = 'is_fire_breathing = ?'
120
- target(Dragon, target_type).count(:conditions => [ dragon_statement, false ]).should == 1
121
- target(Dragon, target_type).count(:conditions => [ dragon_statement, true ]).should == 2
122
- end
123
- end
124
-
125
- describe 'with a property name' do
126
- it 'should count the results' do
127
- target(Dragon, target_type).count(:name).should == 2
128
- end
129
-
130
- it 'should count the results with conditions having operators' do
131
- target(Dragon, target_type).count(:name, :toes_on_claw.gt => 3).should == 1
132
- end
133
-
134
- it 'should count the results with raw conditions' do
135
- statement = 'is_fire_breathing = ?'
136
- target(Dragon, target_type).count(:name, :conditions => [ statement, false ]).should == 1
137
- target(Dragon, target_type).count(:name, :conditions => [ statement, true ]).should == 1
138
- end
139
- end
140
- end
141
-
142
- describe ".min on a #{target_type}" do
143
- describe 'with no arguments' do
144
- it 'should raise an error' do
145
- lambda { target(Dragon, target_type).min }.should raise_error(ArgumentError)
146
- end
147
- end
148
-
149
- describe 'with a property name' do
150
- it 'should provide the lowest value of an Integer property' do
151
- target(Dragon, target_type).min(:toes_on_claw).should == 3
152
- target(Country, target_type).min(:population).should == 82369548
153
- end
154
-
155
- it 'should provide the lowest value of a Float property' do
156
- target(Country, target_type).min(:birth_rate).should be_kind_of(Float)
157
- target(Country, target_type).min(:birth_rate).should >= 7.87 - @approx_by # approx match
158
- target(Country, target_type).min(:birth_rate).should <= 7.87 + @approx_by # approx match
159
- end
160
-
161
- it 'should provide the lowest value of a BigDecimal property' do
162
- target(Country, target_type).min(:gold_reserve_value).should be_kind_of(BigDecimal)
163
- target(Country, target_type).min(:gold_reserve_value).should == BigDecimal('1217050983400.0')
164
- end
165
-
166
- it 'should provide the lowest value of a DateTime property' do
167
- target(Dragon, target_type).min(:birth_at).should be_kind_of(DateTime)
168
- target(Dragon, target_type).min(:birth_at).to_s.should == @birth_at.to_s
169
- end
170
-
171
- it 'should provide the lowest value of a Date property' do
172
- target(Dragon, target_type).min(:birth_on).should be_kind_of(Date)
173
- target(Dragon, target_type).min(:birth_on).to_s.should == @birth_on.to_s
174
- end
175
-
176
- it 'should provide the lowest value of a Time property' do
177
- target(Dragon, target_type).min(:birth_time).should be_kind_of(Time)
178
- target(Dragon, target_type).min(:birth_time).to_s.should == @birth_time.to_s
179
- end
180
-
181
- it 'should provide the lowest value when conditions provided' do
182
- target(Dragon, target_type).min(:toes_on_claw, :is_fire_breathing => true).should == 4
183
- target(Dragon, target_type).min(:toes_on_claw, :is_fire_breathing => false).should == 3
184
- end
185
- end
186
- end
187
-
188
- describe ".max on a #{target_type}" do
189
- describe 'with no arguments' do
190
- it 'should raise an error' do
191
- lambda { target(Dragon, target_type).max }.should raise_error(ArgumentError)
192
- end
193
- end
194
-
195
- describe 'with a property name' do
196
- it 'should provide the highest value of an Integer property' do
197
- target(Dragon, target_type).max(:toes_on_claw).should == 5
198
- target(Country, target_type).max(:population).should == 1330044605
199
- end
200
-
201
- it 'should provide the highest value of a Float property' do
202
- target(Country, target_type).max(:birth_rate).should be_kind_of(Float)
203
- target(Country, target_type).max(:birth_rate).should >= 20.04 - @approx_by # approx match
204
- target(Country, target_type).max(:birth_rate).should <= 20.04 + @approx_by # approx match
205
- end
206
-
207
- it 'should provide the highest value of a BigDecimal property' do
208
- target(Country, target_type).max(:gold_reserve_value).should == BigDecimal('22589877164500.0')
209
- end
210
-
211
- it 'should provide the highest value of a DateTime property' do
212
- target(Dragon, target_type).min(:birth_at).should be_kind_of(DateTime)
213
- target(Dragon, target_type).min(:birth_at).to_s.should == @birth_at.to_s
214
- end
215
-
216
- it 'should provide the highest value of a Date property' do
217
- target(Dragon, target_type).min(:birth_on).should be_kind_of(Date)
218
- target(Dragon, target_type).min(:birth_on).to_s.should == @birth_on.to_s
219
- end
220
-
221
- it 'should provide the highest value of a Time property' do
222
- target(Dragon, target_type).min(:birth_time).should be_kind_of(Time)
223
- target(Dragon, target_type).min(:birth_time).to_s.should == @birth_time.to_s
224
- end
225
-
226
- it 'should provide the highest value when conditions provided' do
227
- target(Dragon, target_type).max(:toes_on_claw, :is_fire_breathing => true).should == 5
228
- target(Dragon, target_type).max(:toes_on_claw, :is_fire_breathing => false).should == 3
229
- end
230
- end
231
- end
232
-
233
- describe ".avg on a #{target_type}" do
234
- describe 'with no arguments' do
235
- it 'should raise an error' do
236
- lambda { target(Dragon, target_type).avg }.should raise_error(ArgumentError)
237
- end
238
- end
239
-
240
- describe 'with a property name' do
241
- it 'should provide the average value of an Integer property' do
242
- target(Dragon, target_type).avg(:toes_on_claw).should be_kind_of(Float)
243
- target(Dragon, target_type).avg(:toes_on_claw).should == 4.0
244
- end
245
-
246
- it 'should provide the average value of a Float property' do
247
- mean_birth_rate = (13.71 + 14.18 + 16.04 + 11.03 + 7.87 + 20.04 + 8.18) / 7
248
- target(Country, target_type).avg(:birth_rate).should be_kind_of(Float)
249
- target(Country, target_type).avg(:birth_rate).should >= mean_birth_rate - @approx_by # approx match
250
- target(Country, target_type).avg(:birth_rate).should <= mean_birth_rate + @approx_by # approx match
251
- end
252
-
253
- it 'should provide the average value of a BigDecimal property' do
254
- mean_gold_reserve_value = ((600.0 + 8133.50 + 438.20 + 765.20 + 3417.40) * @gold_tonne_price) / 5
255
- target(Country, target_type).avg(:gold_reserve_value).should be_kind_of(BigDecimal)
256
- target(Country, target_type).avg(:gold_reserve_value).should == BigDecimal(mean_gold_reserve_value.to_s)
257
- end
258
-
259
- it 'should provide the average value when conditions provided' do
260
- target(Dragon, target_type).avg(:toes_on_claw, :is_fire_breathing => true).should == 4.5
261
- target(Dragon, target_type).avg(:toes_on_claw, :is_fire_breathing => false).should == 3
262
- end
263
- end
264
- end
265
-
266
- describe ".sum on a #{target_type}" do
267
- describe 'with no arguments' do
268
- it 'should raise an error' do
269
- lambda { target(Dragon, target_type).sum }.should raise_error(ArgumentError)
270
- end
271
- end
272
-
273
- describe 'with a property name' do
274
- it 'should provide the sum of values for an Integer property' do
275
- target(Dragon, target_type).sum(:toes_on_claw).should == 12
276
-
277
- total_population = 1330044605 + 303824646 + 191908598 + 140702094 +
278
- 127288419 + 109955400 + 82369548
279
- target(Country, target_type).sum(:population).should == total_population
280
- end
281
-
282
- it 'should provide the sum of values for a Float property' do
283
- total_tonnes = 600.0 + 8133.5 + 438.2 + 765.2 + 3417.4
284
- target(Country, target_type).sum(:gold_reserve_tonnes).should be_kind_of(Float)
285
- target(Country, target_type).sum(:gold_reserve_tonnes).should >= total_tonnes - @approx_by # approx match
286
- target(Country, target_type).sum(:gold_reserve_tonnes).should <= total_tonnes + @approx_by # approx match
287
- end
288
-
289
- it 'should provide the sum of values for a BigDecimal property' do
290
- target(Country, target_type).sum(:gold_reserve_value).should == BigDecimal('37090059214100.0')
291
- end
292
-
293
- it 'should provide the average value when conditions provided' do
294
- target(Dragon, target_type).sum(:toes_on_claw, :is_fire_breathing => true).should == 9
295
- target(Dragon, target_type).sum(:toes_on_claw, :is_fire_breathing => false).should == 3
296
- end
297
- end
298
- end
299
-
300
- describe ".aggregate on a #{target_type}" do
301
- describe 'with no arguments' do
302
- it 'should raise an error' do
303
- lambda { target(Dragon, target_type).aggregate }.should raise_error(ArgumentError)
304
- end
305
- end
306
-
307
- describe 'with only aggregate fields specified' do
308
- it 'should provide aggregate results' do
309
- results = target(Dragon, target_type).aggregate(:all.count, :name.count, :toes_on_claw.min, :toes_on_claw.max, :toes_on_claw.avg, :toes_on_claw.sum)
310
- results.should == [ 3, 2, 3, 5, 4.0, 12 ]
311
- end
312
- end
313
-
314
- describe 'with aggregate fields and a property to group by' do
315
- it 'should provide aggregate results' do
316
- results = target(Dragon, target_type).aggregate(:all.count, :name.count, :toes_on_claw.min, :toes_on_claw.max, :toes_on_claw.avg, :toes_on_claw.sum, :is_fire_breathing)
317
- results.should == [ [ 1, 1, 3, 3, 3.0, 3, false ], [ 2, 1, 4, 5, 4.5, 9, true ] ]
318
- end
319
- end
320
- end
321
-
322
- describe "query path issue" do
323
- it "should not break when a query path is specified" do
324
- dragon = Dragon.first(Dragon.knight.name => 'Chuck')
325
- dragon.name.should == 'George'
326
- end
327
- end
328
- end
329
- end
330
- end