activerecord 2.0.2 → 2.0.4

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.

Files changed (53) hide show
  1. data/CHANGELOG +25 -0
  2. data/README +0 -0
  3. data/Rakefile +5 -3
  4. data/lib/active_record.rb +0 -0
  5. data/lib/active_record/associations.rb +232 -193
  6. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +14 -14
  7. data/lib/active_record/associations/has_many_association.rb +2 -2
  8. data/lib/active_record/associations/has_many_through_association.rb +25 -6
  9. data/lib/active_record/attribute_methods.rb +4 -3
  10. data/lib/active_record/base.rb +75 -41
  11. data/lib/active_record/calculations.rb +2 -1
  12. data/lib/active_record/callbacks.rb +0 -0
  13. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +1 -1
  14. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +8 -6
  15. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +12 -11
  16. data/lib/active_record/connection_adapters/abstract_adapter.rb +1 -0
  17. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -0
  18. data/lib/active_record/connection_adapters/postgresql_adapter.rb +3 -3
  19. data/lib/active_record/connection_adapters/sqlite_adapter.rb +13 -6
  20. data/lib/active_record/fixtures.rb +29 -31
  21. data/lib/active_record/migration.rb +4 -5
  22. data/lib/active_record/observer.rb +1 -1
  23. data/lib/active_record/transactions.rb +3 -5
  24. data/lib/active_record/validations.rb +5 -3
  25. data/lib/active_record/version.rb +1 -1
  26. data/test/abstract_unit.rb +0 -0
  27. data/test/active_schema_test_mysql.rb +5 -2
  28. data/test/adapter_test.rb +1 -0
  29. data/test/all.sh +0 -0
  30. data/test/associations/callbacks_test.rb +1 -1
  31. data/test/associations/eager_test.rb +5 -0
  32. data/test/associations/join_model_test.rb +11 -3
  33. data/test/associations_test.rb +36 -6
  34. data/test/attribute_methods_test.rb +0 -0
  35. data/test/base_test.rb +92 -10
  36. data/test/calculations_test.rb +9 -1
  37. data/test/debug.log +358 -0
  38. data/test/deprecated_finder_test.rb +0 -0
  39. data/test/fixtures/author.rb +1 -1
  40. data/test/fixtures/company.rb +0 -0
  41. data/test/fixtures/fixture_database.sqlite3 +0 -0
  42. data/test/fixtures/fixture_database_2.sqlite3 +0 -0
  43. data/test/fixtures/reply.rb +0 -0
  44. data/test/fixtures/topic.rb +0 -0
  45. data/test/fixtures_test.rb +20 -12
  46. data/test/inheritance_test.rb +0 -0
  47. data/test/lifecycle_test.rb +0 -0
  48. data/test/migration_test.rb +46 -0
  49. data/test/query_cache_test.rb +22 -2
  50. data/test/readonly_test.rb +0 -0
  51. data/test/unconnected_test.rb +0 -0
  52. data/test/validations_test.rb +50 -38
  53. metadata +8 -4
@@ -14,7 +14,7 @@ module ActiveRecord
14
14
  def create(attributes = {})
15
15
  create_record(attributes) { |record| insert_record(record) }
16
16
  end
17
-
17
+
18
18
  def create!(attributes = {})
19
19
  create_record(attributes) { |record| insert_record(record, true) }
20
20
  end
@@ -33,10 +33,10 @@ module ActiveRecord
33
33
 
34
34
  if ids.size == 1
35
35
  id = ids.first.to_i
36
- record = load_target.detect { |record| id == record.id }
36
+ record = load_target.detect { |r| id == r.id }
37
37
  expects_array ? [record] : record
38
38
  else
39
- load_target.select { |record| ids.include?(record.id) }
39
+ load_target.select { |r| ids.include?(r.id) }
40
40
  end
41
41
  else
42
42
  conditions = "#{@finder_sql}"
@@ -80,30 +80,30 @@ module ActiveRecord
80
80
  end
81
81
 
82
82
  if @reflection.options[:insert_sql]
