activerecord 4.1.1 → 4.1.2.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/CHANGELOG.md +312 -0
- data/lib/active_record/association_relation.rb +4 -0
- data/lib/active_record/associations.rb +24 -3
- data/lib/active_record/associations/association.rb +1 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +10 -4
- data/lib/active_record/associations/builder/has_many.rb +1 -1
- data/lib/active_record/associations/collection_association.rb +5 -5
- data/lib/active_record/associations/collection_proxy.rb +4 -0
- data/lib/active_record/associations/has_many_association.rb +6 -5
- data/lib/active_record/associations/has_many_through_association.rb +6 -2
- data/lib/active_record/associations/join_dependency.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +1 -1
- data/lib/active_record/associations/preloader.rb +14 -35
- data/lib/active_record/associations/preloader/association.rb +26 -5
- data/lib/active_record/associations/singular_association.rb +3 -3
- data/lib/active_record/associations/through_association.rb +4 -2
- data/lib/active_record/attribute_methods.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +2 -2
- data/lib/active_record/attribute_methods/serialization.rb +24 -5
- data/lib/active_record/attribute_methods/write.rb +22 -14
- data/lib/active_record/autosave_association.rb +40 -35
- data/lib/active_record/base.rb +2 -2
- data/lib/active_record/callbacks.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +10 -13
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +7 -1
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +8 -6
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid.rb +10 -5
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +9 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +11 -6
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +7 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +6 -3
- data/lib/active_record/connection_handling.rb +2 -2
- data/lib/active_record/core.rb +3 -0
- data/lib/active_record/counter_cache.rb +2 -3
- data/lib/active_record/fixtures.rb +1 -1
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/locking/optimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +1 -1
- data/lib/active_record/migration.rb +1 -1
- data/lib/active_record/nested_attributes.rb +2 -2
- data/lib/active_record/null_relation.rb +19 -5
- data/lib/active_record/persistence.rb +8 -8
- data/lib/active_record/railties/databases.rake +3 -2
- data/lib/active_record/reflection.rb +45 -13
- data/lib/active_record/relation.rb +7 -6
- data/lib/active_record/relation/calculations.rb +10 -2
- data/lib/active_record/relation/delegation.rb +2 -2
- data/lib/active_record/relation/finder_methods.rb +1 -1
- data/lib/active_record/relation/merger.rb +10 -2
- data/lib/active_record/relation/predicate_builder.rb +2 -2
- data/lib/active_record/relation/query_methods.rb +2 -2
- data/lib/active_record/scoping/default.rb +3 -3
- data/lib/active_record/store.rb +14 -5
- data/lib/active_record/timestamp.rb +2 -2
- data/lib/active_record/transactions.rb +1 -1
- data/lib/active_record/validations/presence.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +2 -2
- metadata +27 -35
data/lib/active_record/base.rb
CHANGED
@@ -296,7 +296,6 @@ module ActiveRecord #:nodoc:
|
|
296
296
|
|
297
297
|
include Core
|
298
298
|
include Persistence
|
299
|
-
include NoTouching
|
300
299
|
include ReadonlyAttributes
|
301
300
|
include ModelSchema
|
302
301
|
include Inheritance
|
@@ -310,14 +309,15 @@ module ActiveRecord #:nodoc:
|
|
310
309
|
include Locking::Optimistic
|
311
310
|
include Locking::Pessimistic
|
312
311
|
include AttributeMethods
|
313
|
-
include Callbacks
|
314
312
|
include Timestamp
|
313
|
+
include Callbacks
|
315
314
|
include Associations
|
316
315
|
include ActiveModel::SecurePassword
|
317
316
|
include AutosaveAssociation
|
318
317
|
include NestedAttributes
|
319
318
|
include Aggregations
|
320
319
|
include Transactions
|
320
|
+
include NoTouching
|
321
321
|
include Reflection
|
322
322
|
include Serialization
|
323
323
|
include Store
|
@@ -302,11 +302,11 @@ module ActiveRecord
|
|
302
302
|
run_callbacks(:save) { super }
|
303
303
|
end
|
304
304
|
|
305
|
-
def
|
305
|
+
def _create_record #:nodoc:
|
306
306
|
run_callbacks(:create) { super }
|
307
307
|
end
|
308
308
|
|
309
|
-
def
|
309
|
+
def _update_record(*) #:nodoc:
|
310
310
|
run_callbacks(:update) { super }
|
311
311
|
end
|
312
312
|
end
|
@@ -20,14 +20,7 @@ module ActiveRecord
|
|
20
20
|
|
21
21
|
# Returns an ActiveRecord::Result instance.
|
22
22
|
def select_all(arel, name = nil, binds = [])
|
23
|
-
|
24
|
-
relation = arel
|
25
|
-
arel = relation.arel
|
26
|
-
if !binds || binds.empty?
|
27
|
-
binds = relation.bind_values
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
23
|
+
arel, binds = binds_from_relation arel, binds
|
31
24
|
select(to_sql(arel, binds), name, binds)
|
32
25
|
end
|
33
26
|
|
@@ -47,10 +40,7 @@ module ActiveRecord
|
|
47
40
|
# Returns an array of the values of the first column in a select:
|
48
41
|
# select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
|
49
42
|
def select_values(arel, name = nil)
|
50
|
-
binds = []
|
51
|
-
if arel.is_a?(Relation)
|
52
|
-
arel, binds = arel.arel, arel.bind_values
|
53
|
-
end
|
43
|
+
arel, binds = binds_from_relation arel, []
|
54
44
|
select_rows(to_sql(arel, binds), name, binds).map(&:first)
|
55
45
|
end
|
56
46
|
|
@@ -328,7 +318,7 @@ module ActiveRecord
|
|
328
318
|
def sanitize_limit(limit)
|
329
319
|
if limit.is_a?(Integer) || limit.is_a?(Arel::Nodes::SqlLiteral)
|
330
320
|
limit
|
331
|
-
elsif limit.to_s
|
321
|
+
elsif limit.to_s.include?(',')
|
332
322
|
Arel.sql limit.to_s.split(',').map{ |i| Integer(i) }.join(',')
|
333
323
|
else
|
334
324
|
Integer(limit)
|
@@ -389,6 +379,13 @@ module ActiveRecord
|
|
389
379
|
row = result.rows.first
|
390
380
|
row && row.first
|
391
381
|
end
|
382
|
+
|
383
|
+
def binds_from_relation(relation, binds)
|
384
|
+
if relation.is_a?(Relation) && binds.blank?
|
385
|
+
relation, binds = relation.arel, relation.bind_values
|
386
|
+
end
|
387
|
+
[relation, binds]
|
388
|
+
end
|
392
389
|
end
|
393
390
|
end
|
394
391
|
end
|
@@ -64,7 +64,7 @@ module ActiveRecord
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def add_column_options!(sql, options)
|
67
|
-
sql << " DEFAULT #{
|
67
|
+
sql << " DEFAULT #{quote_value(options[:default], options[:column])}" if options_include_default?(options)
|
68
68
|
# must explicitly check for :null to allow change_column to work on migrations
|
69
69
|
if options[:null] == false
|
70
70
|
sql << " NOT NULL"
|
@@ -75,6 +75,12 @@ module ActiveRecord
|
|
75
75
|
sql
|
76
76
|
end
|
77
77
|
|
78
|
+
def quote_value(value, column)
|
79
|
+
column.sql_type ||= type_to_sql(column.type, column.limit, column.precision, column.scale)
|
80
|
+
|
81
|
+
@conn.quote(value, column)
|
82
|
+
end
|
83
|
+
|
78
84
|
def options_include_default?(options)
|
79
85
|
options.include?(:default) && !(options[:null] == false && options[:default].nil?)
|
80
86
|
end
|
@@ -15,7 +15,7 @@ module ActiveRecord
|
|
15
15
|
# are typically created by methods in TableDefinition, and added to the
|
16
16
|
# +columns+ attribute of said TableDefinition object, in order to be used
|
17
17
|
# for generating a number of table creation or table changing SQL statements.
|
18
|
-
class ColumnDefinition < Struct.new(:name, :type, :limit, :precision, :scale, :default, :null, :first, :after, :primary_key) #:nodoc:
|
18
|
+
class ColumnDefinition < Struct.new(:name, :type, :limit, :precision, :scale, :default, :null, :first, :after, :primary_key, :sql_type) #:nodoc:
|
19
19
|
|
20
20
|
def primary_key?
|
21
21
|
primary_key || type.to_sym == :primary_key
|
@@ -17,7 +17,7 @@ module ActiveRecord
|
|
17
17
|
options = o.options
|
18
18
|
sql_type = type_to_sql(o.type, options[:limit], options[:precision], options[:scale])
|
19
19
|
change_column_sql = "CHANGE #{quote_column_name(column.name)} #{quote_column_name(options[:name])} #{sql_type}"
|
20
|
-
add_column_options!(change_column_sql, options)
|
20
|
+
add_column_options!(change_column_sql, options.merge(column: column))
|
21
21
|
add_column_position!(change_column_sql, options)
|
22
22
|
end
|
23
23
|
|
@@ -111,6 +111,8 @@ module ActiveRecord
|
|
111
111
|
when /^mediumint/i; 3
|
112
112
|
when /^smallint/i; 2
|
113
113
|
when /^tinyint/i; 1
|
114
|
+
when /^float/i; 24
|
115
|
+
when /^double/i; 53
|
114
116
|
else
|
115
117
|
super
|
116
118
|
end
|
@@ -737,22 +739,22 @@ module ActiveRecord
|
|
737
739
|
end
|
738
740
|
|
739
741
|
def configure_connection
|
740
|
-
variables = @config
|
742
|
+
variables = @config.fetch(:variables, {}).stringify_keys
|
741
743
|
|
742
744
|
# By default, MySQL 'where id is null' selects the last inserted id.
|
743
745
|
# Turn this off. http://dev.rubyonrails.org/ticket/6778
|
744
|
-
variables[
|
746
|
+
variables['sql_auto_is_null'] = 0
|
745
747
|
|
746
748
|
# Increase timeout so the server doesn't disconnect us.
|
747
749
|
wait_timeout = @config[:wait_timeout]
|
748
750
|
wait_timeout = 2147483 unless wait_timeout.is_a?(Fixnum)
|
749
|
-
variables[
|
751
|
+
variables['wait_timeout'] = self.class.type_cast_config_to_integer(wait_timeout)
|
750
752
|
|
751
753
|
# Make MySQL reject illegal values rather than truncating or blanking them, see
|
752
754
|
# http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html#sqlmode_strict_all_tables
|
753
755
|
# If the user has provided another value for sql_mode, don't replace it.
|
754
|
-
if strict_mode? && !variables.has_key?(
|
755
|
-
variables[
|
756
|
+
if strict_mode? && !variables.has_key?('sql_mode')
|
757
|
+
variables['sql_mode'] = 'STRICT_ALL_TABLES'
|
756
758
|
end
|
757
759
|
|
758
760
|
# NAMES does not have an equals sign, see
|
@@ -142,10 +142,7 @@ module ActiveRecord
|
|
142
142
|
fields.each_with_index do |fname, i|
|
143
143
|
ftype = result.ftype i
|
144
144
|
fmod = result.fmod i
|
145
|
-
types[fname] =
|
146
|
-
warn "unknown OID: #{fname}(#{oid}) (#{sql})"
|
147
|
-
OID::Identity.new
|
148
|
-
}
|
145
|
+
types[fname] = get_oid_type(ftype, fmod, fname)
|
149
146
|
end
|
150
147
|
|
151
148
|
ret = ActiveRecord::Result.new(fields, result.values, types)
|
@@ -137,7 +137,7 @@ module ActiveRecord
|
|
137
137
|
case @subtype
|
138
138
|
when :date
|
139
139
|
from = ConnectionAdapters::Column.value_to_date(extracted[:from])
|
140
|
-
from
|
140
|
+
from += 1.day if extracted[:exclude_start]
|
141
141
|
to = ConnectionAdapters::Column.value_to_date(extracted[:to])
|
142
142
|
when :decimal
|
143
143
|
from = BigDecimal.new(extracted[:from].to_s)
|
@@ -148,7 +148,7 @@ module ActiveRecord
|
|
148
148
|
to = ConnectionAdapters::Column.string_to_time(extracted[:to])
|
149
149
|
when :integer
|
150
150
|
from = to_integer(extracted[:from]) rescue value ? 1 : 0
|
151
|
-
from
|
151
|
+
from += 1 if extracted[:exclude_start]
|
152
152
|
to = to_integer(extracted[:to]) rescue value ? 1 : 0
|
153
153
|
else
|
154
154
|
return value
|
@@ -210,9 +210,14 @@ module ActiveRecord
|
|
210
210
|
|
211
211
|
class Float < Type
|
212
212
|
def type_cast(value)
|
213
|
-
|
214
|
-
|
215
|
-
|
213
|
+
case value
|
214
|
+
when nil; nil
|
215
|
+
when 'Infinity'; ::Float::INFINITY
|
216
|
+
when '-Infinity'; -::Float::INFINITY
|
217
|
+
when 'NaN'; ::Float::NAN
|
218
|
+
else
|
219
|
+
value.to_f
|
220
|
+
end
|
216
221
|
end
|
217
222
|
end
|
218
223
|
|
@@ -182,6 +182,15 @@ module ActiveRecord
|
|
182
182
|
end
|
183
183
|
result
|
184
184
|
end
|
185
|
+
|
186
|
+
# Does not quote function default values for UUID columns
|
187
|
+
def quote_default_value(value, column) #:nodoc:
|
188
|
+
if column.type == :uuid && value =~ /\(\)/
|
189
|
+
value
|
190
|
+
else
|
191
|
+
quote(value, column)
|
192
|
+
end
|
193
|
+
end
|
185
194
|
end
|
186
195
|
end
|
187
196
|
end
|
@@ -12,7 +12,7 @@ module ActiveRecord
|
|
12
12
|
|
13
13
|
def visit_ColumnDefinition(o)
|
14
14
|
sql = super
|
15
|
-
if o.primary_key? && o.type
|
15
|
+
if o.primary_key? && o.type != :primary_key
|
16
16
|
sql << " PRIMARY KEY "
|
17
17
|
add_column_options!(sql, column_options(o))
|
18
18
|
end
|
@@ -185,13 +185,15 @@ module ActiveRecord
|
|
185
185
|
def columns(table_name)
|
186
186
|
# Limit, precision, and scale are all handled by the superclass.
|
187
187
|
column_definitions(table_name).map do |column_name, type, default, notnull, oid, fmod|
|
188
|
-
oid =
|
189
|
-
OID::Identity.new
|
190
|
-
}
|
188
|
+
oid = get_oid_type(oid.to_i, fmod.to_i, column_name)
|
191
189
|
PostgreSQLColumn.new(column_name, default, oid, type, notnull == 'f')
|
192
190
|
end
|
193
191
|
end
|
194
192
|
|
193
|
+
def column_for(table_name, column_name) #:nodoc:
|
194
|
+
columns(table_name).detect { |c| c.name == column_name.to_s }
|
195
|
+
end
|
196
|
+
|
195
197
|
# Returns the current database name.
|
196
198
|
def current_database
|
197
199
|
query('select current_database()', 'SCHEMA')[0][0]
|
@@ -408,13 +410,16 @@ module ActiveRecord
|
|
408
410
|
# Changes the default value of a table column.
|
409
411
|
def change_column_default(table_name, column_name, default)
|
410
412
|
clear_cache!
|
411
|
-
|
413
|
+
column = column_for(table_name, column_name)
|
414
|
+
|
415
|
+
execute "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} SET DEFAULT #{quote_default_value(default, column)}" if column
|
412
416
|
end
|
413
417
|
|
414
418
|
def change_column_null(table_name, column_name, null, default = nil)
|
415
419
|
clear_cache!
|
416
420
|
unless null || default.nil?
|
417
|
-
|
421
|
+
column = column_for(table_name, column_name)
|
422
|
+
execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote_default_value(default, column)} WHERE #{quote_column_name(column_name)} IS NULL") if column
|
418
423
|
end
|
419
424
|
execute("ALTER TABLE #{quote_table_name(table_name)} ALTER #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL")
|
420
425
|
end
|
@@ -760,6 +760,13 @@ module ActiveRecord
|
|
760
760
|
@type_map
|
761
761
|
end
|
762
762
|
|
763
|
+
def get_oid_type(oid, fmod, column_name)
|
764
|
+
type_map.fetch(oid, fmod) {
|
765
|
+
warn "unknown OID #{oid}: failed to recognize type of '#{column_name}'. It will be treated as String."
|
766
|
+
type_map[oid] = OID::Identity.new
|
767
|
+
}
|
768
|
+
end
|
769
|
+
|
763
770
|
def reload_type_map
|
764
771
|
type_map.clear
|
765
772
|
initialize_type_map(type_map)
|
@@ -299,9 +299,12 @@ module ActiveRecord
|
|
299
299
|
# Don't cache statements if they are not prepared
|
300
300
|
if without_prepared_statement?(binds)
|
301
301
|
stmt = @connection.prepare(sql)
|
302
|
-
|
303
|
-
|
304
|
-
|
302
|
+
begin
|
303
|
+
cols = stmt.columns
|
304
|
+
records = stmt.to_a
|
305
|
+
ensure
|
306
|
+
stmt.close
|
307
|
+
end
|
305
308
|
stmt = records
|
306
309
|
else
|
307
310
|
cache = @statements[sql] ||= {
|
@@ -18,14 +18,14 @@ module ActiveRecord
|
|
18
18
|
# Example for SQLite database:
|
19
19
|
#
|
20
20
|
# ActiveRecord::Base.establish_connection(
|
21
|
-
# adapter: "
|
21
|
+
# adapter: "sqlite3",
|
22
22
|
# database: "path/to/dbfile"
|
23
23
|
# )
|
24
24
|
#
|
25
25
|
# Also accepts keys as strings (for parsing from YAML for example):
|
26
26
|
#
|
27
27
|
# ActiveRecord::Base.establish_connection(
|
28
|
-
# "adapter" => "
|
28
|
+
# "adapter" => "sqlite3",
|
29
29
|
# "database" => "path/to/dbfile"
|
30
30
|
# )
|
31
31
|
#
|
data/lib/active_record/core.rb
CHANGED
@@ -220,6 +220,8 @@ module ActiveRecord
|
|
220
220
|
|
221
221
|
@new_record = false
|
222
222
|
|
223
|
+
self.class.define_attribute_methods
|
224
|
+
|
223
225
|
run_callbacks :find
|
224
226
|
run_callbacks :initialize
|
225
227
|
|
@@ -267,6 +269,7 @@ module ActiveRecord
|
|
267
269
|
@attributes_cache = {}
|
268
270
|
|
269
271
|
@new_record = true
|
272
|
+
@destroyed = false
|
270
273
|
|
271
274
|
super
|
272
275
|
end
|
@@ -20,7 +20,7 @@ module ActiveRecord
|
|
20
20
|
def reset_counters(id, *counters)
|
21
21
|
object = find(id)
|
22
22
|
counters.each do |association|
|
23
|
-
has_many_association =
|
23
|
+
has_many_association = _reflect_on_association(association.to_sym)
|
24
24
|
raise ArgumentError, "'#{self.name}' has no association called '#{association}'" unless has_many_association
|
25
25
|
|
26
26
|
if has_many_association.is_a? ActiveRecord::Reflection::ThroughReflection
|
@@ -29,8 +29,7 @@ module ActiveRecord
|
|
29
29
|
|
30
30
|
foreign_key = has_many_association.foreign_key.to_s
|
31
31
|
child_class = has_many_association.klass
|
32
|
-
|
33
|
-
reflection = belongs_to.find { |e| e.foreign_key.to_s == foreign_key && e.options[:counter_cache].present? }
|
32
|
+
reflection = child_class._reflections.values.find { |e| :belongs_to == e.macro && e.foreign_key.to_s == foreign_key && e.options[:counter_cache].present? }
|
34
33
|
counter_name = reflection.counter_cache_column
|
35
34
|
|
36
35
|
stmt = unscoped.where(arel_table[primary_key].eq(object.id)).arel.compile_update({
|
@@ -643,7 +643,7 @@ module ActiveRecord
|
|
643
643
|
model_class
|
644
644
|
end
|
645
645
|
|
646
|
-
reflection_class.
|
646
|
+
reflection_class._reflections.values.each do |association|
|
647
647
|
case association.macro
|
648
648
|
when :belongs_to
|
649
649
|
# Do not replace association name with association foreign key if they are named the same
|
@@ -66,7 +66,7 @@ module ActiveRecord
|
|
66
66
|
send(lock_col + '=', previous_lock_value + 1)
|
67
67
|
end
|
68
68
|
|
69
|
-
def
|
69
|
+
def _update_record(attribute_names = @attributes.keys) #:nodoc:
|
70
70
|
return super unless locking_enabled?
|
71
71
|
return 0 if attribute_names.empty?
|
72
72
|
|
@@ -25,7 +25,7 @@ module ActiveRecord
|
|
25
25
|
if column.binary?
|
26
26
|
# This specifically deals with the PG adapter that casts bytea columns into a Hash.
|
27
27
|
value = value[:value] if value.is_a?(Hash)
|
28
|
-
value = "<#{value.bytesize} bytes of binary data>"
|
28
|
+
value = value ? "<#{value.bytesize} bytes of binary data>" : "<NULL binary data>"
|
29
29
|
end
|
30
30
|
|
31
31
|
[column.name, value]
|
@@ -640,7 +640,7 @@ module ActiveRecord
|
|
640
640
|
|
641
641
|
say_with_time "#{method}(#{arg_list})" do
|
642
642
|
unless @connection.respond_to? :revert
|
643
|
-
unless arguments.empty? ||
|
643
|
+
unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
|
644
644
|
arguments[0] = proper_table_name(arguments.first, table_name_options)
|
645
645
|
arguments[1] = proper_table_name(arguments.second, table_name_options) if method == :rename_table
|
646
646
|
end
|
@@ -305,7 +305,7 @@ module ActiveRecord
|
|
305
305
|
options[:reject_if] = REJECT_ALL_BLANK_PROC if options[:reject_if] == :all_blank
|
306
306
|
|
307
307
|
attr_names.each do |association_name|
|
308
|
-
if reflection =
|
308
|
+
if reflection = _reflect_on_association(association_name)
|
309
309
|
reflection.autosave = true
|
310
310
|
add_autosave_association_callbacks(reflection)
|
311
311
|
|
@@ -542,7 +542,7 @@ module ActiveRecord
|
|
542
542
|
end
|
543
543
|
|
544
544
|
def raise_nested_attributes_record_not_found!(association_name, record_id)
|
545
|
-
raise RecordNotFound, "Couldn't find #{self.class.
|
545
|
+
raise RecordNotFound, "Couldn't find #{self.class._reflect_on_association(association_name).klass.name} with ID=#{record_id} for #{self.class.name} with ID=#{id}"
|
546
546
|
end
|
547
547
|
end
|
548
548
|
end
|
@@ -23,7 +23,7 @@ module ActiveRecord
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def size
|
26
|
-
|
26
|
+
calculate :size, nil
|
27
27
|
end
|
28
28
|
|
29
29
|
def empty?
|
@@ -43,18 +43,32 @@ module ActiveRecord
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def count(*)
|
46
|
-
|
46
|
+
calculate :count, nil
|
47
47
|
end
|
48
48
|
|
49
49
|
def sum(*)
|
50
|
-
|
50
|
+
calculate :sum, nil
|
51
|
+
end
|
52
|
+
|
53
|
+
def average(*)
|
54
|
+
calculate :average, nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def minimum(*)
|
58
|
+
calculate :minimum, nil
|
59
|
+
end
|
60
|
+
|
61
|
+
def maximum(*)
|
62
|
+
calculate :maximum, nil
|
51
63
|
end
|
52
64
|
|
53
65
|
def calculate(operation, _column_name, _options = {})
|
54
66
|
# TODO: Remove _options argument as soon we remove support to
|
55
67
|
# activerecord-deprecated_finders.
|
56
|
-
if
|
57
|
-
0
|
68
|
+
if [:count, :sum, :size].include? operation
|
69
|
+
group_values.any? ? Hash.new : 0
|
70
|
+
elsif [:average, :minimum, :maximum].include?(operation) && group_values.any?
|
71
|
+
Hash.new
|
58
72
|
else
|
59
73
|
nil
|
60
74
|
end
|