activerecord 3.0.20 → 3.1.0.beta1

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 (122) hide show
  1. data/CHANGELOG +220 -91
  2. data/README.rdoc +3 -3
  3. data/examples/performance.rb +88 -109
  4. data/lib/active_record.rb +6 -2
  5. data/lib/active_record/aggregations.rb +22 -45
  6. data/lib/active_record/associations.rb +264 -991
  7. data/lib/active_record/associations/alias_tracker.rb +85 -0
  8. data/lib/active_record/associations/association.rb +231 -0
  9. data/lib/active_record/associations/association_scope.rb +120 -0
  10. data/lib/active_record/associations/belongs_to_association.rb +40 -60
  11. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +15 -63
  12. data/lib/active_record/associations/builder/association.rb +53 -0
  13. data/lib/active_record/associations/builder/belongs_to.rb +85 -0
  14. data/lib/active_record/associations/builder/collection_association.rb +75 -0
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +63 -0
  16. data/lib/active_record/associations/builder/has_many.rb +65 -0
  17. data/lib/active_record/associations/builder/has_one.rb +63 -0
  18. data/lib/active_record/associations/builder/singular_association.rb +32 -0
  19. data/lib/active_record/associations/collection_association.rb +524 -0
  20. data/lib/active_record/associations/collection_proxy.rb +125 -0
  21. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +27 -118
  22. data/lib/active_record/associations/has_many_association.rb +50 -79
  23. data/lib/active_record/associations/has_many_through_association.rb +98 -67
  24. data/lib/active_record/associations/has_one_association.rb +45 -115
  25. data/lib/active_record/associations/has_one_through_association.rb +21 -25
  26. data/lib/active_record/associations/join_dependency.rb +215 -0
  27. data/lib/active_record/associations/join_dependency/join_association.rb +150 -0
  28. data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
  29. data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
  30. data/lib/active_record/associations/join_helper.rb +56 -0
  31. data/lib/active_record/associations/preloader.rb +177 -0
  32. data/lib/active_record/associations/preloader/association.rb +126 -0
  33. data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
  34. data/lib/active_record/associations/preloader/collection_association.rb +24 -0
  35. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
  36. data/lib/active_record/associations/preloader/has_many.rb +17 -0
  37. data/lib/active_record/associations/preloader/has_many_through.rb +15 -0
  38. data/lib/active_record/associations/preloader/has_one.rb +23 -0
  39. data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
  40. data/lib/active_record/associations/preloader/singular_association.rb +21 -0
  41. data/lib/active_record/associations/preloader/through_association.rb +67 -0
  42. data/lib/active_record/associations/singular_association.rb +55 -0
  43. data/lib/active_record/associations/through_association.rb +80 -0
  44. data/lib/active_record/attribute_methods.rb +19 -5
  45. data/lib/active_record/attribute_methods/before_type_cast.rb +9 -8
  46. data/lib/active_record/attribute_methods/dirty.rb +8 -2
  47. data/lib/active_record/attribute_methods/primary_key.rb +33 -13
  48. data/lib/active_record/attribute_methods/read.rb +17 -17
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -4
  50. data/lib/active_record/attribute_methods/write.rb +2 -1
  51. data/lib/active_record/autosave_association.rb +66 -45
  52. data/lib/active_record/base.rb +445 -273
  53. data/lib/active_record/callbacks.rb +24 -33
  54. data/lib/active_record/coders/yaml_column.rb +41 -0
  55. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +106 -13
  56. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +16 -2
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +12 -11
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +83 -12
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +16 -16
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +61 -22
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +16 -273
  62. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +80 -42
  63. data/lib/active_record/connection_adapters/abstract_adapter.rb +44 -25
  64. data/lib/active_record/connection_adapters/column.rb +268 -0
  65. data/lib/active_record/connection_adapters/mysql2_adapter.rb +686 -0
  66. data/lib/active_record/connection_adapters/mysql_adapter.rb +331 -88
  67. data/lib/active_record/connection_adapters/postgresql_adapter.rb +295 -267
  68. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +3 -7
  69. data/lib/active_record/connection_adapters/sqlite_adapter.rb +108 -26
  70. data/lib/active_record/counter_cache.rb +7 -4
  71. data/lib/active_record/fixtures.rb +174 -192
  72. data/lib/active_record/identity_map.rb +131 -0
  73. data/lib/active_record/locking/optimistic.rb +20 -14
  74. data/lib/active_record/locking/pessimistic.rb +4 -4
  75. data/lib/active_record/log_subscriber.rb +24 -4
  76. data/lib/active_record/migration.rb +265 -144
  77. data/lib/active_record/migration/command_recorder.rb +103 -0
  78. data/lib/active_record/named_scope.rb +68 -25
  79. data/lib/active_record/nested_attributes.rb +58 -15
  80. data/lib/active_record/observer.rb +3 -7
  81. data/lib/active_record/persistence.rb +58 -38
  82. data/lib/active_record/query_cache.rb +25 -3
  83. data/lib/active_record/railtie.rb +21 -12
  84. data/lib/active_record/railties/console_sandbox.rb +6 -0
  85. data/lib/active_record/railties/databases.rake +147 -116
  86. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  87. data/lib/active_record/reflection.rb +176 -44
  88. data/lib/active_record/relation.rb +125 -49
  89. data/lib/active_record/relation/batches.rb +7 -5
  90. data/lib/active_record/relation/calculations.rb +50 -18
  91. data/lib/active_record/relation/finder_methods.rb +47 -26
  92. data/lib/active_record/relation/predicate_builder.rb +24 -21
  93. data/lib/active_record/relation/query_methods.rb +117 -101
  94. data/lib/active_record/relation/spawn_methods.rb +27 -20
  95. data/lib/active_record/result.rb +34 -0
  96. data/lib/active_record/schema.rb +5 -6
  97. data/lib/active_record/schema_dumper.rb +11 -13
  98. data/lib/active_record/serialization.rb +2 -2
  99. data/lib/active_record/serializers/xml_serializer.rb +10 -10
  100. data/lib/active_record/session_store.rb +8 -2
  101. data/lib/active_record/test_case.rb +9 -20
  102. data/lib/active_record/timestamp.rb +21 -9
  103. data/lib/active_record/transactions.rb +16 -15
  104. data/lib/active_record/validations.rb +21 -22
  105. data/lib/active_record/validations/associated.rb +3 -1
  106. data/lib/active_record/validations/uniqueness.rb +48 -58
  107. data/lib/active_record/version.rb +3 -3
  108. data/lib/rails/generators/active_record.rb +6 -0
  109. data/lib/rails/generators/active_record/migration/templates/migration.rb +10 -2
  110. data/lib/rails/generators/active_record/model/model_generator.rb +2 -1
  111. data/lib/rails/generators/active_record/model/templates/migration.rb +6 -5
  112. data/lib/rails/generators/active_record/model/templates/model.rb +2 -0
  113. data/lib/rails/generators/active_record/model/templates/module.rb +2 -0
  114. data/lib/rails/generators/active_record/observer/templates/observer.rb +2 -0
  115. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +2 -1
  116. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +2 -2
  117. metadata +106 -77
  118. checksums.yaml +0 -7
  119. data/lib/active_record/association_preload.rb +0 -431
  120. data/lib/active_record/associations/association_collection.rb +0 -572
  121. data/lib/active_record/associations/association_proxy.rb +0 -304
  122. data/lib/active_record/associations/through_association_scope.rb +0 -160
