dm-aggregates 0.9.11 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,7 @@
1
+ === 0.10.0 / 2009-10-15
2
+
3
+ * Updated to work with dm-core 0.10.0
4
+
1
5
  === 0.9.11 / 2009-03-29
2
6
 
3
7
  * No changes this version
data/Manifest.txt CHANGED
@@ -1,16 +1,17 @@
1
- History.txt
1
+ History.rdoc
2
2
  LICENSE
3
3
  Manifest.txt
4
- README.txt
4
+ README.rdoc
5
5
  Rakefile
6
6
  TODO
7
7
  lib/dm-aggregates.rb
8
8
  lib/dm-aggregates/adapters/data_objects_adapter.rb
9
9
  lib/dm-aggregates/aggregate_functions.rb
10
10
  lib/dm-aggregates/collection.rb
11
+ lib/dm-aggregates/core_ext/symbol.rb
11
12
  lib/dm-aggregates/model.rb
13
+ lib/dm-aggregates/query.rb
12
14
  lib/dm-aggregates/repository.rb
13
- lib/dm-aggregates/support/symbol.rb
14
15
  lib/dm-aggregates/version.rb
15
16
  spec/public/collection_spec.rb
16
17
  spec/public/model_spec.rb
File without changes
data/Rakefile CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'pathname'
2
- require 'rubygems'
3
2
 
4
3
  ROOT = Pathname(__FILE__).dirname.expand_path
5
4
  JRUBY = RUBY_PLATFORM =~ /java/
@@ -14,10 +13,10 @@ GEM_NAME = 'dm-aggregates'
14
13
  GEM_VERSION = DataMapper::Aggregates::VERSION
15
14
  GEM_DEPENDENCIES = [['dm-core', GEM_VERSION]]
16
15
  GEM_CLEAN = %w[ log pkg coverage ]
17
- GEM_EXTRAS = { :has_rdoc => true, :extra_rdoc_files => %w[ README.txt LICENSE TODO History.txt ] }
16
+ GEM_EXTRAS = { :has_rdoc => true, :extra_rdoc_files => %w[ README.rdoc LICENSE TODO History.rdoc ] }
18
17
 
19
18
  PROJECT_NAME = 'datamapper'
20
- PROJECT_URL = "http://github.com/sam/dm-more/tree/master/#{GEM_NAME}"
19
+ PROJECT_URL = "http://github.com/datamapper/dm-more/tree/master/#{GEM_NAME}"
21
20
  PROJECT_DESCRIPTION = PROJECT_SUMMARY = 'DataMapper plugin providing support for aggregates, functions on collections and datasets'
22
21
 
23
22
  [ ROOT, ROOT.parent ].each do |dir|
@@ -1,24 +1,44 @@
1
1
  module DataMapper
2
- module Adapters
3
- class DataObjectsAdapter
2
+ module Aggregates
3
+ module DataObjectsAdapter
4
+ def self.included(base)
5
+ base.send(:include, SQL)
6
+ end
7
+
4
8
  def aggregate(query)
5
- with_reader(read_statement(query), query.bind_values) do |reader|
6
- results = []
7
-
8
- while(reader.next!) do
9
- row = query.fields.zip(reader.values).map do |field,value|
10
- if field.respond_to?(:operator)
11
- send(field.operator, field.target, value)
12
- else
13
- field.typecast(value)
9
+ fields = query.fields
10
+ types = fields.map { |p| p.respond_to?(:operator) ? String : p.primitive }
11
+
12
+ field_size = fields.size
13
+
14
+ records = []
15
+
16
+ with_connection do |connection|
17
+ statement, bind_values = select_statement(query)
18
+
19
+ command = connection.create_command(statement)
20
+ command.set_types(types)
21
+
22
+ reader = command.execute_reader(*bind_values)
23
+
24
+ begin
25
+ while(reader.next!)
26
+ row = fields.zip(reader.values).map do |field, value|
27
+ if field.respond_to?(:operator)
28
+ send(field.operator, field.target, value)
29
+ else
30
+ field.typecast(value)
31
+ end
14
32
  end
15
- end
16
33
 