83
- @owner.connection.execute(interpolate_sql(@reflection.options[:insert_sql], record))
83
+ @owner.connection.insert(interpolate_sql(@reflection.options[:insert_sql], record))
84
84
  else
85
85
  columns = @owner.connection.columns(@reflection.options[:join_table], "#{@reflection.options[:join_table]} Columns")
86
86
 
87
- attributes = columns.inject({}) do |attributes, column|
87
+ attributes = columns.inject({}) do |attrs, column|
88
88
  case column.name
89
89
  when @reflection.primary_key_name
90
- attributes[column.name] = @owner.quoted_id
90
+ attrs[column.name] = @owner.quoted_id
91
91
  when @reflection.association_foreign_key
92
- attributes[column.name] = record.quoted_id
92
+ attrs[column.name] = record.quoted_id
93
93
  else
94
- if record.attributes.has_key?(column.name)
94
+ if record.has_attribute?(column.name)
95
95
  value = @owner.send(:quote_value, record[column.name], column)
96
- attributes[column.name] = value unless value.nil?
96
+ attrs[column.name] = value unless value.nil?
97
97
  end
98
98
  end
99
- attributes
99
+ attrs
100
100
  end
101
101
 
102
102
  sql =
103
103
  "INSERT INTO #{@reflection.options[:join_table]} (#{@owner.send(:quoted_column_names, attributes).join(', ')}) " +
104
104
  "VALUES (#{attributes.values.join(', ')})"
105
105
 
106
- @owner.connection.execute(sql)
106
+ @owner.connection.insert(sql)
107
107
  end
108
108
 
109
109
  return true
@@ -111,11 +111,11 @@ module ActiveRecord
111
111
 
112
112
  def delete_records(records)
113
113
  if sql = @reflection.options[:delete_sql]
114
- records.each { |record| @owner.connection.execute(interpolate_sql(sql, record)) }
114
+ records.each { |record| @owner.connection.delete(interpolate_sql(sql, record)) }
115
115
  else
116
116
  ids = quoted_record_ids(records)
117
- sql = "DELETE FROM #{@reflection.options[:join_table]} WHERE #{@reflection.primary_key_name} = #{@owner.quoted_id} AND #{@reflection.association_foreign_key} IN (#{ids})"
118
- @owner.connection.execute(sql)
117
+ sql = "DELETE FROM #{@owner.connection.quote_table_name @reflection.options[:join_table]} WHERE #{@reflection.primary_key_name} = #{@owner.quoted_id} AND #{@reflection.association_foreign_key} IN (#{ids})"
118
+ @owner.connection.delete(sql)
119
119
  end
120
120
  end
121
121
 
@@ -41,10 +41,10 @@ module ActiveRecord
41
41
 
42
42
  if ids.size == 1
43
43
  id = ids.first
44
- record = load_target.detect { |record| id == record.id }
44
+ record = load_target.detect { |r| id == r.id }
45
45
  expects_array ? [ record ] : record
46
46
  else
47
- load_target.select { |record| ids.include?(record.id) }
47
+ load_target.select { |r| ids.include?(r.id) }
48
48
  end
49
49
  else
50
50
  conditions = "#{@finder_sql}"
@@ -262,12 +262,31 @@ module ActiveRecord
262
262
  end
263
263
 
264
264
  def conditions
