activerecord 3.0.0 → 3.0.3

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 (46) hide show
  1. data/CHANGELOG +42 -0
  2. data/examples/performance.rb +18 -1
  3. data/lib/active_record.rb +3 -3
  4. data/lib/active_record/aggregations.rb +2 -2
  5. data/lib/active_record/association_preload.rb +1 -1
  6. data/lib/active_record/associations.rb +59 -26
  7. data/lib/active_record/associations/association_collection.rb +28 -18
  8. data/lib/active_record/associations/association_proxy.rb +4 -4
  9. data/lib/active_record/associations/belongs_to_association.rb +3 -3
  10. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +10 -13
  11. data/lib/active_record/associations/has_many_through_association.rb +2 -3
  12. data/lib/active_record/associations/has_one_association.rb +6 -6
  13. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  14. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -4
  15. data/lib/active_record/attribute_methods/primary_key.rb +4 -3
  16. data/lib/active_record/autosave_association.rb +7 -7
  17. data/lib/active_record/base.rb +71 -47
  18. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +6 -8
  19. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +2 -2
  20. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +5 -9
  21. data/lib/active_record/connection_adapters/mysql_adapter.rb +7 -7
  22. data/lib/active_record/connection_adapters/sqlite_adapter.rb +2 -2
  23. data/lib/active_record/dynamic_finder_match.rb +20 -17
  24. data/lib/active_record/dynamic_scope_match.rb +6 -15
  25. data/lib/active_record/fixtures.rb +3 -5
  26. data/lib/active_record/locking/optimistic.rb +1 -1
  27. data/lib/active_record/locking/pessimistic.rb +4 -4
  28. data/lib/active_record/nested_attributes.rb +17 -13
  29. data/lib/active_record/persistence.rb +7 -8
  30. data/lib/active_record/railties/databases.rake +7 -7
  31. data/lib/active_record/relation.rb +16 -18
  32. data/lib/active_record/relation/batches.rb +1 -1
  33. data/lib/active_record/relation/calculations.rb +37 -28
  34. data/lib/active_record/relation/finder_methods.rb +19 -19
  35. data/lib/active_record/relation/predicate_builder.rb +8 -1
  36. data/lib/active_record/relation/query_methods.rb +100 -75
  37. data/lib/active_record/relation/spawn_methods.rb +50 -39
  38. data/lib/active_record/serialization.rb +1 -1
  39. data/lib/active_record/session_store.rb +4 -4
  40. data/lib/active_record/transactions.rb +6 -6
  41. data/lib/active_record/validations.rb +1 -1
  42. data/lib/active_record/validations/uniqueness.rb +6 -1
  43. data/lib/active_record/version.rb +2 -2
  44. data/lib/rails/generators/active_record.rb +2 -10
  45. data/lib/rails/generators/active_record/migration.rb +15 -0
  46. metadata +15 -14
@@ -14,7 +14,7 @@ module ActiveRecord
14
14
  counter_cache_name = @reflection.counter_cache_column
15
15
 
16
16
  if record.nil?
17
- if counter_cache_name && !@owner.new_record?
17
+ if counter_cache_name && @owner.persisted?
18
18
  @reflection.klass.decrement_counter(counter_cache_name, previous_record_id) if @owner[@reflection.primary_key_name]
19
19
  end
20
20
 
@@ -22,13 +22,13 @@ module ActiveRecord
22
22
  else
23
23
  raise_on_type_mismatch(record)
24
24
 
25
- if counter_cache_name && !@owner.new_record? && record.id != @owner[@reflection.primary_key_name]
25
+ if counter_cache_name && @owner.persisted? && record.id != @owner[@reflection.primary_key_name]
26
26
  @reflection.klass.increment_counter(counter_cache_name, record.id)
27
27
  @reflection.klass.decrement_counter(counter_cache_name, @owner[@reflection.primary_key_name]) if @owner[@reflection.primary_key_name]
28
28
  end
29
29
 
30
30
  @target = (AssociationProxy === record ? record.target : record)
31
- @owner[@reflection.primary_key_name] = record_id(record) unless record.new_record?
31
+ @owner[@reflection.primary_key_name] = record_id(record) if record.persisted?
32
32
  @updated = true
33
33
  end
34
34
 
@@ -34,7 +34,7 @@ module ActiveRecord
34
34
  end
35
35
 
36
36
  def insert_record(record, force = true, validate = true)
37
- if record.new_record?
37
+ unless record.persisted?
38
38
  if force