17
- results << (query.fields.size > 1 ? row : row[0])
34
+ records << (field_size > 1 ? row : row[0])
35
+ end
36
+ ensure
37
+ reader.close
18
38
  end
19
-
20
- results
21
39
  end
40
+
41
+ records
22
42
  end
23
43
 
24
44
  private
@@ -44,26 +64,32 @@ module DataMapper
44
64
  end
45
65
 
46
66
  module SQL
47
- private
48
-
49
- alias original_property_to_column_name property_to_column_name
67
+ def self.included(base)
68
+ base.class_eval <<-RUBY, __FILE__, __LINE__ + 1
69
+ # FIXME: figure out a cleaner approach than AMC
70
+ alias property_to_column_name_without_operator property_to_column_name
71
+ alias property_to_column_name property_to_column_name_with_operator
72
+ RUBY
73
+ end
50
74
 
51
- def property_to_column_name(repository, property, qualify)
75
+ def property_to_column_name_with_operator(property, qualify)
52
76
  case property
53
- when Query::Operator
54
- aggregate_field_statement(repository, property.operator, property.target, qualify)
55
- when Property, Query::Path
56
- original_property_to_column_name(repository, property, qualify)
77
+ when DataMapper::Query::Operator
78
+ aggregate_field_statement(property.operator, property.target, qualify)
79
+
80
+ when Property, DataMapper::Query::Path
81
+ property_to_column_name_without_operator(property, qualify)
82
+
57
83
  else
58
84
  raise ArgumentError, "+property+ must be a DataMapper::Query::Operator, a DataMapper::Property or a Query::Path, but was a #{property.class} (#{property.inspect})"
59
85
  end
60
86
  end
61
87
 
62
- def aggregate_field_statement(repository, aggregate_function, property, qualify)
88
+ def aggregate_field_statement(aggregate_function, property, qualify)
63
89
  column_name = if aggregate_function == :count && property == :all
64
90
  '*'
65
91
  else
66
- property_to_column_name(repository, property, qualify)
92
+ property_to_column_name(property, qualify)
67
93
  end
68
94
 
69
95
  function_name = case aggregate_function
@@ -78,8 +104,22 @@ module DataMapper
78
104
  "#{function_name}(#{column_name})"
79
105
  end
80
106
  end # module SQL
81
-
82
- include SQL
83
107
  end # class DataObjectsAdapter
108
+ end # module Aggregates
109
+
110
+ module Adapters
111
+ extendable do
112
+
113
+ # TODO: document
114
+ # @api private
115
+ def const_added(const_name)
116
+ if DataMapper::Aggregates.const_defined?(const_name)
117
+ adapter = const_get(const_name)
118
+ adapter.send(:include, DataMapper::Aggregates.const_get(const_name))
119
+ end
120
+
121
+ super
122
+ end
123
+ end
84
124
  end # module Adapters
85
125
  end # module DataMapper
@@ -1,200 +1,203 @@
1
1
  module DataMapper