265
- @conditions ||= [
266
- (interpolate_sql(@reflection.klass.send(:sanitize_sql, @reflection.options[:conditions])) if @reflection.options[:conditions]),
267
- (interpolate_sql(@reflection.active_record.send(:sanitize_sql, @reflection.through_reflection.options[:conditions])) if @reflection.through_reflection.options[:conditions]),
268
- (interpolate_sql(@reflection.active_record.send(:sanitize_sql, @reflection.source_reflection.options[:conditions])) if @reflection.source_reflection.options[:conditions]),
269
- ("#{@reflection.through_reflection.table_name}.#{@reflection.through_reflection.klass.inheritance_column} = #{@reflection.klass.quote_value(@reflection.through_reflection.klass.name.demodulize)}" unless @reflection.through_reflection.klass.descends_from_active_record?)
270
- ].compact.collect { |condition| "(#{condition})" }.join(' AND ') unless (!@reflection.options[:conditions] && !@reflection.through_reflection.options[:conditions] && !@reflection.source_reflection.options[:conditions] && @reflection.through_reflection.klass.descends_from_active_record?)
265
+ @conditions = build_conditions unless defined?(@conditions)
266
+ @conditions
267
+ end
268
+
269
+ def build_conditions
270
+ association_conditions = @reflection.options[:conditions]
271
+ through_conditions = @reflection.through_reflection.options[:conditions]
272
+ source_conditions = @reflection.source_reflection.options[:conditions]
273
+ uses_sti = !@reflection.through_reflection.klass.descends_from_active_record?
274
+
275
+ if association_conditions || through_conditions || source_conditions || uses_sti
276
+ all = []
277
+
278
+ [association_conditions, through_conditions, source_conditions].each do |conditions|
279
+ all << interpolate_sql(sanitize_sql(conditions)) if conditions
280
+ end
281
+
282
+ all << build_sti_condition if uses_sti
283
+
284
+ all.map { |sql| "(#{sql})" } * ' AND '
285
+ end
286
+ end
287
+
288
+ def build_sti_condition
289
+ "#{@reflection.through_reflection.table_name}.#{@reflection.through_reflection.klass.inheritance_column} = #{@reflection.klass.quote_value(@reflection.through_reflection.klass.name.demodulize)}"
271
290
  end
272
291
 
273
292
  alias_method :sql_conditions, :conditions
@@ -5,7 +5,7 @@ module ActiveRecord
5
5
 
6
6
  def self.included(base)
7
7
  base.extend ClassMethods
8
- base.attribute_method_suffix *DEFAULT_SUFFIXES
8
+ base.attribute_method_suffix(*DEFAULT_SUFFIXES)
9
9
  base.cattr_accessor :attribute_types_cached_by_default, :instance_writer => false
10
10
  base.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT
11
11
  end
@@ -82,9 +82,10 @@ module ActiveRecord
82
82
  # Check to see if the method is defined in the model or any of its subclasses that also derive from ActiveRecord.
83
83
  # Raise DangerousAttributeError if the method is defined by ActiveRecord though.
84
84
  def instance_method_already_implemented?(method_name)
85
+ method_name = method_name.to_s
85
86
  return true if method_name =~ /^id(=$|\?$|$)/
86
- @_defined_class_methods ||= Set.new(ancestors.first(ancestors.index(ActiveRecord::Base)).collect! { |m| m.public_instance_methods(false) | m.private_instance_methods(false) | m.protected_instance_methods(false) }.flatten)
87
- @@_defined_activerecord_methods ||= Set.new(ActiveRecord::Base.public_instance_methods(false) | ActiveRecord::Base.private_instance_methods(false) | ActiveRecord::Base.protected_instance_methods(false))
87
+ @_defined_class_methods ||= ancestors.first(ancestors.index(ActiveRecord::Base)).sum([]) { |m| m.public_instance_methods(false) | m.private_instance_methods(false) | m.protected_instance_methods(false) }.map(&:to_s).to_set
88
+ @@_defined_activerecord_methods ||= (ActiveRecord::Base.public_instance_methods(false) | ActiveRecord::Base.private_instance_methods(false) | ActiveRecord::Base.protected_instance_methods(false)).map(&:to_s).to_set
88
89
  raise DangerousAttributeError, "#{method_name} is defined by ActiveRecord" if @@_defined_activerecord_methods.include?(method_name)
89
90
  @_defined_class_methods.include?(method_name)
90
91
  end
@@ -1,4 +1,3 @@
1
- require 'base64'
2
1
  require 'yaml'
3
2
  require 'set'
4
3
 
@@ -549,8 +548,14 @@ module ActiveRecord #:nodoc:
549
548
  # Person.exists?(:name => "David")
550
549
  # Person.exists?(['name LIKE ?', "%#{query}%"])
551
550
  def exists?(id_or_conditions)