@@ -0,0 +1,17 @@
1
+ module ActiveRecord
2
+ module Associations
3
+ class Preloader
4
+ class HasMany < CollectionAssociation #:nodoc:
5
+
6
+ def association_key_name
7
+ reflection.foreign_key
8
+ end
9
+
10
+ def owner_key_name
11
+ reflection.active_record_primary_key
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ module ActiveRecord
2
+ module Associations
3
+ class Preloader
4
+ class HasManyThrough < CollectionAssociation #:nodoc:
5
+ include ThroughAssociation
6
+
7
+ def associated_records_by_owner
8
+ super.each do |owner, records|
9
+ records.uniq! if options[:uniq]
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ module ActiveRecord
2
+ module Associations
3
+ class Preloader
4
+ class HasOne < SingularAssociation #:nodoc:
5
+
6
+ def association_key_name
7
+ reflection.foreign_key
8
+ end
9
+
10
+ def owner_key_name
11
+ reflection.active_record_primary_key
12
+ end
13
+
14
+ private
15
+
16
+ def build_scope
17
+ super.order(preload_options[:order] || options[:order])
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ module ActiveRecord
2
+ module Associations
3
+ class Preloader
4
+ class HasOneThrough < SingularAssociation #:nodoc:
5
+ include ThroughAssociation
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ module ActiveRecord
2
+ module Associations
3
+ class Preloader
4
+ class SingularAssociation < Association #:nodoc:
5
+
6
+ private
7
+
8
+ def preload
9
+ associated_records_by_owner.each do |owner, associated_records|
10
+ record = associated_records.first
11
+
12
+ association = owner.association(reflection.name)
13
+ association.target = record
14
+ association.set_inverse_instance(record)
15
+ end
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,67 @@
1
+ module ActiveRecord
2
+ module Associations
3
+ class Preloader
4
+ module ThroughAssociation #:nodoc:
5
+
6
+ def through_reflection
7
+ reflection.through_reflection
8
+ end
9
+
10
+ def source_reflection
11
+ reflection.source_reflection
12
+ end
13
+
14
+ def associated_records_by_owner
15
+ through_records = through_records_by_owner
16
+
17
+ ActiveRecord::Associations::Preloader.new(
18
+ through_records.values.flatten,
19
+ source_reflection.name, options
20
+ ).run
21
+
22
+ through_records.each do |owner, records|
23
+ records.map! { |r| r.send(source_reflection.name) }.flatten!
24
+ records.compact!
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def through_records_by_owner
31
+ ActiveRecord::Associations::Preloader.new(
32
+ owners, through_reflection.name,
33
+ through_options
34
+ ).run
35
+
36
+ Hash[owners.map do |owner|
37
+ through_records = Array.wrap(owner.send(through_reflection.name))
38
+
39
+ # Dont cache the association - we would only be caching a subset
40
+ if reflection.options[:source_type] && through_reflection.collection?
41
+ owner.association(through_reflection.name).reset
42
+ end
43
+
44
+ [owner, through_records]
45
+ end]
46
+ end
47
+
48
+ def through_options
49
+ through_options = {}
50
+
51
+ if options[:source_type]
52
+ through_options[:conditions] = { reflection.foreign_type => options[:source_type] }
53
+ else
54
+ if options[:conditions]
55
+ through_options[:include] = options[:include] || options[:source]
56
+ through_options[:conditions] = options[:conditions]
57
+ end
58
+
59
+ through_options[:order] = options[:order]
60
+ end
61
+
62
+ through_options
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,55 @@
1
+ module ActiveRecord
2
+ module Associations
3
+ class SingularAssociation < Association #:nodoc:
4
+ # Implements the reader method, e.g. foo.bar for Foo.has_one :bar
5
+ def reader(force_reload = false)
6
+ if force_reload
7
+ klass.uncached { reload }
8
+ elsif !loaded? || stale_target?
9
+ reload
10
+ end
11
+
12
+ target
13
+ end
14
+
15
+ # Implements the writer method, e.g. foo.items= for Foo.has_many :items
16
+ def writer(record)
17
+ replace(record)
18
+ end
19
+
20
+ def create(attributes = {}, options = {})
21
+ new_record(:create, attributes, options)
22
+ end
23
+
24
+ def create!(attributes = {}, options = {})
25
+ build(attributes, options).tap { |record| record.save! }
26
+ end
27
+
28
+ def build(attributes = {}, options = {})
29
+ new_record(:build, attributes, options)
30
+ end
31
+
32
+ private
33
+
34
+ def find_target
35
+ scoped.first.tap { |record| set_inverse_instance(record) }
36
+ end
37
+
38
+ # Implemented by subclasses
39
+ def replace(record)
40
+ raise NotImplementedError, "Subclasses must implement a replace(record) method"
41
+ end
42
+
43
+ def set_new_record(record)
44
+ replace(record)
45
+ end
46
+
47
+ def new_record(method, attributes, options)
48
+ attributes = scoped.scope_for_create.merge(attributes || {})
49
+ record = reflection.send("#{method}_association", attributes, options)
50
+ set_new_record(record)
51
+ record
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,80 @@
1
+ module ActiveRecord
2
+ # = Active Record Through Association
3
+ module Associations
4
+ module ThroughAssociation #:nodoc:
5
+
6
+ delegate :source_reflection, :through_reflection, :chain, :to => :reflection
7
+
8
+ protected
9
+
10
+ # We merge in these scopes for two reasons:
11
+ #
12
+ # 1. To get the default_scope conditions for any of the other reflections in the chain
13
+ # 2. To get the type conditions for any STI models in the chain
14
+ def target_scope
15
+ scope = super
16
+ chain[1..-1].each do |reflection|
17
+ scope = scope.merge(reflection.klass.scoped)
18
+ end
19
+ scope
20
+ end
21
+
22
+ private
23
+
24
+ # Construct attributes for :through pointing to owner and associate. This is used by the
25
+ # methods which create and delete records on the association.
26
+ #
27
+ # We only support indirectly modifying through associations which has a belongs_to source.
28
+ # This is the "has_many :tags, :through => :taggings" situation, where the join model
29
+ # typically has a belongs_to on both side. In other words, associations which could also
30
+ # be represented as has_and_belongs_to_many associations.
31
+ #
32
+ # We do not support creating/deleting records on the association where the source has
33
+ # some other type, because this opens up a whole can of worms, and in basically any
34
+ # situation it is more natural for the user to just create or modify their join records
35
+ # directly as required.
36
+ def construct_join_attributes(*records)
37
+ if source_reflection.macro != :belongs_to
38
+ raise HasManyThroughCantAssociateThroughHasOneOrManyReflection.new(owner, reflection)
39
+ end
40
+
41
+ join_attributes = {
42
+ source_reflection.foreign_key =>
43
+ records.map { |record|
44
+ record.send(source_reflection.association_primary_key)
45
+ }
46
+ }
47
+
48
+ if options[:source_type]
49
+ join_attributes[source_reflection.foreign_type] =
50
+ records.map { |record| record.class.base_class.name }
51
+ end
52
+
53
+ if records.count == 1
54
+ Hash[join_attributes.map { |k, v| [k, v.first] }]
55
+ else
56
+ join_attributes
57
+ end
58
+ end
59
+
60
+ # Note: this does not capture all cases, for example it would be crazy to try to
61
+ # properly support stale-checking for nested associations.
62
+ def stale_state
63
+ if through_reflection.macro == :belongs_to
64
+ owner[through_reflection.foreign_key].to_s
65
+ end
66
+ end
67
+
68
+ def foreign_key_present?
69
+ through_reflection.macro == :belongs_to &&
70
+ !owner[through_reflection.foreign_key].nil?
71
+ end
72
+
73
+ def ensure_not_nested
74
+ if reflection.nested?
75
+ raise HasManyThroughNestedAssociationsAreReadonly.new(owner, reflection)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -10,7 +10,18 @@ module ActiveRecord
10
10
  # Generates all the attribute related methods for columns in the database