2
- module AggregateFunctions
3
- # Count results (given the conditions)
4
- #
5
- # @example the count of all friends
6
- # Friend.count
7
- #
8
- # @example the count of all friends older then 18
9
- # Friend.count(:age.gt => 18)
10
- #
11
- # @example the count of all your female friends
12
- # Friend.count(:conditions => [ 'gender = ?', 'female' ])
13
- #
14
- # @example the count of all friends with an address (NULL values are not included)
15
- # Friend.count(:address)
16
- #
17
- # @example the count of all friends with an address that are older then 18
18
- # Friend.count(:address, :age.gt => 18)
19
- #
20
- # @example the count of all your female friends with an address
21
- # Friend.count(:address, :conditions => [ 'gender = ?', 'female' ])
22
- #
23
- # @param property [Symbol] of the property you with to count (optional)
24
- # @param opts [Hash, Symbol] the conditions
25
- #
26
- # @return [Integer] return the count given the conditions
27
- #
28
- # @api public
29
- def count(*args)
30
- query = args.last.kind_of?(Hash) ? args.pop : {}
31
- property_name = args.first
32
-
33
- if property_name
34
- assert_kind_of 'property', property_by_name(property_name), Property
2
+ module Aggregates
3
+ module Functions
4
+ # Count results (given the conditions)
5
+ #
6
+ # @example the count of all friends
7
+ # Friend.count
8
+ #
9
+ # @example the count of all friends older then 18
10
+ # Friend.count(:age.gt => 18)
11
+ #
12
+ # @example the count of all your female friends
13
+ # Friend.count(:conditions => [ 'gender = ?', 'female' ])
14
+ #
15
+ # @example the count of all friends with an address (NULL values are not included)
16
+ # Friend.count(:address)
17
+ #
18
+ # @example the count of all friends with an address that are older then 18
19
+ # Friend.count(:address, :age.gt => 18)
20
+ #
21
+ # @example the count of all your female friends with an address
22
+ # Friend.count(:address, :conditions => [ 'gender = ?', 'female' ])
23
+ #
24
+ # @param property [Symbol] of the property you with to count (optional)
25
+ # @param opts [Hash, Symbol] the conditions
26
+ #
27
+ # @return [Integer] return the count given the conditions
28
+ #
29
+ # @api public
30
+ def count(*args)
31
+ query = args.last.kind_of?(Hash) ? args.pop : {}
32
+ property_name = args.first
33
+
34
+ if property_name
35
+ assert_kind_of 'property', property_by_name(property_name), Property
36
+ end
37
+
38
+ aggregate(query.merge(:fields => [ property_name ? property_name.count : :all.count ]))
35
39
  end
36
40
 
37
- aggregate(query.merge(:fields => [ property_name ? property_name.count : :all.count ]))
38
- end
39
-
40
- # Get the lowest value of a property
41
- #
42
- # @example the age of the youngest friend
43
- # Friend.min(:age)
44
- #
45
- # @example the age of the youngest female friend
46
- # Friend.min(:age, :conditions => [ 'gender = ?', 'female' ])
47
- #
48
- # @param property [Symbol] the property you wish to get the lowest value of
49
- # @param opts [Hash, Symbol] the conditions
50
- #
51
- # @return [Integer] return the lowest value of a property given the conditions
52
- #
53
- # @api public
54
- def min(*args)
55
- query = args.last.kind_of?(Hash) ? args.pop : {}
56
- property_name = args.first
57
-
58
- assert_property_type property_name, Integer, Float, BigDecimal, DateTime, Date, Time
59
-
60
- aggregate(query.merge(:fields => [ property_name.min ]))
61
- end
41
+ # Get the lowest value of a property
42
+ #
43
+ # @example the age of the youngest friend
44
+ # Friend.min(:age)
45
+ #
46
+ # @example the age of the youngest female friend
47
+ # Friend.min(:age, :conditions => [ 'gender = ?', 'female' ])
48
+ #
49
+ # @param property [Symbol] the property you wish to get the lowest value of
50
+ # @param opts [Hash, Symbol] the conditions
51
+ #
52
+ # @return [Integer] return the lowest value of a property given the conditions
53
+ #
54
+ # @api public
55
+ def min(*args)
56
+ query = args.last.kind_of?(Hash) ? args.pop : {}
57
+ property_name = args.first
58
+
59
+ assert_property_type property_name, Integer, Float, BigDecimal, DateTime, Date, Time
60
+
61
+ aggregate(query.merge(:fields => [ property_name.min ]))
62
+ end
62
63
 