39
39
  record.save!
40
40
  else
@@ -49,23 +49,20 @@ module ActiveRecord
49
49
  timestamps = record_timestamp_columns(record)
50
50
  timezone = record.send(:current_time_from_proper_timezone) if timestamps.any?
51
51
 
52
- attributes = columns.inject({}) do |attrs, column|
52
+ attributes = Hash[columns.map do |column|
53
53
  name = column.name
54
- case name.to_s
54
+ value = case name.to_s
55
55
  when @reflection.primary_key_name.to_s
56
- attrs[relation[name]] = @owner.id
56
+ @owner.id
57
57
  when @reflection.association_foreign_key.to_s
58
- attrs[relation[name]] = record.id
58
+ record.id
59
59
  when *timestamps
60
- attrs[relation[name]] = timezone
60
+ timezone
61
61
  else
62
- if record.has_attribute?(name)
63
- value = @owner.send(:quote_value, record[name], column)
64
- attrs[relation[name]] = value unless value.nil?
65
- end
62
+ @owner.send(:quote_value, record[name], column) if record.has_attribute?(name)
66
63
  end
67
- attrs
68
- end
64
+ [relation[name], value] unless value.nil?
65
+ end]
69
66
 
70
67
  relation.insert(attributes)
71
68
  end
@@ -79,7 +76,7 @@ module ActiveRecord
79
76
  else
80
77
  relation = Arel::Table.new(@reflection.options[:join_table])
81
78
  relation.where(relation[@reflection.primary_key_name].eq(@owner.id).
82
- and(relation[@reflection.association_foreign_key].in(records.map { |x| x.id }))
79
+ and(relation[@reflection.association_foreign_key].in(records.map { |x| x.id }.compact))
83
80
  ).delete
84
81
  end
85
82
  end
@@ -59,7 +59,7 @@ module ActiveRecord
59
59
  end
60
60
 
61
61
  def insert_record(record, force = true, validate = true)
62
- if record.new_record?
62
+ unless record.persisted?
63
63
  if force
64
64
  record.save!
65
65
  else
@@ -68,8 +68,7 @@ module ActiveRecord
68
68
  end
69
69
 
70
70
  through_association = @owner.send(@reflection.through_reflection.name)
71
- through_record = through_association.create!(construct_join_attributes(record))
72
- through_association.proxy_target << through_record
71
+ through_association.create!(construct_join_attributes(record))
73
72
  end
74
73
 
75
74
  # TODO - add dependent option support
@@ -35,18 +35,18 @@ module ActiveRecord
35
35
  if dependent? && !dont_save
36
36
  case @reflection.options[:dependent]
37
37
  when :delete
38
- @target.delete unless @target.new_record?
38
+ @target.delete if @target.persisted?
39
39
  @owner.clear_association_cache
40
40
  when :destroy
41
- @target.destroy unless @target.new_record?
41
+ @target.destroy if @target.persisted?
42
42
  @owner.clear_association_cache
43
43
  when :nullify
44
44
  @target[@reflection.primary_key_name] = nil
45
- @target.save unless @owner.new_record? || @target.new_record?
45
+ @target.save if @owner.persisted? && @target.persisted?
46
46
  end
47
47
  else
48
48
  @target[@reflection.primary_key_name] = nil
49
- @target.save unless @owner.new_record? || @target.new_record?
49
+ @target.save if @owner.persisted? && @target.persisted?
50
50
  end
51
51
  end
52
52
 
@@ -61,7 +61,7 @@ module ActiveRecord
61
61
  set_inverse_instance(obj, @owner)
62
62
  @loaded = true
63
63
 
64
- unless @owner.new_record? or obj.nil? or dont_save
64
+ unless !@owner.persisted? or obj.nil? or dont_save
65
65
  return (obj.save ? self : false)
66
66
  else
67
67
  return (obj.nil? ? nil : self)
@@ -120,7 +120,7 @@ module ActiveRecord
120
120
  if replace_existing
121
121
  replace(record, true)
122
122
  else
123
- record[@reflection.primary_key_name] = @owner.id unless @owner.new_record?
123
+ record[@reflection.primary_key_name] = @owner.id if @owner.persisted?
124
124
  self.target = record
125
125
  set_inverse_instance(record, @owner)
126
126
  end
@@ -21,7 +21,7 @@ module ActiveRecord
21
21
  if current_object
22
22
  new_value ? current_object.update_attributes(construct_join_attributes(new_value)) : current_object.destroy