11
11
  # accessors, mutators and query methods.
12
12
  def define_attribute_methods
13
- super(columns_hash.keys)
13
+ return if attribute_methods_generated?
14
+ super(column_names)
15
+ @attribute_methods_generated = true
16
+ end
17
+
18
+ def attribute_methods_generated?
19
+ @attribute_methods_generated ||= false
20
+ end
21
+
22
+ def undefine_attribute_methods(*args)
23
+ super
24
+ @attribute_methods_generated = false
14
25
  end
15
26
 
16
27
  # Checks whether the method is defined in the model or any of its subclasses
@@ -18,7 +29,11 @@ module ActiveRecord
18
29
  # method is defined by Active Record though.
19
30
  def instance_method_already_implemented?(method_name)
20
31
  method_name = method_name.to_s
21
- @_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 {|m| m.to_s }.to_set
32
+ index = ancestors.index(ActiveRecord::Base) || ancestors.length
33
+ @_defined_class_methods ||= ancestors.first(index).map { |m|
34
+ m.instance_methods(false) | m.private_instance_methods(false)
35
+ }.flatten.map {|m| m.to_s }.to_set
36
+
22
37
  @@_defined_activerecord_methods ||= defined_activerecord_methods
23
38
  raise DangerousAttributeError, "#{method_name} is defined by ActiveRecord" if @@_defined_activerecord_methods.include?(method_name)
