From 2b82708b0efb3a3458e8177beab58f0c585788ae Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 2 Sep 2009 13:57:33 -0700 Subject: [PATCH] Revert "Assert primary key does not exist in habtm when the association is defined, instead of doing that everytime a record is inserted." Test failures on PostgreSQL. [#3128] This reverts commit 594a281d663dd8a7801651f4aea7e5b7f4f02548. --- .../lib/active_record/associations.rb | 24 +++++++++---------- .../has_and_belongs_to_many_association.rb | 16 +++++++++++++ .../associations/habtm_join_table_test.rb | 16 +++++++++++-- activerecord/test/fixtures/edges.yml | 3 ++- activerecord/test/schema/schema.rb | 2 +- 5 files changed, 45 insertions(+), 16 deletions(-) diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index c68c8cc2ad6e..a08119c6f214 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -53,12 +53,6 @@ def initialize(owner, reflection) end end - class HasAndBelongsToManyAssociationWithPrimaryKeyError < ActiveRecordError #:nodoc: - def initialize(reflection) - super("Primary key is not allowed in a has_and_belongs_to_many join table (#{reflection.options[:join_table]}).") - end - end - class HasAndBelongsToManyAssociationForeignKeyNeeded < ActiveRecordError #:nodoc: def initialize(reflection) super("Cannot create self referential has_and_belongs_to_many association on '#{reflection.class_name rescue nil}##{reflection.name rescue nil}'. :association_foreign_key cannot be the same as the :foreign_key.") @@ -1589,19 +1583,16 @@ def create_belongs_to_reflection(association_id, options) def create_has_and_belongs_to_many_reflection(association_id, options, &extension) options.assert_valid_keys(valid_keys_for_has_and_belongs_to_many_association) + options[:extend] = create_extension_modules(association_id, extension, options[:extend]) reflection = create_reflection(:has_and_belongs_to_many, association_id, options, self) - reflection.options[:join_table] ||= join_table_name(undecorated_table_name(self.to_s), undecorated_table_name(reflection.class_name)) - + if reflection.association_foreign_key == reflection.primary_key_name raise HasAndBelongsToManyAssociationForeignKeyNeeded.new(reflection) end - if connection.supports_primary_key? && - (connection.primary_key(reflection.options[:join_table]) rescue false) - raise HasAndBelongsToManyAssociationWithPrimaryKeyError.new(reflection) - end + reflection.options[:join_table] ||= join_table_name(undecorated_table_name(self.to_s), undecorated_table_name(reflection.class_name)) reflection end @@ -1610,6 +1601,15 @@ def reflect_on_included_associations(associations) [ associations ].flatten.collect { |association| reflect_on_association(association.to_s.intern) } end + def guard_against_unlimitable_reflections(reflections, options) + if (options[:offset] || options[:limit]) && !using_limitable_reflections?(reflections) + raise( + ConfigurationError, + "You can not use offset and limit together with has_many or has_and_belongs_to_many associations" + ) + end + end + def select_all_rows(options, join_dependency) connection.select_all( construct_finder_sql_with_included_associations(options, join_dependency), 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 af9ce3dfb253..cb60baa7cc82 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 @@ def reset_column_information @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 @@ def count_records 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/test/cases/associations/habtm_join_table_test.rb b/activerecord/test/cases/associations/habtm_join_table_test.rb index 745f169ad7c2..bf3e04c3eb3f 100644 --- a/activerecord/test/cases/associations/habtm_join_table_test.rb +++ b/activerecord/test/cases/associations/habtm_join_table_test.rb @@ -36,9 +36,21 @@ def teardown uses_transaction :test_should_raise_exception_when_join_table_has_a_primary_key def test_should_raise_exception_when_join_table_has_a_primary_key if ActiveRecord::Base.connection.supports_primary_key? - assert_raise ActiveRecord::HasAndBelongsToManyAssociationWithPrimaryKeyError do - MyReader.has_and_belongs_to_many :my_books + assert_raise ActiveRecord::ConfigurationError do + jaime = MyReader.create(:name=>"Jaime") + jaime.my_books << MyBook.create(:name=>'Great Expectations') end end end + + uses_transaction :test_should_cache_result_of_primary_key_check + def test_should_cache_result_of_primary_key_check + if ActiveRecord::Base.connection.supports_primary_key? + ActiveRecord::Base.connection.stubs(:primary_key).with('my_books_my_readers').returns(false).once + weaz = MyReader.create(:name=>'Weaz') + + weaz.my_books << MyBook.create(:name=>'Great Expectations') + weaz.my_books << MyBook.create(:name=>'Greater Expectations') + end + end end diff --git a/activerecord/test/fixtures/edges.yml b/activerecord/test/fixtures/edges.yml index b804f7b6a6c5..c16c70dd2fcd 100644 --- a/activerecord/test/fixtures/edges.yml +++ b/activerecord/test/fixtures/edges.yml @@ -1,5 +1,6 @@ <% (1..4).each do |id| %> edge_<%= id %>: + id: <%= id %> source_id: <%= id %> sink_id: <%= id + 1 %> -<% end %> +<% end %> \ No newline at end of file diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index da71aace7f16..87fad0ebcee8 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -153,7 +153,7 @@ def create_table(*args, &block) t.integer :access_level, :default => 1 end - create_table :edges, :force => true, :id => false do |t| + create_table :edges, :force => true do |t| t.column :source_id, :integer, :null => false t.column :sink_id, :integer, :null => false end