23
23
  elsif new_value
24
- if @owner.new_record?
24
+ unless @owner.persisted?
25
25
  self.target = new_value
26
26
  through_association = @owner.send(:association_instance_get, @reflection.through_reflection.name)
27
27
  through_association.build(construct_join_attributes(new_value))
@@ -13,10 +13,7 @@ module ActiveRecord
13
13
 
14
14
  # Returns a hash of attributes before typecasting and deserialization.
15
15
  def attributes_before_type_cast
16
- self.attribute_names.inject({}) do |attrs, name|
17
- attrs[name] = read_attribute_before_type_cast(name)
18
- attrs
19
- end
16
+ Hash[attribute_names.map { |name| [name, read_attribute_before_type_cast(name)] }]
20
17
  end
21
18
 
22
19
  private
@@ -3,10 +3,11 @@ module ActiveRecord
3
3
  module PrimaryKey
4
4
  extend ActiveSupport::Concern
5
5
 
6
- # Returns this record's primary key value wrapped in an Array
7
- # or nil if the record is a new_record?
6
+ # Returns this record's primary key value wrapped in an Array or nil if
7
+ # the record is not persisted? or has just been destroyed.
8
8
  def to_key
9
- new_record? ? nil : [ id ]
9
+ key = send(self.class.primary_key)
10
+ [key] if key
10
11
  end
11
12
 
12
13
  module ClassMethods
@@ -208,7 +208,7 @@ module ActiveRecord
208
208
  # Returns whether or not this record has been changed in any way (including whether
209
209
  # any of its nested autosave associations are likewise changed)
210
210
  def changed_for_autosave?
211
- new_record? || changed? || marked_for_destruction? || nested_records_changed_for_autosave?
211
+ !persisted? || changed? || marked_for_destruction? || nested_records_changed_for_autosave?
212
212
  end
213
213
 
214
214
  private
@@ -222,7 +222,7 @@ module ActiveRecord
222
222
  elsif autosave
223
223
  association.target.find_all { |record| record.changed_for_autosave? }
224
224
  else
225
- association.target.find_all { |record| record.new_record? }
225
+ association.target.find_all { |record| !record.persisted? }
226
226
  end
227
227
  end
228
228
 
@@ -248,7 +248,7 @@ module ActiveRecord
248
248
  # +reflection+.
249
249
  def validate_collection_association(reflection)
250
250
  if association = association_instance_get(reflection.name)
251
- if records = associated_records_to_validate_or_save(association, new_record?, reflection.options[:autosave])
251
+ if records = associated_records_to_validate_or_save(association, !persisted?, reflection.options[:autosave])
252
252
  records.each { |record| association_valid?(reflection, record) }
253
253
  end
254
254
  end
@@ -277,7 +277,7 @@ module ActiveRecord
277
277
  # Is used as a before_save callback to check while saving a collection
278
278
  # association whether or not the parent was a new record before saving.
279
279
  def before_save_collection_association
280
- @new_record_before_save = new_record?
280
+ @new_record_before_save = !persisted?
281
281
  true
282
282
  end
283
283
 
@@ -299,7 +299,7 @@ module ActiveRecord
299
299
 
300
300
  if autosave && record.marked_for_destruction?
301
301
  association.destroy(record)
302
- elsif autosave != false && (@new_record_before_save || record.new_record?)
302
+ elsif autosave != false && (@new_record_before_save || !record.persisted?)
303
303
  if autosave
304
304
  saved = association.send(:insert_record, record, false, false)
305
305
  else
@@ -334,7 +334,7 @@ module ActiveRecord
334
334
  association.destroy
335
335
  else
336
336
  key = reflection.options[:primary_key] ? send(reflection.options[:primary_key]) : id
337
- if autosave != false && (new_record? || association.new_record? || association[reflection.primary_key_name] != key || autosave)
337
+ if autosave != false && (!persisted? || !association.persisted? || association[reflection.primary_key_name] != key || autosave)
338
338
  association[reflection.primary_key_name] = key
339
339
  saved = association.save(:validate => !autosave)
340
340
  raise ActiveRecord::Rollback if !saved && autosave
@@ -354,7 +354,7 @@ module ActiveRecord
354
354
  if autosave && association.marked_for_destruction?
355
355
  association.destroy
356
356
  elsif autosave != false
357
- saved = association.save(:validate => !autosave) if association.new_record? || autosave
357
+ saved = association.save(:validate => !autosave) if !association.persisted? || autosave
358
358
 