552
- !find(:first, :select => "#{quoted_table_name}.#{primary_key}",
553
- :conditions => expand_id_conditions(id_or_conditions)).nil?
551
+ connection.select_all(
552
+ construct_finder_sql(
553
+ :select => "#{quoted_table_name}.#{primary_key}",
554
+ :conditions => expand_id_conditions(id_or_conditions),
555
+ :limit => 1
556
+ ),
557
+ "#{name} Exists"
558
+ ).size > 0
554
559
  end
555
560
 
556
561
  # Creates an object (or multiple objects) and saves it to the database, if validations pass.
@@ -593,7 +598,7 @@ module ActiveRecord #:nodoc:
593
598
  def update(id, attributes)
594
599
  if id.is_a?(Array)
595
600
  idx = -1
596
- id.collect { |id| idx += 1; update(id, attributes[idx]) }
601
+ id.collect { |one_id| idx += 1; update(one_id, attributes[idx]) }
597
602
  else
598
603
  object = find(id)
599
604
  object.update_attributes(attributes)
@@ -643,7 +648,11 @@ module ActiveRecord #:nodoc:
643
648
  # todos = [1,2,3]
644
649
  # Todo.destroy(todos)
645
650
  def destroy(id)
646
- id.is_a?(Array) ? id.each { |id| destroy(id) } : find(id).destroy
651
+ if id.is_a?(Array)
652
+ id.map { |one_id| destroy(one_id) }
653
+ else
654
+ find(id).destroy
655
+ end
647
656
  end
648
657
 
649
658
  # Updates all records with details given if they match a set of conditions supplied, limits and order can
@@ -671,8 +680,8 @@ module ActiveRecord #:nodoc:
671
680
  sql = "UPDATE #{table_name} SET #{sanitize_sql_for_assignment(updates)} "
672
681
  scope = scope(:find)
673
682
  add_conditions!(sql, conditions, scope)
674
- add_order!(sql, options[:order], scope)
675
- add_limit!(sql, options, scope)
683
+ add_order!(sql, options[:order], nil)
684
+ add_limit!(sql, options, nil)
676
685
  connection.update(sql, "#{name} Update")
677
686
  end
678
687
 
@@ -957,14 +966,19 @@ module ActiveRecord #:nodoc:
957
966
  end
958
967
 
959
968
  def reset_primary_key #:nodoc:
969
+ key = get_primary_key(base_class.name)
970
+ set_primary_key(key)
971
+ key
972
+ end
973
+
974
+ def get_primary_key(base_name) #:nodoc:
960
975
  key = 'id'
961
976
  case primary_key_prefix_type
962
977
  when :table_name
963
- key = Inflector.foreign_key(base_class.name, false)
978
+ key = Inflector.foreign_key(base_name, false)
964
979
  when :table_name_with_underscore
965
- key = Inflector.foreign_key(base_class.name)
980
+ key = Inflector.foreign_key(base_name)
966
981
  end
967
- set_primary_key(key)
968
982
  key
969
983
  end
970
984
 
@@ -1076,9 +1090,9 @@ module ActiveRecord #:nodoc:
1076
1090
 
1077
1091
  # Returns an array of column objects for the table associated with this class.
1078
1092
  def columns
1079
- unless @columns
1093
+ unless defined?(@columns) && @columns
1080
1094
  @columns = connection.columns(table_name, "#{name} Columns")
1081
- @columns.each {|column| column.primary = column.name == primary_key}
1095
+ @columns.each { |column| column.primary = column.name == primary_key }
1082
1096
  end
1083
1097
  @columns
1084
1098
  end
@@ -1176,13 +1190,13 @@ module ActiveRecord #:nodoc:
1176
1190
  # project.milestones << Milestone.find(:all)
1177
1191
  # end
1178
1192
  #
1179
- # The benchmark is only recorded if the current level of the logger matches the <tt>log_level</tt>, which makes it
1180
- # easy to include benchmarking statements in production software that will remain inexpensive because the benchmark
1181
- # will only be conducted if the log level is low enough.
1193
+ # The benchmark is only recorded if the current level of the logger is less than or equal to the <tt>log_level</tt>,
1194
+ # which makes it easy to include benchmarking statements in production software that will remain inexpensive because
1195
+ # the benchmark will only be conducted if the log level is low enough.
1182
1196
  #