63
- # Get the highest value of a property
64
- #
65
- # @example the age of the oldest friend
66
- # Friend.max(:age)
67
- #
68
- # @example the age of the oldest female friend
69
- # Friend.max(:age, :conditions => [ 'gender = ?', 'female' ])
70
- #
71
- # @param property [Symbol] the property you wish to get the highest value of
72
- # @param opts [Hash, Symbol] the conditions
73
- #
74
- # @return [Integer] return the highest value of a property given the conditions
75
- #
76
- # @api public
77
- def max(*args)
78
- query = args.last.kind_of?(Hash) ? args.pop : {}
79
- property_name = args.first
80
-
81
- assert_property_type property_name, Integer, Float, BigDecimal, DateTime, Date, Time
82
-
83
- aggregate(query.merge(:fields => [ property_name.max ]))
84
- end
64
+ # Get the highest value of a property
65
+ #
66
+ # @example the age of the oldest friend
67
+ # Friend.max(:age)
68
+ #
69
+ # @example the age of the oldest female friend
70
+ # Friend.max(:age, :conditions => [ 'gender = ?', 'female' ])
71
+ #
72
+ # @param property [Symbol] the property you wish to get the highest value of
73
+ # @param opts [Hash, Symbol] the conditions
74
+ #
75
+ # @return [Integer] return the highest value of a property given the conditions
76
+ #
77
+ # @api public
78
+ def max(*args)
79
+ query = args.last.kind_of?(Hash) ? args.pop : {}
80
+ property_name = args.first
81
+
82
+ assert_property_type property_name, Integer, Float, BigDecimal, DateTime, Date, Time
83
+
84
+ aggregate(query.merge(:fields => [ property_name.max ]))
85
+ end
85
86
 
86
- # Get the average value of a property
87
- #
88
- # @example the average age of all friends
89
- # Friend.avg(:age)
90
- #
91
- # @example the average age of all female friends
92
- # Friend.avg(:age, :conditions => [ 'gender = ?', 'female' ])
93
- #
94
- # @param property [Symbol] the property you wish to get the average value of
95
- # @param opts [Hash, Symbol] the conditions
96
- #
97
- # @return [Integer] return the average value of a property given the conditions
98
- #
99
- # @api public
100
- def avg(*args)
101
- query = args.last.kind_of?(Hash) ? args.pop : {}
102
- property_name = args.first
103
-
104
- assert_property_type property_name, Integer, Float, BigDecimal
105
-
106
- aggregate(query.merge(:fields => [ property_name.avg ]))
107
- end
87
+ # Get the average value of a property
88
+ #
89
+ # @example the average age of all friends
90
+ # Friend.avg(:age)
91
+ #
92
+ # @example the average age of all female friends
93
+ # Friend.avg(:age, :conditions => [ 'gender = ?', 'female' ])
94
+ #
95
+ # @param property [Symbol] the property you wish to get the average value of
96
+ # @param opts [Hash, Symbol] the conditions
97
+ #
98
+ # @return [Integer] return the average value of a property given the conditions
99
+ #
100
+ # @api public
101
+ def avg(*args)
102
+ query = args.last.kind_of?(Hash) ? args.pop : {}
103
+ property_name = args.first
104
+
105
+ assert_property_type property_name, Integer, Float, BigDecimal
106
+
107
+ aggregate(query.merge(:fields => [ property_name.avg ]))
108
+ end
108
109
 
109
- # Get the total value of a property
110
- #
111
- # @example the total age of all friends
112
- # Friend.sum(:age)
113
- #
114
- # @example the total age of all female friends
115
- # Friend.max(:age, :conditions => [ 'gender = ?', 'female' ])
116
- #
117
- # @param property [Symbol] the property you wish to get the total value of
118
- # @param opts [Hash, Symbol] the conditions
119
- #
120
- # @return [Integer] return the total value of a property given the conditions
121
- #
122
- # @api public
123
- def sum(*args)
124
- query = args.last.kind_of?(Hash) ? args.pop : {}
125
- property_name = args.first
126
-
127
- assert_property_type property_name, Integer, Float, BigDecimal
128
-
129
- aggregate(query.merge(:fields => [ property_name.sum ]))
130
- end
110
+ # Get the total value of a property
111
+ #
112
+ # @example the total age of all friends
113
+ # Friend.sum(:age)
114
+ #
115
+ # @example the total age of all female friends
116
+ # Friend.max(:age, :conditions => [ 'gender = ?', 'female' ])
117
+ #
118
+ # @param property [Symbol] the property you wish to get the total value of
119
+ # @param opts [Hash, Symbol] the conditions
120
+ #
121
+ # @return [Integer] return the total value of a property given the conditions
122
+ #
123
+ # @api public
124
+ def sum(*args)
125
+ query = args.last.kind_of?(Hash) ? args.pop : {}
126
+ property_name = args.first
127
+
128
+ assert_property_type property_name, Integer, Float, BigDecimal
129
+
130
+ aggregate(query.merge(:fields => [ property_name.sum ]))
131
+ end
131
132
 
