Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Assert primary key does not exist in habtm when the association is de…
…fined, instead of doing that everytime a record is inserted.

[#3128 state:committed]

Signed-off-by: Jeremy Kemper <jeremy@bitsweat.net>
  • Loading branch information
josevalim authored and jeremy committed Sep 1, 2009
1 parent 6bf1777 commit 594a281
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 45 deletions.
24 changes: 12 additions & 12 deletions activerecord/lib/active_record/associations.rb
Expand Up @@ -53,6 +53,12 @@ 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.")
Expand Down Expand Up @@ -1583,16 +1589,19 @@ 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

reflection.options[:join_table] ||= join_table_name(undecorated_table_name(self.to_s), undecorated_table_name(reflection.class_name))
if connection.supports_primary_key? &&
(connection.primary_key(reflection.options[:join_table]) rescue false)
raise HasAndBelongsToManyAssociationWithPrimaryKeyError.new(reflection)
end

reflection
end
Expand All @@ -1601,15 +1610,6 @@ 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),
Expand Down
@@ -1,11 +1,6 @@
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
Expand All @@ -22,12 +17,6 @@ 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
Expand All @@ -40,11 +29,6 @@ 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!
Expand Down
16 changes: 2 additions & 14 deletions activerecord/test/cases/associations/habtm_join_table_test.rb
Expand Up @@ -36,21 +36,9 @@ 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::ConfigurationError do
jaime = MyReader.create(:name=>"Jaime")
jaime.my_books << MyBook.create(:name=>'Great Expectations')
assert_raise ActiveRecord::HasAndBelongsToManyAssociationWithPrimaryKeyError do
MyReader.has_and_belongs_to_many :my_books
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
3 changes: 1 addition & 2 deletions activerecord/test/fixtures/edges.yml
@@ -1,6 +1,5 @@
<% (1..4).each do |id| %>
edge_<%= id %>:
id: <%= id %>
source_id: <%= id %>
sink_id: <%= id + 1 %>
<% end %>
<% end %>
2 changes: 1 addition & 1 deletion activerecord/test/schema/schema.rb
Expand Up @@ -153,7 +153,7 @@ def create_table(*args, &block)
t.integer :access_level, :default => 1
end

create_table :edges, :force => true do |t|
create_table :edges, :force => true, :id => false do |t|
t.column :source_id, :integer, :null => false
t.column :sink_id, :integer, :null => false
end
Expand Down

0 comments on commit 594a281

Please sign in to comment.