1183
1197
  # The logging of the multiple statements is turned off unless <tt>use_silence</tt> is set to false.
1184
1198
  def benchmark(title, log_level = Logger::DEBUG, use_silence = true)
1185
- if logger && logger.level == log_level
1199
+ if logger && logger.level <= log_level
1186
1200
  result = nil
1187
1201
  seconds = Benchmark.realtime { result = use_silence ? silence { yield } : yield }
1188
1202
  logger.add(log_level, "#{title} (#{'%.5f' % seconds})")
@@ -1218,7 +1232,7 @@ module ActiveRecord #:nodoc:
1218
1232
  # Returns whether this class is a base AR class. If A is a base class and
1219
1233
  # B descends from A, then B.base_class will return B.
1220
1234
  def abstract_class?
1221
- abstract_class == true
1235
+ defined?(@abstract_class) && @abstract_class == true
1222
1236
  end
1223
1237
 
1224
1238
  private
@@ -1429,7 +1443,7 @@ module ActiveRecord #:nodoc:
1429
1443
  case join
1430
1444
  when Symbol, Hash, Array
1431
1445
  join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, join, nil)
1432
- sql << " #{join_dependency.join_associations.collect{|join| join.association_join }.join} "
1446
+ sql << " #{join_dependency.join_associations.collect { |assoc| assoc.association_join }.join} "
1433
1447
  else
1434
1448
  sql << " #{join} "
1435
1449
  end
@@ -1484,7 +1498,7 @@ module ActiveRecord #:nodoc:
1484
1498
 