132
- # Perform aggregate queries
133
- #
134
- # @example the count of friends
135
- # Friend.aggregate(:all.count)
136
- #
137
- # @example the minimum age, the maximum age and the total age of friends
138
- # Friend.aggregate(:age.min, :age.max, :age.sum)
139
- #
140
- # @example the average age, grouped by gender
141
- # Friend.aggregate(:age.avg, :fields => [ :gender ])
142
- #
143
- # @param aggregates [Symbol, ...] operators to aggregate with
144
- # @params query [Hash] the conditions
145
- #
146
- # @return [Array,Numeric,DateTime,Date,Time] the results of the
147
- # aggregate query
148
- #
149
- # @api public
150
- def aggregate(*args)
151
- query = args.last.kind_of?(Hash) ? args.pop : {}
152
-
153
- query[:fields] ||= []
154
- query[:fields] |= args
155
- query[:fields].map! { |f| normalize_field(f) }
156
- query[:order] ||= query[:fields].select { |p| p.kind_of?(Property) }
157
-
158
- raise ArgumentError, 'query[:fields] must not be empty' if query[:fields].empty?
159
-
160
- query = scoped_query(query)
161
-
162
- if query.fields.any? { |p| p.kind_of?(Property) }
163
- # explicitly specify the fields to circumvent a bug in Query#update
164
- query.repository.aggregate(query.update(:fields => query.fields, :unique => true))
165
- else
166
- query.repository.aggregate(query).first # only return one row
133
+ # Perform aggregate queries
134
+ #
135
+ # @example the count of friends
136
+ # Friend.aggregate(:all.count)
137
+ #
138
+ # @example the minimum age, the maximum age and the total age of friends
139
+ # Friend.aggregate(:age.min, :age.max, :age.sum)
140
+ #
141
+ # @example the average age, grouped by gender
142
+ # Friend.aggregate(:age.avg, :fields => [ :gender ])
143
+ #
144
+ # @param aggregates [Symbol, ...] operators to aggregate with
145
+ # @params query [Hash] the conditions
146
+ #
147
+ # @return [Array,Numeric,DateTime,Date,Time] the results of the
148
+ # aggregate query
149
+ #
150
+ # @api public
151
+ def aggregate(*args)
152
+ query = args.last.kind_of?(Hash) ? args.pop : {}
153
+
154
+ query[:fields] ||= []
155
+ query[:fields] |= args
156
+ query[:fields].map! { |f| normalize_field(f) }
157
+ query[:order] ||= query[:fields].select { |p| p.kind_of?(Property) }
158
+
159
+ raise ArgumentError, 'query[:fields] must not be empty' if query[:fields].empty?
160
+
161
+ query = scoped_query(query)
162
+
163
+ if query.fields.any? { |p| p.kind_of?(Property) }
164
+ query.repository.aggregate(query.update(:unique => true))
165
+ else
166
+ query.repository.aggregate(query).first # only return one row
167
+ end
167
168
  end
168
- end
169
169
 
170
- private
170
+ private
171
171
 
172
- def assert_property_type(name, *types)
173
- if name.nil?
174
- raise ArgumentError, 'property name must not be nil'
175
- end
172
+ def assert_property_type(name, *types)
173
+ if name.nil?
174
+ raise ArgumentError, 'property name must not be nil'
175
+ end
176
176
 
177
- type = property_by_name(name).type
177
+ type = property_by_name(name).type
178
178
 
179
- unless types.include?(type)
180
- raise ArgumentError, "#{name} must be #{types * ' or '}, but was #{type}"
179
+ unless types.include?(type)
180
+ raise ArgumentError, "#{name} must be #{types * ' or '}, but was #{type}"
181
+ end
181
182
  end
182
- end
183
183
 
