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:
parent
d2d464e26e
commit
f0602214e0
@ -29,6 +29,10 @@ def count_records
|
|||||||
end
|
end
|
||||||
|
|
||||||
def insert_record(record, force = true, validate = true)
|
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 record.new_record?
|
||||||
if force
|
if force
|
||||||
record.save!
|
record.save!
|
||||||
|
@ -56,6 +56,13 @@ def supports_migrations?
|
|||||||
false
|
false
|
||||||
end
|
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+
|
# Does this adapter support using DISTINCT within COUNT? This is +true+
|
||||||
# for all adapters except sqlite.
|
# for all adapters except sqlite.
|
||||||
def supports_count_distinct?
|
def supports_count_distinct?
|
||||||
|
@ -208,6 +208,10 @@ def supports_migrations? #:nodoc:
|
|||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def supports_primary_key? #:nodoc:
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
def supports_savepoints? #:nodoc:
|
def supports_savepoints? #:nodoc:
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
@ -550,6 +554,12 @@ def pk_and_sequence_for(table) #:nodoc:
|
|||||||
keys.length == 1 ? [keys.first, nil] : nil
|
keys.length == 1 ? [keys.first, nil] : nil
|
||||||
end
|
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
|
def case_sensitive_equality_operator
|
||||||
"= BINARY"
|
"= BINARY"
|
||||||
end
|
end
|
||||||
|
@ -250,6 +250,11 @@ def supports_migrations?
|
|||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Does PostgreSQL support finding primary key on non-ActiveRecord tables?
|
||||||
|
def supports_primary_key? #:nodoc:
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
# Does PostgreSQL support standard conforming strings?
|
# Does PostgreSQL support standard conforming strings?
|
||||||
def supports_standard_conforming_strings?
|
def supports_standard_conforming_strings?
|
||||||
# Temporarily set the client message level above error to prevent unintentional
|
# Temporarily set the client message level above error to prevent unintentional
|
||||||
@ -811,6 +816,12 @@ def pk_and_sequence_for(table) #:nodoc:
|
|||||||
nil
|
nil
|
||||||
end
|
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.
|
# Renames a table.
|
||||||
def rename_table(name, new_name)
|
def rename_table(name, new_name)
|
||||||
execute "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_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
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def supports_primary_key? #:nodoc:
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
def requires_reloading?
|
def requires_reloading?
|
||||||
true
|
true
|
||||||
end
|
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
|
def test_instance_destroy_should_quote_pkey
|
||||||
assert_nothing_raised { MixedCaseMonkey.find(1).destroy }
|
assert_nothing_raised { MixedCaseMonkey.find(1).destroy }
|
||||||
end
|
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
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user