24
39
  @_defined_class_methods.include?(method_name)
@@ -27,9 +42,8 @@ module ActiveRecord
27
42
  def defined_activerecord_methods
28
43
  active_record = ActiveRecord::Base
29
44
  super_klass = ActiveRecord::Base.superclass
30
- methods = active_record.public_instance_methods - super_klass.public_instance_methods
31
- methods += active_record.private_instance_methods - super_klass.private_instance_methods
32
- methods += active_record.protected_instance_methods - super_klass.protected_instance_methods
45
+ methods = (active_record.instance_methods - super_klass.instance_methods) +
46
+ (active_record.private_instance_methods - super_klass.private_instance_methods)
33
47
  methods.map {|m| m.to_s }.to_set
34
48
  end
35
49
  end
@@ -13,18 +13,19 @@ module ActiveRecord
13
13
 
14
14
  # Returns a hash of attributes before typecasting and deserialization.
15
15
  def attributes_before_type_cast
16
- Hash[attribute_names.map { |name| [name, read_attribute_before_type_cast(name)] }]
16
+ @attributes
17
17
  end
18
18
 
19
19
  private
20
- # Handle *_before_type_cast for method_missing.
21
- def attribute_before_type_cast(attribute_name)
22
- if attribute_name == 'id'
23
- read_attribute_before_type_cast(self.class.primary_key)
24
- else
25
- read_attribute_before_type_cast(attribute_name)
26
- end
20
+
21
+ # Handle *_before_type_cast for method_missing.
22
+ def attribute_before_type_cast(attribute_name)
23
+ if attribute_name == 'id'
24
+ read_attribute_before_type_cast(self.class.primary_key)
25
+ else
26
+ read_attribute_before_type_cast(attribute_name)
27
27
  end
