dm-aggregates 0.9.11 → 0.10.0
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 → History.rdoc} +4 -0
- data/Manifest.txt +4 -3
- data/{README.txt → README.rdoc} +0 -0
- data/Rakefile +2 -3
- data/lib/dm-aggregates/adapters/data_objects_adapter.rb +67 -27
- data/lib/dm-aggregates/aggregate_functions.rb +184 -181
- data/lib/dm-aggregates/collection.rb +10 -8
- data/lib/dm-aggregates/core_ext/symbol.rb +9 -0
- data/lib/dm-aggregates/model.rb +10 -8
- data/lib/dm-aggregates/query.rb +27 -0
- data/lib/dm-aggregates/repository.rb +5 -3
- data/lib/dm-aggregates/version.rb +1 -1
- data/lib/dm-aggregates.rb +22 -11
- data/spec/public/collection_spec.rb +1 -2
- data/spec/public/model_spec.rb +1 -2
- data/spec/public/shared/aggregate_shared_spec.rb +1 -1
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +11 -4
- data/tasks/install.rb +1 -1
- data/tasks/spec.rb +4 -4
- metadata +16 -22
- data/lib/dm-aggregates/support/symbol.rb +0 -21
data/Manifest.txt
CHANGED
@@ -1,16 +1,17 @@
|
|
1
|
-
History.
|
1
|
+
History.rdoc
|
2
2
|
LICENSE
|
3
3
|
Manifest.txt
|
4
|
-
README.
|
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
|
data/{README.txt → README.rdoc}
RENAMED
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.
|
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/
|
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
|
3
|
-
|
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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
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
|
75
|
+
def property_to_column_name_with_operator(property, qualify)
|
52
76
|
case property
|
53
|
-
when Query::Operator
|
54
|
-
aggregate_field_statement(
|
55
|
-
|
56
|
-
|
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(
|
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(
|
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
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
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
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
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
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
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
|
-
|
170
|
+
private
|
171
171
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
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
|
-
|
177
|
+
type = property_by_name(name).type
|
178
178
|
|
179
|
-
|
180
|
-
|
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
|
-
|
185
|
-
|
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
|
-
|
188
|
-
when Query::Operator
|
189
|
-
if field.target == :all
|
198
|
+
when Property
|
190
199
|
field
|
191
|
-
|
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
|
-
|
3
|
-
|
2
|
+
module Aggregates
|
3
|
+
module Collection
|
4
|
+
include Functions
|
4
5
|
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# def size
|
7
|
+
# loaded? ? super : count
|
8
|
+
# end
|
8
9
|
|
9
|
-
|
10
|
+
private
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
def property_by_name(property_name)
|
13
|
+
properties[property_name]
|
14
|
+
end
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
data/lib/dm-aggregates/model.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
module DataMapper
|
2
|
-
module
|
3
|
-
|
2
|
+
module Aggregates
|
3
|
+
module Model
|
4
|
+
include Functions
|
4
5
|
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# def size
|
7
|
+
# count
|
8
|
+
# end
|
8
9
|
|
9
|
-
|
10
|
+
private
|
10
11
|
|
11
|
-
|
12
|
-
|
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
|
data/lib/dm-aggregates.rb
CHANGED
@@ -1,15 +1,26 @@
|
|
1
|
-
require '
|
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
|
-
|
10
|
+
module DataMapper
|
11
|
+
class Repository
|
12
|
+
include Aggregates::Repository
|
13
|
+
end
|
4
14
|
|
5
|
-
|
6
|
-
|
7
|
-
|
15
|
+
module Model
|
16
|
+
include Aggregates::Model
|
17
|
+
end
|
8
18
|
|
19
|
+
class Collection
|
20
|
+
include Aggregates::Collection
|
21
|
+
end
|
9
22
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
require dir + 'adapters' + 'data_objects_adapter'
|
15
|
-
require dir + 'support' + 'symbol'
|
23
|
+
class Query
|
24
|
+
include Aggregates::Query
|
25
|
+
end
|
26
|
+
end
|
data/spec/public/model_spec.rb
CHANGED
data/spec/spec.opts
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -1,9 +1,16 @@
|
|
1
|
-
require 'pathname'
|
2
1
|
require 'rubygems'
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
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.
|
9
|
+
t.libs << 'lib' << 'spec' # needed for CI rake spec task, duplicated in spec_helper
|
12
10
|
|
13
11
|
begin
|
14
|
-
|
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.
|
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-
|
12
|
+
date: 2009-09-16 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
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.
|
24
|
+
- README.rdoc
|
34
25
|
- LICENSE
|
35
26
|
- TODO
|
36
|
-
- History.
|
27
|
+
- History.rdoc
|
37
28
|
files:
|
38
|
-
- History.
|
29
|
+
- History.rdoc
|
39
30
|
- LICENSE
|
40
31
|
- Manifest.txt
|
41
|
-
- README.
|
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/
|
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.
|
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.
|
76
|
+
rubygems_version: 1.3.5
|
83
77
|
signing_key:
|
84
|
-
specification_version:
|
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
|