aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/associations
diff options
context:
space:
mode:
authorEmilio Tagua <miloops@gmail.com>2009-08-10 18:07:33 -0300
committerEmilio Tagua <miloops@gmail.com>2009-08-10 18:07:33 -0300
commit0e2fbd80e2420329738b891240d44a056cea1de4 (patch)
tree5b16755670be58e168b5e86e2cdcb43ee5aa3918 /activerecord/lib/active_record/associations
parenteb3ae44ccaff1dc63eb31bf86d8db07c88ddc413 (diff)
parent600a89f2082beadf4af9fe140a1a2ae56386cd49 (diff)
downloadrails-0e2fbd80e2420329738b891240d44a056cea1de4.tar.gz
rails-0e2fbd80e2420329738b891240d44a056cea1de4.tar.bz2
rails-0e2fbd80e2420329738b891240d44a056cea1de4.zip
Merge commit 'rails/master'
Conflicts: activerecord/lib/active_record/calculations.rb activerecord/lib/active_record/connection_adapters/mysql_adapter.rb activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
Diffstat (limited to 'activerecord/lib/active_record/associations')
-rw-r--r--activerecord/lib/active_record/associations/association_collection.rb1
-rw-r--r--activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb16
-rw-r--r--activerecord/lib/active_record/associations/has_many_association.rb1
-rw-r--r--activerecord/lib/active_record/associations/has_many_through_association.rb8
-rw-r--r--activerecord/lib/active_record/associations/has_one_through_association.rb12
-rw-r--r--activerecord/lib/active_record/associations/through_association_scope.rb2
6 files changed, 34 insertions, 6 deletions
diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb
index e67ccfb228..1b7bf42b91 100644
--- a/activerecord/lib/active_record/associations/association_collection.rb
+++ b/activerecord/lib/active_record/associations/association_collection.rb
@@ -208,6 +208,7 @@ module ActiveRecord
# Note that this method will _always_ remove records from the database
# ignoring the +:dependent+ option.
def destroy(*records)
+ records = find(records) if records.any? {|record| record.kind_of?(Fixnum) || record.kind_of?(String)}
remove_records(records) do |records, old_records|
old_records.each { |record| record.destroy }
end
diff --git a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb
index fd23e59e82..d91c555dad 100644
--- a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb
+++ b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb
@@ -1,6 +1,11 @@
module ActiveRecord
module Associations
class HasAndBelongsToManyAssociation < AssociationCollection #:nodoc:
+ def initialize(owner, reflection)
+ super
+ @primary_key_list = {}
+ end
+
def create(attributes = {})
create_record(attributes) { |record| insert_record(record) }
end
@@ -17,6 +22,12 @@ module ActiveRecord
@reflection.reset_column_information
end
+ def has_primary_key?
+ return @has_primary_key unless @has_primary_key.nil?
+ @has_primary_key = (ActiveRecord::Base.connection.supports_primary_key? &&
+ ActiveRecord::Base.connection.primary_key(@reflection.options[:join_table]))
+ end
+
protected
def construct_find_options!(options)
options[:joins] = @join_sql
@@ -29,6 +40,11 @@ module ActiveRecord
end
def insert_record(record, force = true, validate = true)
+ if has_primary_key?
+ raise ActiveRecord::ConfigurationError,
+ "Primary key is not allowed in a has_and_belongs_to_many join table (#{@reflection.options[:join_table]})."
+ end
+
if record.new_record?
if force
record.save!
diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb
index e4b631bc54..73d3c23cd3 100644
--- a/activerecord/lib/active_record/associations/has_many_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_association.rb
@@ -74,6 +74,7 @@ module ActiveRecord
"#{@reflection.primary_key_name} = NULL",
"#{@reflection.primary_key_name} = #{owner_quoted_id} AND #{@reflection.klass.primary_key} IN (#{ids})"
)
+ @owner.class.update_counters(@owner.id, cached_counter_attribute_name => -records.size) if has_cached_counter?
end
end
diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb
index 2ed92ca1ba..6004751dc9 100644
--- a/activerecord/lib/active_record/associations/has_many_through_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_through_association.rb
@@ -20,7 +20,11 @@ module ActiveRecord
ensure_owner_is_not_new
transaction do
- self << (object = attrs ? @reflection.klass.send(:with_scope, :create => attrs) { @reflection.create_association } : @reflection.create_association)
+ object = attrs ? @reflection.klass.send(:with_scope, :create => attrs) { @reflection.create_association } : @reflection.create_association
+ raise_on_type_mismatch(object)
+ add_record_to_target_with_callbacks(object) do |r|
+ insert_record(object, false)
+ end
object
end
end
@@ -54,7 +58,7 @@ module ActiveRecord
options[:select] = construct_select(options[:select])
options[:from] ||= construct_from
options[:joins] = construct_joins(options[:joins])
- options[:include] = @reflection.source_reflection.options[:include] if options[:include].nil?
+ options[:include] = @reflection.source_reflection.options[:include] if options[:include].nil? && @reflection.source_reflection.options[:include]
end
def insert_record(record, force = true, validate = true)
diff --git a/activerecord/lib/active_record/associations/has_one_through_association.rb b/activerecord/lib/active_record/associations/has_one_through_association.rb
index 830aa1808a..a79bf943d1 100644
--- a/activerecord/lib/active_record/associations/has_one_through_association.rb
+++ b/activerecord/lib/active_record/associations/has_one_through_association.rb
@@ -18,9 +18,15 @@ module ActiveRecord
current_object = @owner.send(@reflection.through_reflection.name)
if current_object
- new_value ? current_object.update_attributes(construct_join_attributes(new_value)) : current_object.destroy
- else
- @owner.send(@reflection.through_reflection.name, klass.send(:create, construct_join_attributes(new_value))) if new_value
+ new_value ? current_object.update_attributes(construct_join_attributes(new_value)) : current_object.destroy
+ elsif new_value
+ if @owner.new_record?
+ self.target = new_value
+ through_association = @owner.send(:association_instance_get, @reflection.through_reflection.name)
+ through_association.build(construct_join_attributes(new_value))
+ else
+ @owner.send(@reflection.through_reflection.name, klass.create(construct_join_attributes(new_value)))
+ end
end
end
diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb
index c172e7b8f9..1924156e2a 100644
--- a/activerecord/lib/active_record/associations/through_association_scope.rb
+++ b/activerecord/lib/active_record/associations/through_association_scope.rb
@@ -93,7 +93,7 @@ module ActiveRecord
# Construct attributes for :through pointing to owner and associate.
def construct_join_attributes(associate)
# TODO: revist this to allow it for deletion, supposing dependent option is supported
- raise ActiveRecord::HasManyThroughCantAssociateThroughHasManyReflection.new(@owner, @reflection) if @reflection.source_reflection.macro == :has_many
+ raise ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection.new(@owner, @reflection) if [:has_one, :has_many].include?(@reflection.source_reflection.macro)
join_attributes = construct_owner_attributes(@reflection.through_reflection).merge(@reflection.source_reflection.primary_key_name => associate.id)