184
- def normalize_field(field)
185
- assert_kind_of 'field', field, Query::Operator, Symbol, Property
184
+ def normalize_field(field)
185
+ assert_kind_of 'field', field, DataMapper::Query::Operator, Symbol, Property
186
+
187
+ case field
188
+ when DataMapper::Query::Operator
189
+ if field.target == :all
190
+ field
191
+ else
192
+ field.class.new(property_by_name(field.target), field.operator)
193
+ end
194
+
195
+ when Symbol
196
+ property_by_name(field)
186
197
 
187
- case field
188
- when Query::Operator
189
- if field.target == :all
198
+ when Property
190
199
  field
191
- else
192
- field.class.new(property_by_name(field.target), field.operator)
193
- end
194
- when Symbol
195
- property_by_name(field)
196
- when Property
197
- field
200
+ end
198
201
  end
199
202
  end
200
203
  end
@@ -1,15 +1,17 @@
1
1
  module DataMapper
2
- class Collection
3
- include AggregateFunctions
2
+ module Aggregates
3
+ module Collection
4
+ include Functions
4
5
 
5
- # def size
6
- # loaded? ? super : count
7
- # end
6
+ # def size
7
+ # loaded? ? super : count
8
+ # end
8
9
 
9
- private
10
+ private
10
11
 
11
- def property_by_name(property_name)
12
- properties[property_name]
12
+ def property_by_name(property_name)
13
+ properties[property_name]
14
+ end
13
15
  end
14
16
  end
15
17
  end