359
359
  if association.updated?
360
360
  association_id = association.send(reflection.options[:primary_key] || :id)
@@ -205,7 +205,7 @@ module ActiveRecord #:nodoc:
205
205
  #
206
206
  # # No 'Winter' tag exists
207
207
  # winter = Tag.find_or_initialize_by_name("Winter")
208
- # winter.new_record? # true
208
+ # winter.persisted? # false
209
209
  #
210
210
  # To find by a subset of the attributes to be used for instantiating a new object, pass a hash instead of
211
211
  # a list of parameters.
@@ -438,7 +438,7 @@ module ActiveRecord #:nodoc:
438
438
 
439
439
  delegate :find, :first, :last, :all, :destroy, :destroy_all, :exists?, :delete, :delete_all, :update, :update_all, :to => :scoped
440
440
  delegate :find_each, :find_in_batches, :to => :scoped
441
- delegate :select, :group, :order, :reorder, :limit, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, :having, :create_with, :to => :scoped
441
+ delegate :select, :group, :order, :reorder, :except, :limit, :offset, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, :having, :create_with, :to => :scoped
442
442
  delegate :count, :average, :minimum, :maximum, :sum, :calculate, :to => :scoped
443
443
 
444
444
  # Executes a custom SQL query against your database and returns all the results. The results will
@@ -608,7 +608,7 @@ module ActiveRecord #:nodoc:
608
608
  # Defines the column name for use with single table inheritance. Use
609
609
  # <tt>set_inheritance_column</tt> to set a different value.
610
610
  def inheritance_column
611
- @inheritance_column ||= "type".freeze
611
+ @inheritance_column ||= "type"
612
612
  end
613
613
 
614
614
  # Lazy-set the sequence name to the connection's default. This method
@@ -684,7 +684,7 @@ module ActiveRecord #:nodoc:
684
684
 
685
685
  # Returns a hash of column objects for the table associated with this class.
686
686
  def columns_hash
687
- @columns_hash ||= columns.inject({}) { |hash, column| hash[column.name] = column; hash }
687
+ @columns_hash ||= Hash[columns.map { |column| [column.name, column] }]
688
688
  end
689
689
 
690
690
  # Returns an array of column names as strings.
@@ -855,7 +855,7 @@ module ActiveRecord #:nodoc:
855
855
  if self == ActiveRecord::Base
856
856
  Arel::Table.engine
857
857
  else
858
- connection_handler.connection_pools[name] ? Arel::Sql::Engine.new(self) : superclass.arel_engine
858
+ connection_handler.connection_pools[name] ? self : superclass.arel_engine
859
859
  end
860
860
  end
861
861
  end
@@ -890,6 +890,10 @@ module ActiveRecord #:nodoc:
890
890
  Thread.current[key] = Thread.current[key].presence || self.default_scoping.dup
891
891
  end
892
892
 
893
+ def before_remove_const #:nodoc:
894
+ reset_scoped_methods
895
+ end
896
+
893
897
  private
894
898
 
895
899
  def relation #:nodoc:
@@ -901,21 +905,9 @@ module ActiveRecord #:nodoc:
901
905
  # single-table inheritance model that makes it possible to create
902
906
  # objects of different types from the same table.
903
907
  def instantiate(record)
904
- object = find_sti_class(record[inheritance_column]).allocate
905
-
906
- object.instance_variable_set(:@attributes, record)
907
- object.instance_variable_set(:@attributes_cache, {})
908
- object.instance_variable_set(:@new_record, false)
909
- object.instance_variable_set(:@readonly, false)
910
- object.instance_variable_set(:@destroyed, false)
911
- object.instance_variable_set(:@marked_for_destruction, false)
912
- object.instance_variable_set(:@previously_changed, {})
913
- object.instance_variable_set(:@changed_attributes, {})
914
-
915
- object.send(:_run_find_callbacks)
916
- object.send(:_run_initialize_callbacks)
917
-
918
- object
908
+ model = find_sti_class(record[inheritance_column]).allocate
909
+ model.init_with('attributes' => record)
910
+ model
919
911
  end
920
912
 
921
913
  def find_sti_class(type_name)
@@ -939,7 +931,7 @@ module ActiveRecord #:nodoc:
939
931
  end
940
932
 
941
933
  def construct_finder_arel(options = {}, scope = nil)
