raises exception (ActiveRecord::ConfigurationError with message) on habtm association creation if join table contains a primary key

Signed-off-by: Jeremy Kemper <jeremy@bitsweat.net>
This commit is contained in:
Jaime Bellmyer 2009-02-26 09:48:58 -06:00 committed by Jeremy Kemper
parent d2d464e26e
commit f0602214e0
7 changed files with 99 additions and 0 deletions

@ -29,6 +29,10 @@ def count_records
end
def insert_record(record, force = true, validate = true)
if ActiveRecord::Base.connection.supports_primary_key? && ActiveRecord::Base.connection.primary_key(@reflection.options[:join_table])
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!

@ -56,6 +56,13 @@ def supports_migrations?
false
end
# Can this adapter determine the primary key for tables not attached
# to an ActiveRecord class, such as join tables? Backend specific, as
# the abstract adapter always returns +false+.
def supports_primary_key?
false
end
# Does this adapter support using DISTINCT within COUNT? This is +true+
# for all adapters except sqlite.
def supports_count_distinct?

@ -208,6 +208,10 @@ def supports_migrations? #:nodoc:
true
end
def supports_primary_key? #:nodoc:
true
end
def supports_savepoints? #:nodoc:
true
end
@ -550,6 +554,12 @@ def pk_and_sequence_for(table) #:nodoc:
keys.length == 1 ? [keys.first, nil] : nil
end
# Returns just a table's primary key
def primary_key(table)
pk_and_sequence = pk_and_sequence_for(table)
pk_and_sequence && pk_and_sequence.first
end
def case_sensitive_equality_operator
"= BINARY"
end

@ -250,6 +250,11 @@ def supports_migrations?
true
end
# Does PostgreSQL support finding primary key on non-ActiveRecord tables?
def supports_primary_key? #:nodoc:
true
end
# Does PostgreSQL support standard conforming strings?
def supports_standard_conforming_strings?
# Temporarily set the client message level above error to prevent unintentional
@ -811,6 +816,12 @@ def pk_and_sequence_for(table) #:nodoc:
nil
end
# Returns just a table's primary key
def primary_key(table)
pk_and_sequence = pk_and_sequence_for(table)
pk_and_sequence && pk_and_sequence.first
end
# Renames a table.
def rename_table(name, new_name)
execute "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}"

@ -101,6 +101,10 @@ def supports_migrations? #:nodoc:
true
end
def supports_primary_key? #:nodoc:
true
end
def requires_reloading?
true
end

@ -0,0 +1,45 @@
require 'cases/helper'
class MyReader < ActiveRecord::Base
has_and_belongs_to_many :my_books
end
class MyBook < ActiveRecord::Base
has_and_belongs_to_many :my_readers
end
class JoinTableTest < ActiveRecord::TestCase
def setup
ActiveRecord::Base.connection.create_table :my_books, :force => true do |t|
t.string :name
end
assert ActiveRecord::Base.connection.table_exists?(:my_books)
ActiveRecord::Base.connection.create_table :my_readers, :force => true do |t|
t.string :name
end
assert ActiveRecord::Base.connection.table_exists?(:my_readers)
ActiveRecord::Base.connection.create_table :my_books_my_readers, :force => true do |t|
t.integer :my_book_id
t.integer :my_reader_id
end
assert ActiveRecord::Base.connection.table_exists?(:my_books_my_readers)
end
def teardown
ActiveRecord::Base.connection.drop_table :my_books
ActiveRecord::Base.connection.drop_table :my_readers
ActiveRecord::Base.connection.drop_table :my_books_my_readers
end
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::ConfigurationError do
jaime = MyReader.create(:name=>"Jaime")
jaime.my_books << MyBook.create(:name=>'Great Expectations')
end
end
end
end

@ -98,4 +98,22 @@ def test_instance_update_should_quote_pkey
def test_instance_destroy_should_quote_pkey
assert_nothing_raised { MixedCaseMonkey.find(1).destroy }
end
def test_supports_primary_key
assert_nothing_raised NoMethodError do
ActiveRecord::Base.connection.supports_primary_key?
end
end
def test_primary_key_returns_value_if_it_exists
if ActiveRecord::Base.connection.supports_primary_key?
assert_equal 'id', ActiveRecord::Base.connection.primary_key('developers')
end
end
def test_primary_key_returns_nil_if_it_does_not_exist
if ActiveRecord::Base.connection.supports_primary_key?
assert_nil ActiveRecord::Base.connection.primary_key('developers_projects')
end
end
end