1485
1499
  self.class_eval %{
1486
1500
  def self.#{method_id}(*args)
1487
- options = args.last.is_a?(Hash) ? args.pop : {}
1501
+ options = args.extract_options!
1488
1502
  attributes = construct_attributes_from_arguments([:#{attribute_names.join(',:')}], args)
1489
1503
  finder_options = { :conditions => attributes }
1490
1504
  validate_find_options(options)
@@ -1863,10 +1877,13 @@ module ActiveRecord #:nodoc:
1863
1877
  end
1864
1878
 
1865
1879
  def expand_range_bind_variables(bind_vars) #:nodoc:
1866
- bind_vars.each_with_index do |var, index|
1867
- bind_vars[index, 1] = [var.first, var.last] if var.is_a?(Range)
1880
+ bind_vars.sum do |var|
1881
+ if var.is_a?(Range)
1882
+ [var.first, var.last]
1883
+ else
1884
+ [var]
1885
+ end
1868
1886
  end
1869
- bind_vars
1870
1887
  end
1871
1888
 
1872
1889
  def quote_bound_value(value) #:nodoc:
@@ -1963,7 +1980,7 @@ module ActiveRecord #:nodoc:
1963
1980
 
1964
1981
  # Returns true if this object hasn't been saved yet -- that is, a record for the object doesn't exist yet.
1965
1982
  def new_record?
1966
- @new_record
1983
+ defined?(@new_record) && @new_record
1967
1984
  end
1968
1985
 
1969
1986
  # * No record exists: Creates a new record with values matching those of the object attributes.
@@ -2040,28 +2057,28 @@ module ActiveRecord #:nodoc:
2040
2057
  save!
2041
2058
  end
2042
2059
 
2043
- # Initializes the +attribute+ to zero if nil and adds one. Only makes sense for number-based attributes. Returns self.
2044
- def increment(attribute)
2060
+ # Initializes the +attribute+ to zero if nil and adds the value passed as +by+ (default is one). Only makes sense for number-based attributes. Returns self.
2061
+ def increment(attribute, by = 1)
2045
2062
  self[attribute] ||= 0
2046
- self[attribute] += 1
2063
+ self[attribute] += by
2047
2064
  self
2048
2065
  end
2049
2066
 
2050
2067
  # Increments the +attribute+ and saves the record.
2051
- def increment!(attribute)
2052
- increment(attribute).update_attribute(attribute, self[attribute])
2068
+ def increment!(attribute, by = 1)
2069
+ increment(attribute, by).update_attribute(attribute, self[attribute])
2053
2070
  end
2054
2071
 
2055
- # Initializes the +attribute+ to zero if nil and subtracts one. Only makes sense for number-based attributes. Returns self.
2056
- def decrement(attribute)
2072
+ # Initializes the +attribute+ to zero if nil and subtracts the value passed as +by+ (default is one). Only makes sense for number-based attributes. Returns self.
2073
+ def decrement(attribute, by = 1)
2057
2074
  self[attribute] ||= 0
2058
- self[attribute] -= 1
2075
+ self[attribute] -= by
2059
2076
  self
2060
2077
  end
2061
2078
 
2062
2079
  # Decrements the +attribute+ and saves the record.
2063
- def decrement!(attribute)
2064
- decrement(attribute).update_attribute(attribute, self[attribute])
2080
+ def decrement!(attribute, by = 1)
2081
+ decrement(attribute, by).update_attribute(attribute, self[attribute])
2065
2082
  end
2066
2083
 
2067
2084
  # Turns an +attribute+ that's currently true into false and vice versa. Returns self.
@@ -2128,6 +2145,7 @@ module ActiveRecord #:nodoc:
2128
2145
  if options.nil?
2129
2146
  attributes
2130
2147
  else
2148
+ ActiveSupport::Deprecation.warn "Passing options to Base#attributes is deprecated and will be removed in Rails 2.1. Please use Hash#slice or Hash#except instead"
2131
2149
  if except = options[:except]
2132
2150
  except = Array(except).collect { |attribute| attribute.to_s }
2133
2151
  except.each { |attribute_name| attributes.delete(attribute_name) }
@@ -2214,7 +2232,7 @@ module ActiveRecord #:nodoc:
2214
2232
  # Returns +true+ if the record is read only. Records loaded through joins with piggy-back
2215
2233
  # attributes will be marked as read only since they cannot be saved.
2216
2234
  def readonly?
2217
- @readonly == true
2235
+ defined?(@readonly) && @readonly == true
2218
2236
  end
2219
2237
 
2220
2238
  # Marks this record as read only.
@@ -2335,11 +2353,11 @@ module ActiveRecord #:nodoc:
2335
2353
  # Returns a copy of the attributes hash where all the values have been safely quoted for use in
2336
2354
  # an SQL statement.
2337
2355
  def attributes_with_quotes(include_primary_key = true, include_readonly_attributes = true)
2338
- quoted = attributes.inject({}) do |quoted, (name, value)|
2356
+ quoted = attributes.inject({}) do |result, (name, value)|
2339
2357
  if column = column_for_attribute(name)
2340
- quoted[name] = quote_value(value, column) unless !include_primary_key && column.primary
2358
+ result[name] = quote_value(value, column) unless !include_primary_key && column.primary
2341
2359
  end
2342
- quoted
2360
+ result
2343
2361
  end
2344
2362
  include_readonly_attributes ? quoted : remove_readonly_attributes(quoted)
2345
2363
  end
@@ -2379,6 +2397,10 @@ module ActiveRecord #:nodoc:
2379
2397
  end
2380
2398
 
2381
2399
  # Includes an ugly hack for Time.local instead of Time.new because the latter is reserved by Time itself.
2400
+ def instantiate_time_object(*values)
2401
+ @@default_timezone == :utc ? Time.utc(*values) : Time.local(*values)
2402
+ end
2403
+
2382
2404
  def execute_callstack_for_multiparameter_attributes(callstack)
2383
2405
  errors = []
2384
2406
  callstack.each do |name, values|
@@ -2387,7 +2409,19 @@ module ActiveRecord #:nodoc:
2387
2409
  send(name + "=", nil)
2388
2410
  else
2389
2411
  begin
2390
- send(name + "=", Time == klass ? (@@default_timezone == :utc ? klass.utc(*values) : klass.local(*values)) : klass.new(*values))
2412
+ value = if Time == klass
2413
+ instantiate_time_object(*values)
2414
+ elsif Date == klass
2415
+ begin
2416
+ Date.new(*values)
2417
+ rescue ArgumentError => ex # if Date.new raises an exception on an invalid date
2418
+ instantiate_time_object(*values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates
2419
+ end
2420
+ else
2421
+ klass.new(*values)
2422
+ end
2423
+
2424
+ send(name + "=", value)
2391
2425
  rescue => ex
2392
2426
  errors << AttributeAssignmentError.new("error on assignment #{values.inspect} to #{name}", ex, name)
2393
2427
  end
@@ -2455,9 +2489,9 @@ module ActiveRecord #:nodoc:
2455
2489
  end
2456
2490
 
2457
2491
  def clone_attributes(reader_method = :read_attribute, attributes = {})
2458
- self.attribute_names.inject(attributes) do |attributes, name|
2459
- attributes[name] = clone_attribute_value(reader_method, name)
2460
- attributes
2492
+ self.attribute_names.inject(attributes) do |attrs, name|
2493
+ attrs[name] = clone_attribute_value(reader_method, name)
2494
+ attrs
2461
2495
  end
2462
2496
  end
2463
2497
 
@@ -155,6 +155,7 @@ module ActiveRecord
155
155
  scope = scope(:find)
156
156
  merged_includes = merge_includes(scope ? scope[:include] : [], options[:include])
157
157
  aggregate_alias = column_alias_for(operation, column_name)
158
+ column_name = "#{connection.quote_table_name(table_name)}.#{column_name}" unless column_name == "*" || column_name.to_s.include?('.')
158
159
 
159
160
  if operation == 'count'
160
161
  if merged_includes.any?
@@ -213,7 +214,7 @@ module ActiveRecord
213
214
  group_attr = options[:group].to_s
214
215
  association = reflect_on_association(group_attr.to_sym)
215
216
  associated = association && association.macro == :belongs_to # only count belongs_to associations
216
- group_field = (associated ? "#{options[:group]}_id" : options[:group]).to_s
217
+ group_field = associated ? association.primary_key_name : group_attr
217
218
  group_alias = column_alias_for(group_field)
218
219
  group_column = column_for group_field
219
220
  sql = construct_calculation_sql(operation, column_name, options.merge(:group_field => group_field, :group_alias => group_alias))
File without changes
@@ -71,7 +71,7 @@ module ActiveRecord
71
71
  # also be used to "borrow" the connection to do database work unrelated
72
72
  # to any of the specific Active Records.
73
73
  def connection
74
- if @active_connection_name && (conn = active_connections[@active_connection_name])
74
+ if defined?(@active_connection_name) && (conn = active_connections[@active_connection_name])
75
75
  conn
76
76
  else
77
77
  # retrieve_connection sets the cache key.
@@ -192,14 +192,14 @@ module ActiveRecord
192
192
  end
193
193
 
194
194
  def fallback_string_to_date(string)
195
- new_date *ParseDate.parsedate(string)[0..2]
195
+ new_date(*ParseDate.parsedate(string)[0..2])
196
196
  end
197
197
 
198
198
  def fallback_string_to_time(string)
199
199
  time_hash = Date._parse(string)
200
200
  time_hash[:sec_fraction] = microseconds(time_hash)
201
201
 
202
- new_time *time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction)
202
+ new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction))
203
203
  end
204
204
  end
205
205
 
@@ -417,7 +417,11 @@ module ActiveRecord
417
417
  # end
418
418
  def column(name, type, options = {})
419
419
  column = self[name] || ColumnDefinition.new(@base, name, type)
420
- column.limit = options[:limit] || native[type.to_sym][:limit] if options[:limit] or native[type.to_sym]
420
+ if options[:limit]
421
+ column.limit = options[:limit]
422
+ elsif native[type.to_sym].is_a?(Hash)
423
+ column.limit = native[type.to_sym][:limit]
424
+ end
421
425
  column.precision = options[:precision]
422
426
  column.scale = options[:scale]
423
427
  column.default = options[:default]
@@ -449,9 +453,7 @@ module ActiveRecord
449
453
  polymorphic = options.delete(:polymorphic)
450
454
  args.each do |col|
451
455
  column("#{col}_id", :integer, options)
452
- unless polymorphic.nil?
453
- column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : {})
454
- end
456
+ column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil?
455
457
  end
456
458
  end
457
459
  alias :belongs_to :references