942
- relation = options.is_a?(Hash) ? unscoped.apply_finder_options(options) : unscoped.merge(options)
934
+ relation = options.is_a?(Hash) ? unscoped.apply_finder_options(options) : options
943
935
  relation = scope.merge(relation) if scope
944
936
  relation
945
937
  end
@@ -1039,8 +1031,9 @@ module ActiveRecord #:nodoc:
1039
1031
  end
1040
1032
 
1041
1033
  def all_attributes_exists?(attribute_names)
1042
- attribute_names = expand_attribute_names_for_aggregates(attribute_names)
1043
- attribute_names.all? { |name| column_methods_hash.include?(name.to_sym) }
1034
+ expand_attribute_names_for_aggregates(attribute_names).all? { |name|
1035
+ column_methods_hash.include?(name.to_sym)
1036
+ }
1044
1037
  end
1045
1038
 
1046
1039
  protected
@@ -1096,9 +1089,9 @@ module ActiveRecord #:nodoc:
1096
1089
 
1097
1090
  if method_scoping.is_a?(Hash)
1098
1091
  # Dup first and second level of hash (method and params).
1099
- method_scoping = method_scoping.inject({}) do |hash, (method, params)|
1100
- hash[method] = (params == true) ? params : params.dup
1101
- hash
1092
+ method_scoping = method_scoping.dup
1093
+ method_scoping.each do |method, params|
1094
+ method_scoping[method] = params.dup unless params == true
1102
1095
  end
1103
1096
 
1104
1097
  method_scoping.assert_valid_keys([ :find, :create ])
@@ -1167,6 +1160,7 @@ MSG
1167
1160
  # Article.new.published # => true
1168
1161
  # Article.create.published # => true
1169
1162
  def default_scope(options = {})
1163
+ reset_scoped_methods
1170
1164
  self.default_scoping << construct_finder_arel(options, default_scoping.pop)
1171
1165
  end
1172
1166
 
@@ -1174,6 +1168,10 @@ MSG
1174
1168
  scoped_methods.last
1175
1169
  end
1176
1170
 
1171
+ def reset_scoped_methods #:nodoc:
1172
+ Thread.current[:"#{self}_scoped_methods"] = nil
1173
+ end
1174
+
1177
1175
  # Returns the class type of the record using the current module as a prefix. So descendants of
1178
1176
  # MyApp::Business::Account would appear as MyApp::Business::AccountSubclass.
1179
1177
  def compute_type(type_name)
@@ -1395,7 +1393,7 @@ MSG
1395
1393
  def initialize(attributes = nil)
1396
1394
  @attributes = attributes_from_column_definition
1397
1395
  @attributes_cache = {}
1398
- @new_record = true
1396
+ @persisted = false
1399
1397
  @readonly = false
1400
1398
  @destroyed = false
1401
1399
  @marked_for_destruction = false
@@ -1404,10 +1402,7 @@ MSG
1404
1402
 
1405
1403
  ensure_proper_type
1406
1404
 
1407
- if scope = self.class.send(:current_scoped_methods)
1408
- create_with = scope.scope_for_create
1409
- create_with.each { |att,value| self.send("#{att}=", value) } if create_with
1410
- end
1405
+ populate_with_current_scope_attributes
1411
1406
  self.attributes = attributes unless attributes.nil?
1412
1407
 
1413
1408
  result = yield self if block_given?
@@ -1433,13 +1428,29 @@ MSG
1433
1428
  clear_aggregation_cache
1434
1429
  clear_association_cache
1435
1430
  @attributes_cache = {}
1436
- @new_record = true
1431
+ @persisted = false
1437
1432
  ensure_proper_type
1438
1433
 
1439
- if scope = self.class.send(:current_scoped_methods)
1440
- create_with = scope.scope_for_create
1441
- create_with.each { |att,value| self.send("#{att}=", value) } if create_with
1442
- end
1434
+ populate_with_current_scope_attributes
1435
+ end
1436
+
1437
+ # Initialize an empty model object from +coder+. +coder+ must contain
1438
+ # the attributes necessary for initializing an empty model object. For
1439
+ # example:
1440
+ #
1441
+ # class Post < ActiveRecord::Base
1442
+ # end
1443
+ #
1444
+ # post = Post.allocate
1445
+ # post.init_with('attributes' => { 'title' => 'hello world' })
1446
+ # post.title # => 'hello world'
1447
+ def init_with(coder)
1448
+ @attributes = coder['attributes']
1449
+ @attributes_cache, @previously_changed, @changed_attributes = {}, {}, {}
1450
+ @readonly = @destroyed = @marked_for_destruction = false
1451
+ @persisted = true
1452
+ _run_find_callbacks
1453
+ _run_initialize_callbacks
1443
1454
  end