28
+ end
28
29
  end
29
30
  end
30
31
  end
@@ -1,3 +1,4 @@
1
+ require 'active_support/core_ext/class/attribute'
1
2
  require 'active_support/core_ext/object/blank'
2
3
 
3
4
  module ActiveRecord
@@ -12,7 +13,7 @@ module ActiveRecord
12
13
  raise "You cannot include Dirty after Timestamp"
13
14
  end
14
15
 
15
- superclass_delegating_accessor :partial_updates
16
+ class_attribute :partial_updates
16
17
  self.partial_updates = true
17
18
  end
18
19
 
@@ -21,6 +22,8 @@ module ActiveRecord
21
22
  if status = super
22
23
  @previously_changed = changes
23
24
  @changed_attributes.clear
25
+ elsif IdentityMap.enabled?
26
+ IdentityMap.remove(self)
24
27
  end
25
28
  status
26
29
  end
@@ -31,6 +34,9 @@ module ActiveRecord
31
34
  @previously_changed = changes
32
35
  @changed_attributes.clear
33
36
  end
37
+ rescue
38
+ IdentityMap.remove(self) if IdentityMap.enabled?
39
+ raise
34
40
  end
35
41
 
36
42
  # <tt>reload</tt> the record and clears changed attributes.
@@ -88,7 +94,7 @@ module ActiveRecord
88
94
  end
89
95
 
90
96
  def clone_with_time_zone_conversion_attribute?(attr, old)
91
- old.class.name == "Time" && time_zone_aware_attributes && !skip_time_zone_conversion_for_attributes.include?(attr.to_sym)
97
+ old.class.name == "Time" && time_zone_aware_attributes && !self.skip_time_zone_conversion_for_attributes.include?(attr.to_sym)
92
98
  end
93
99
  end
94
100
  end
@@ -3,17 +3,18 @@ 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
13
14
  # Defines the primary key field -- can be overridden in subclasses. Overwriting will negate any effect of the
14
15
  # primary_key_prefix_type setting, though.
15
16
  def primary_key
16
- reset_primary_key
17
+ @primary_key ||= reset_primary_key
17
18
  end
18
19
 
19
20
  # Returns a quoted version of the primary key name, used to construct SQL statements.
@@ -22,20 +23,36 @@ module ActiveRecord
22
23
  end
23
24
 
24
25
  def reset_primary_key #:nodoc:
25
- key = get_primary_key(base_class.name)
26
+ key = self == base_class ? get_primary_key(base_class.name) :
27
+ base_class.primary_key
28
+
26
29
  set_primary_key(key)
27
30
  key
28
31
  end
29
32
 
30
33
  def get_primary_key(base_name) #:nodoc:
31
- key = 'id'
34
+ return 'id' unless base_name && !base_name.blank?
35
+
32
36
  case primary_key_prefix_type
33
- when :table_name
34
- key = base_name.to_s.foreign_key(false)
35
- when :table_name_with_underscore
36
- key = base_name.to_s.foreign_key
37
+ when :table_name
38
+ base_name.foreign_key(false)
39
+ when :table_name_with_underscore
40
+ base_name.foreign_key
41
+ else
42
+ if ActiveRecord::Base != self && connection.table_exists?(table_name)
43
+ connection.primary_key(table_name)
44
+ else
45
+ 'id'
46
+ end
37
47
  end
38
- key
48
+ end
49
+
50
+ attr_accessor :original_primary_key
51
+
52
+ # Attribute writer for the primary key column
53
+ def primary_key=(value)
54
+ @quoted_primary_key = nil
55
+ @primary_key = value
39
56
  end
40
57
 
41
58
  # Sets the name of the primary key column to use to the given value,
@@ -47,9 +64,12 @@ module ActiveRecord
47
64
  # end
48
65
  def set_primary_key(value = nil, &block)
49
66
  @quoted_primary_key = nil
50
- define_attr_method :primary_key, value, &block
67
+ @primary_key ||= ''
68
+ self.original_primary_key = @primary_key
69
+ value &&= value.to_s
70
+ connection_pool.primary_keys[table_name] = value
71
+ self.primary_key = block_given? ? instance_eval(&block) : value
51
72
  end
52
- alias :primary_key= :set_primary_key
53
73
  end
54
74
  end
55
75
  end