@@ -0,0 +1,9 @@
1
+ class Symbol
2
+ [ :count, :min, :max, :avg, :sum ].each do |sym|
3
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
4
+ def #{sym}
5
+ DataMapper::Query::Operator.new(self, #{sym.inspect})
6
+ end
7
+ RUBY
8
+ end
9
+ end # class Symbol
@@ -1,15 +1,17 @@
1
1
  module DataMapper
2
- module Model
3
- include AggregateFunctions
2
+ module Aggregates
3
+ module Model
4
+ include Functions
4
5
 
5
- # def size
6
- # count
7
- # end
6
+ # def size
7
+ # count
8
+ # end
8
9
 
9
- private
10
+ private
10
11
 
11
- def property_by_name(property_name)
12
- properties(repository.name)[property_name]
12
+ def property_by_name(property_name)
13
+ properties(repository.name)[property_name]
14
+ end
13
15
  end
14
16
  end
15
17
  end
@@ -0,0 +1,27 @@
1
+ module DataMapper
2
+ module Aggregates
3
+ module Query
4
+ def self.included(base)
5
+ base.class_eval <<-RUBY, __FILE__, __LINE__ + 1
6
+ # FIXME: figure out a cleaner approach than AMC
7
+ alias assert_valid_fields_without_operator assert_valid_fields
8
+ alias assert_valid_fields assert_valid_fields_with_operator
9
+ RUBY
10
+ end
11
+
12
+ def assert_valid_fields_with_operator(fields, unique)
13
+ operators, fields = fields.partition { |f| f.kind_of?(DataMapper::Query::Operator) }
14
+
15
+ operators.each do |operator|
16
+ target = operator.target
17
+
18
+ unless target == :all || target.kind_of?(Property) && target.model == model && @properties.include?(target)
19
+ raise ArgumentError, "+options[:fields]+ entry #{target.inspect} does not map to a property in #{model}"
20
+ end
21
+ end
22
+
23
+ assert_valid_fields_without_operator(fields, unique)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,7 +1,9 @@
1
1
  module DataMapper
2
- class Repository
3
- def aggregate(query)
4
- adapter.aggregate(query)
2
+ module Aggregates
3
+ module Repository
4
+ def aggregate(query)
5
+ adapter.aggregate(query)
6
+ end
5
7
  end
6
8
  end
7
9
  end
@@ -1,5 +1,5 @@
1
1
  module DataMapper
2
2
  module Aggregates
3
- VERSION = '0.9.11'
3
+ VERSION = '0.10.0'.freeze
4
4
  end
5
5
  end
data/lib/dm-aggregates.rb CHANGED
@@ -1,15 +1,26 @@
1
- require 'rubygems'
1
+ require 'dm-aggregates/adapters/data_objects_adapter'
2
+ require 'dm-aggregates/aggregate_functions'
3
+ require 'dm-aggregates/collection'
4
+ require 'dm-aggregates/core_ext/symbol'
5
+ require 'dm-aggregates/model'
6
+ require 'dm-aggregates/query'
7
+ require 'dm-aggregates/repository'
8
+ require 'dm-aggregates/version'
2
9
 
3
- dir = Pathname(__FILE__).dirname.expand_path + 'dm-aggregates'
10
+ module DataMapper
11
+ class Repository
12
+ include Aggregates::Repository
13
+ end
4
14
 
5
- require dir + 'version'
6
- gem 'dm-core', '0.9.11'
7
- require 'dm-core'
15
+ module Model
16
+ include Aggregates::Model
17
+ end
8
18
 
19
+ class Collection
20
+ include Aggregates::Collection
21
+ end
9
22
 
10
- require dir + 'aggregate_functions'
11
- require dir + 'model'
12
- require dir + 'repository'
13
- require dir + 'collection'
14
- require dir + 'adapters' + 'data_objects_adapter'
15
- require dir + 'support' + 'symbol'
23
+ class Query
24
+ include Aggregates::Query
25
+ end
26
+ end
@@ -1,5 +1,4 @@
1
- require 'pathname'
2
- require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
1
+ require 'spec_helper'
3
2
 
4
3
  if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
5
4
  describe DataMapper::Collection do
@@ -1,5 +1,4 @@
1
- require 'pathname'
2
- require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
1
+ require 'spec_helper'
3
2
 
4
3
  if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
5
4
  describe DataMapper::Model do
@@ -19,7 +19,7 @@ shared_examples_for 'It Has Setup Resources' do
19
19
  property :birth_on, Date
20
20
  property :birth_time, Time
21
21
 
22
- belongs_to :knight
22
+ belongs_to :knight, :nullable => true
23
23
  end
24
24
 
25
25
  # A more complex example, with BigDecimal and Float properties
data/spec/spec.opts CHANGED
@@ -1 +1,2 @@
1
1
  --colour
2
+ --loadby random
data/spec/spec_helper.rb CHANGED
@@ -1,9 +1,16 @@
1
- require 'pathname'
2
1
  require 'rubygems'
3
2
 
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 }
3
+ # use local dm-core if running from a typical dev checkout.
4
+ lib = File.join('..', '..', 'dm-core', 'lib')
5
+ $LOAD_PATH.unshift(lib) if File.directory?(lib)
6
+ require 'dm-core'
7
+
8
+ # Support running specs with 'rake spec' and 'spec'
9
+ $LOAD_PATH.unshift('lib') unless $LOAD_PATH.include?('lib')
10
+
11
+ require 'dm-aggregates'
12
+
13
+ require 'public/shared/aggregate_shared_spec'
7
14
 
8
15
  def load_driver(name, default_uri)
9
16
  return false if ENV['ADAPTER'] != name.to_s
data/tasks/install.rb CHANGED
@@ -4,7 +4,7 @@ end
4
4
 
5
5
  desc "Install #{GEM_NAME} #{GEM_VERSION}"
6
6
  task :install => [ :package ] do
7
- sudo_gem "install --local pkg/#{GEM_NAME}-#{GEM_VERSION} --no-update-sources"
7
+ sudo_gem "install pkg/#{GEM_NAME}-#{GEM_VERSION} --no-update-sources"
8
8
  end
9
9
 
10
10
  desc "Uninstall #{GEM_NAME} #{GEM_VERSION}"
data/tasks/spec.rb CHANGED
@@ -1,6 +1,4 @@
1
1
  begin
2
- gem 'rspec', '~>1.2'
3
- require 'spec'
4
2
  require 'spec/rake/spectask'
5
3
 
6
4
  task :default => [ :spec ]
@@ -8,16 +6,18 @@ begin
8
6
  desc 'Run specifications'
9
7
  Spec::Rake::SpecTask.new(:spec) do |t|
10
8
  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).map { |f| f.to_s }