1444
1455
 
1445
1456
  # Returns a String, which Action Pack uses for constructing an URL to this
@@ -1478,7 +1489,7 @@ MSG
1478
1489
  # Person.find(5).cache_key # => "people/5-20071224150000" (updated_at available)
1479
1490
  def cache_key
1480
1491
  case
1481
- when new_record?
1492
+ when !persisted?
1482
1493
  "#{self.class.model_name.cache_key}/new"
1483
1494
  when timestamp = self[:updated_at]
1484
1495
  "#{self.class.model_name.cache_key}/#{id}-#{timestamp.to_s(:number)}"
@@ -1596,11 +1607,20 @@ MSG
1596
1607
  self.class.columns_hash[name.to_s]
1597
1608
  end
1598
1609
 
1599
- # Returns true if the +comparison_object+ is the same object, or is of the same type and has the same id.
1610
+ # Returns true if +comparison_object+ is the same exact object, or +comparison_object+
1611
+ # is of the same type and +self+ has an ID and it is equal to +comparison_object.id+.
1612
+ #
1613
+ # Note that new records are different from any other record by definition, unless the
1614
+ # other record is the receiver itself. Besides, if you fetch existing records with
1615
+ # +select+ and leave the ID out, you're on your own, this predicate will return false.
1616
+ #
1617
+ # Note also that destroying a record preserves its ID in the model instance, so deleted
1618
+ # models are still comparable.
1600
1619
  def ==(comparison_object)
1601
1620
  comparison_object.equal?(self) ||
1602
- (comparison_object.instance_of?(self.class) &&
1603
- comparison_object.id == id && !comparison_object.new_record?)
1621
+ comparison_object.instance_of?(self.class) &&
1622
+ id.present? &&
1623
+ comparison_object.id == id
1604
1624
  end
1605
1625
 
1606
1626
  # Delegates to ==
@@ -1645,7 +1665,7 @@ MSG
1645
1665
  # Returns the contents of the record as a nicely formatted string.
1646
1666
  def inspect
1647
1667
  attributes_as_nice_string = self.class.column_names.collect { |name|
1648
- if has_attribute?(name) || new_record?
1668
+ if has_attribute?(name) || !persisted?
1649
1669
  "#{name}: #{attribute_for_inspect(name)}"
1650
1670
  end
1651
1671
  }.compact.join(", ")
@@ -1697,8 +1717,8 @@ MSG
1697
1717
  if include_readonly_attributes || (!include_readonly_attributes && !self.class.readonly_attributes.include?(name))
1698
1718
  value = read_attribute(name)
1699
1719
 
1700
- if value && ((self.class.serialized_attributes.has_key?(name) && (value.acts_like?(:date) || value.acts_like?(:time))) || value.is_a?(Hash) || value.is_a?(Array))
1701
- value = value.to_yaml
1720
+ if value && self.class.serialized_attributes.key?(name)
1721
+ value = YAML.dump value
1702
1722
  end
1703
1723
  attrs[self.class.arel_table[name]] = value
1704
1724
  end
@@ -1805,10 +1825,7 @@ MSG
1805
1825
  end
1806
1826
 
1807
1827
  def quote_columns(quoter, hash)
1808
- hash.inject({}) do |quoted, (name, value)|
1809
- quoted[quoter.quote_column_name(name)] = value
1810
- quoted
1811
- end
1828
+ Hash[hash.map { |name, value| [quoter.quote_column_name(name), value] }]
1812
1829
  end
1813
1830
 
1814
1831
  def quoted_comma_pair_list(quoter, hash)
@@ -1831,6 +1848,13 @@ MSG
1831
1848
  return string unless string.is_a?(String) && string =~ /^---/
1832
1849
  YAML::load(string) rescue string
1833
1850
  end
1851
+
1852
+ def populate_with_current_scope_attributes
1853
+ if scope = self.class.send(:current_scoped_methods)
1854
+ create_with = scope.scope_for_create
1855
+ create_with.each { |att,value| self.respond_to?(:"#{att}=") && self.send("#{att}=", value) } if create_with
1856
+ end
1857
+ end
1834
1858
  end
1835
1859
 
1836
1860
  Base.class_eval do