From e9fb6d04bdfbe3dfc4ba1a3cf442ec5d25764300 Mon Sep 17 00:00:00 2001
From: Jon Leighton <j@jonathanleighton.com>
Date: Thu, 1 Dec 2011 21:55:59 +0000
Subject: Add test for read_attribute(:id) with non-standard PK.

Also make it actually work.

It slows down all read_attribute accesses to map 'id' to whatever the PK
actually is, inside read_attribute. So instead make sure the necessary
methods are defined and that they redirect wherever they need to go.
---
 .../lib/active_record/attribute_methods/primary_key.rb     | 14 ++++++++++++++
 activerecord/lib/active_record/attribute_methods/read.rb   |  8 ++++----
 2 files changed, 18 insertions(+), 4 deletions(-)

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record/attribute_methods/primary_key.rb b/activerecord/lib/active_record/attribute_methods/primary_key.rb
index 98aa1ed225..c756924186 100644
--- a/activerecord/lib/active_record/attribute_methods/primary_key.rb
+++ b/activerecord/lib/active_record/attribute_methods/primary_key.rb
@@ -25,6 +25,20 @@ module ActiveRecord
       end
 
       module ClassMethods
+        def define_method_attribute(attr_name)
+          super
+
+          if attr_name == primary_key && attr_name != 'id'
+            generated_attribute_methods.send(:alias_method, :id, primary_key)
+            generated_attribute_methods.module_eval <<-CODE, __FILE__, __LINE__
+              def self.attribute_id(v, attributes, attributes_cache, attr_name)
+                attr_name = '#{primary_key}'
+                send(:'attribute_#{attr_name}', attributes[attr_name], attributes, attributes_cache, attr_name)
+              end
+            CODE
+          end
+        end
+
         def dangerous_attribute_method?(method_name)
           super && !['id', 'id=', 'id?'].include?(method_name)
         end
diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb
index 41cd194c92..2fe9968faf 100644
--- a/activerecord/lib/active_record/attribute_methods/read.rb
+++ b/activerecord/lib/active_record/attribute_methods/read.rb
@@ -58,7 +58,7 @@ module ActiveRecord
                   #{internal}
                 end
 
-                def self.attribute_#{attr_name}(v, attributes_cache, attr_name)
+                def self.attribute_#{attr_name}(v, attributes, attributes_cache, attr_name)
                   #{external}
                 end
               STR
@@ -68,7 +68,7 @@ module ActiveRecord
                   eval(internal)
                 end
 
-                singleton_class.send(:define_method, "attribute_#{attr_name}") do |v, attributes_cache, attr_name|
+                singleton_class.send(:define_method, "attribute_#{attr_name}") do |v, attributes, attributes_cache, attr_name|
                   eval(external)
                 end
               end
@@ -117,8 +117,8 @@ module ActiveRecord
         methods   = self.class.generated_attribute_methods
 
         if methods.respond_to?(accessor)
-          if @attributes.has_key?(attr_name)
-            methods.send(accessor, @attributes[attr_name], @attributes_cache, attr_name)
+          if @attributes.has_key?(attr_name) || attr_name == 'id'
+            methods.send(accessor, @attributes[attr_name], @attributes, @attributes_cache, attr_name)
           end
         elsif !self.class.attribute_methods_generated?
           # If we haven't generated the caster methods yet, do that and
-- 
cgit v1.2.3