9
+ t.libs << 'lib' << 'spec' # needed for CI rake spec task, duplicated in spec_helper
12
10
 
13
11
  begin
14
- gem 'rcov', '~>0.8'
12
+ require 'rcov'
15
13
  t.rcov = JRUBY ? false : (ENV.has_key?('NO_RCOV') ? ENV['NO_RCOV'] != 'true' : true)
16
14
  t.rcov_opts << '--exclude' << 'spec'
17
15
  t.rcov_opts << '--text-summary'
18
16
  t.rcov_opts << '--sort' << 'coverage' << '--sort-reverse'
19
17
  rescue LoadError
20
18
  # rcov not installed
19
+ rescue SyntaxError
20
+ # rcov syntax invalid
21
21
  end
22
22
  end
23
23
  rescue LoadError
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.11
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foy Savas
@@ -9,19 +9,10 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-29 00:00:00 -07:00
12
+ date: 2009-09-16 00:00:00 -07:00
13
13
  default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: dm-core
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - "="
22
- - !ruby/object:Gem::Version
23
- version: 0.9.11
24
- version:
14
+ dependencies: []
15
+
25
16
  description: DataMapper plugin providing support for aggregates, functions on collections and datasets
26
17
  email:
27
18
  - foysavas [a] gmail [d] com
@@ -30,24 +21,25 @@ executables: []
30
21
  extensions: []
31
22
 
32
23
  extra_rdoc_files:
33
- - README.txt
24
+ - README.rdoc
34
25
  - LICENSE
35
26
  - TODO
36
- - History.txt
27
+ - History.rdoc
37
28
  files:
38
- - History.txt
29
+ - History.rdoc
39
30
  - LICENSE
40
31
  - Manifest.txt
41
- - README.txt
32
+ - README.rdoc
42
33
  - Rakefile
43
34
  - TODO
44
35
  - lib/dm-aggregates.rb
45
36
  - lib/dm-aggregates/adapters/data_objects_adapter.rb
46
37
  - lib/dm-aggregates/aggregate_functions.rb
47
38
  - lib/dm-aggregates/collection.rb
39
+ - lib/dm-aggregates/core_ext/symbol.rb
48
40
  - lib/dm-aggregates/model.rb
41
+ - lib/dm-aggregates/query.rb
49
42
  - lib/dm-aggregates/repository.rb
50
- - lib/dm-aggregates/support/symbol.rb
51
43
  - lib/dm-aggregates/version.rb
52
44
  - spec/public/collection_spec.rb
53
45
  - spec/public/model_spec.rb
@@ -57,11 +49,13 @@ files:
57
49
  - tasks/install.rb
58
50
  - tasks/spec.rb
59
51
  has_rdoc: true
60
- homepage: http://github.com/sam/dm-more/tree/master/dm-aggregates
52
+ homepage: http://github.com/datamapper/dm-more/tree/master/dm-aggregates
53
+ licenses: []
54
+
61
55
  post_install_message:
62
56
  rdoc_options:
63
57
  - --main
64
- - README.txt
58
+ - README.rdoc
65
59
  require_paths:
66
60
  - lib
67
61
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -79,9 +73,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
79
73
  requirements: []
80
74
 
81
75
  rubyforge_project: datamapper
82
- rubygems_version: 1.3.1
76
+ rubygems_version: 1.3.5
83
77
  signing_key:
84
- specification_version: 2
78
+ specification_version: 3
85
79
  summary: DataMapper plugin providing support for aggregates, functions on collections and datasets
86
80
  test_files: []
87
81
 
@@ -1,21 +0,0 @@
1
- class Symbol
2
- def count
3
- DataMapper::Query::Operator.new(self, :count)
4
- end
5
-
6
- def min
7
- DataMapper::Query::Operator.new(self, :min)
8
- end
9
-
10
- def max
11
- DataMapper::Query::Operator.new(self, :max)
12
- end
13
-
14
- def avg
15
- DataMapper::Query::Operator.new(self, :avg)
16
- end
17
-
18
- def sum
19
- DataMapper::Query::Operator.new(self, :sum)
20
- end
21
- end # class Symbol