aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
authorYehuda Katz <wycats@gmail.com>2009-07-19 13:21:17 -0700
committerYehuda Katz <wycats@gmail.com>2009-07-19 13:21:17 -0700
commit37658f15bb88e054635a496327a4a82bb50fd5d5 (patch)
tree78f3d350394910270d1eca3537857111e8f14fe8 /activerecord/lib
parentf2f5cdc8bcd9df3a297ea02b80dbdb21790de732 (diff)
parent17d5cc12b9f8d0d78a081d231e7e0c5ec9df1104 (diff)
downloadrails-37658f15bb88e054635a496327a4a82bb50fd5d5.tar.gz
rails-37658f15bb88e054635a496327a4a82bb50fd5d5.tar.bz2
rails-37658f15bb88e054635a496327a4a82bb50fd5d5.zip
Merge branch 'master' of git@github.com:rails/rails
Diffstat (limited to 'activerecord/lib')
-rwxr-xr-xactiverecord/lib/active_record/associations.rb18
-rw-r--r--activerecord/lib/active_record/associations/belongs_to_association.rb26
-rw-r--r--activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb6
-rw-r--r--activerecord/lib/active_record/autosave_association.rb3
4 files changed, 43 insertions, 10 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 10ecd068d3..934beb7d39 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -963,6 +963,8 @@ module ActiveRecord
# of the association with an "_id" suffix. So a class that defines a <tt>belongs_to :person</tt> association will use
# "person_id" as the default <tt>:foreign_key</tt>. Similarly, <tt>belongs_to :favorite_person, :class_name => "Person"</tt>
# will use a foreign key of "favorite_person_id".
+ # [:primary_key]
+ # Specify the method that returns the primary key of associated object used for the association. By default this is id.
# [:dependent]
# If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method. This option should not be specified when
@@ -993,6 +995,7 @@ module ActiveRecord
#
# Option examples:
# belongs_to :firm, :foreign_key => "client_of"
+ # belongs_to :person, :primary_key => "name", :foreign_key => "person_name"
# belongs_to :author, :class_name => "Person", :foreign_key => "author_id"
# belongs_to :valid_coupon, :class_name => "Coupon", :foreign_key => "coupon_id",
# :conditions => 'discounts > #{payments_count}'
@@ -1273,9 +1276,16 @@ module ActiveRecord
if send(reflection.name).loaded? || reflection.options[:finder_sql]
send(reflection.name).map(&:id)
else
- send(reflection.name).all(:select => "#{reflection.quoted_table_name}.#{reflection.klass.primary_key}").map(&:id)
+ if reflection.through_reflection && reflection.source_reflection.belongs_to?
+ through = reflection.through_reflection
+ primary_key = reflection.source_reflection.primary_key_name
+ send(through.name).all(:select => "DISTINCT #{through.quoted_table_name}.#{primary_key}").map!(&:"#{primary_key}")
+ else
+ send(reflection.name).all(:select => "#{reflection.quoted_table_name}.#{reflection.klass.primary_key}").map!(&:id)
+ end
end
end
+
end
def collection_accessor_methods(reflection, association_proxy_class, writer = true)
@@ -1321,14 +1331,14 @@ module ActiveRecord
method_name = "belongs_to_counter_cache_after_create_for_#{reflection.name}".to_sym
define_method(method_name) do
association = send(reflection.name)
- association.class.increment_counter(cache_column, send(reflection.primary_key_name)) unless association.nil?
+ association.class.increment_counter(cache_column, association.id) unless association.nil?
end
after_create(method_name)
method_name = "belongs_to_counter_cache_before_destroy_for_#{reflection.name}".to_sym
define_method(method_name) do
association = send(reflection.name)
- association.class.decrement_counter(cache_column, send(reflection.primary_key_name)) unless association.nil?
+ association.class.decrement_counter(cache_column, association.id) unless association.nil?
end
before_destroy(method_name)
@@ -1520,7 +1530,7 @@ module ActiveRecord
mattr_accessor :valid_keys_for_belongs_to_association
@@valid_keys_for_belongs_to_association = [
- :class_name, :foreign_key, :foreign_type, :remote, :select, :conditions,
+ :class_name, :primary_key, :foreign_key, :foreign_type, :remote, :select, :conditions,
:include, :dependent, :counter_cache, :extend, :polymorphic, :readonly,
:validate, :touch, :inverse_of
]
diff --git a/activerecord/lib/active_record/associations/belongs_to_association.rb b/activerecord/lib/active_record/associations/belongs_to_association.rb
index c88575048a..628033c87a 100644
--- a/activerecord/lib/active_record/associations/belongs_to_association.rb
+++ b/activerecord/lib/active_record/associations/belongs_to_association.rb
@@ -14,7 +14,7 @@ module ActiveRecord
if record.nil?
if counter_cache_name && !@owner.new_record?
- @reflection.klass.decrement_counter(counter_cache_name, @owner[@reflection.primary_key_name]) if @owner[@reflection.primary_key_name]
+ @reflection.klass.decrement_counter(counter_cache_name, previous_record_id) if @owner[@reflection.primary_key_name]
end
@target = @owner[@reflection.primary_key_name] = nil
@@ -27,7 +27,7 @@ module ActiveRecord
end
@target = (AssociationProxy === record ? record.target : record)
- @owner[@reflection.primary_key_name] = record.id unless record.new_record?
+ @owner[@reflection.primary_key_name] = record_id(record) unless record.new_record?
@updated = true
end
@@ -43,13 +43,18 @@ module ActiveRecord
private
def find_target
- the_target = @reflection.klass.find(
+ find_method = if @reflection.options[:primary_key]
+ "find_by_#{@reflection.options[:primary_key]}"
+ else
+ "find"
+ end
+ the_target = @reflection.klass.send(find_method,
@owner[@reflection.primary_key_name],
:select => @reflection.options[:select],
:conditions => conditions,
:include => @reflection.options[:include],
:readonly => @reflection.options[:readonly]
- )
+ ) if @owner[@reflection.primary_key_name]
set_inverse_instance(the_target, @owner)
the_target
end
@@ -63,6 +68,19 @@ module ActiveRecord
def we_can_set_the_inverse_on_this?(record)
@reflection.has_inverse? && @reflection.inverse_of.macro == :has_one
end
+
+ def record_id(record)
+ record.send(@reflection.options[:primary_key] || :id)
+ end
+
+ def previous_record_id
+ @previous_record_id ||= if @reflection.options[:primary_key]
+ previous_record = @owner.send(@reflection.name)
+ previous_record.nil? ? nil : previous_record.id
+ else
+ @owner[@reflection.primary_key_name]
+ end
+ end
end
end
end
diff --git a/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb b/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb
index d8146daa54..67e18d692d 100644
--- a/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb
+++ b/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb
@@ -7,7 +7,7 @@ module ActiveRecord
else
@target = (AssociationProxy === record ? record.target : record)
- @owner[@reflection.primary_key_name] = record.id
+ @owner[@reflection.primary_key_name] = record_id(record)
@owner[@reflection.options[:foreign_type]] = record.class.base_class.name.to_s
@updated = true
@@ -41,6 +41,10 @@ module ActiveRecord
!@owner[@reflection.primary_key_name].nil?
end
+ def record_id(record)
+ record.send(@reflection.options[:primary_key] || :id)
+ end
+
def association_class
@owner[@reflection.options[:foreign_type]] ? @owner[@reflection.options[:foreign_type]].constantize : nil
end
diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb
index a540570f42..c1bc8423a9 100644
--- a/activerecord/lib/active_record/autosave_association.rb
+++ b/activerecord/lib/active_record/autosave_association.rb
@@ -339,7 +339,8 @@ module ActiveRecord
association.save(!autosave) if association.new_record? || autosave
if association.updated?
- self[reflection.primary_key_name] = association.id
+ association_id = association.send(reflection.options[:primary_key] || :id)
+ self[reflection.primary_key_name] = association_id
# TODO: Removing this code doesn't seem to matter…
if reflection.options[:polymorphic]
self[reflection.options[:foreign_type]] = association.class.base_class.name.to_s