dm-aggregates 0.9.7 → 0.9.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/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