Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #9774 (new defect)

Opened 2 years ago

Last modified 2 years ago

HABTM inserts empty rows into join table when using non-standard column names

Reported by: rdobbs Assigned to: core
Priority: normal Milestone: 2.x
Component: ActiveRecord Version: 1.2.3
Severity: minor Keywords: habtm activerecord
Cc:

Description

Here is an odd one, and I have made up a test case for it. After creating or updating a record that has a habtm relationship, and selecting one of the HABTM-dervied checkboxes, it attempts to INSERT a empty record into the join table.

I'm using a modified version of the books and authors classes as an example. I have purposefully used different conventions, as it appears to be the source of the issue. The schema I'm trying to use AR on doesn't match RoR convention 100%, but it should work.

book.rb:

class Book < ActiveRecord::Base
          has_and_belongs_to_many :authors, :class_name => "Author",
                :table_name => 'authors' , :join_table=>'books_join',
                :foreign_key => :booksId, :association_foreign_key => :authorsId
  def to_s
        "#{typename} | #{description}"
  end
end

author.rb:

class Author < ActiveRecord::Base
  has_and_belongs_to_many :books, :class_name => "Book", :table_name => 'books',
        :join_table=>'books_join', :foreign_key => :authorsId,
        :association_foreign_key => :booksId
  def to_s
        "#{typename} | #{description}"
  end
end

books_controller.rb:

class BooksController < ApplicationController
        layout "user"
        active_scaffold :books do |c|
                c.columns[:authors].form_ui = :select
        end
end

001_create_books.rb:

class CreateBooks < ActiveRecord::Migration
  def self.up
    create_table :books do |t|
            t.column :typename, :string, :null => false
            t.column :description, :string, :null => false
    end
  end

  def self.down
    drop_table :books
  end
end

002_create_authors.rb:

class CreateAuthors < ActiveRecord::Migration
  def self.up
    create_table :authors do |t|
            t.column :typename, :string, :null => false
            t.column :description, :string, :null => false
    end
  end

  def self.down
    drop_table :authors
  end
end

003_create_books_join.rb:

class CreateBooksJoin < ActiveRecord::Migration
        def self.up
                create_table :books_join, :id => false do |t|
                        t.column :booksId, :integer
                        t.column :authorsId, :integer
                end
        end

        def self.down
                drop_table :books_join
        end
end

The log:

  SQL (0.000000)   BEGIN
  SQL (0.000000)   INSERT INTO books (`description`, `typename`) VALUES('Test Description', 'Test Book')
  SQL (0.050000)   COMMIT
  SQL (0.000000)   BEGIN
  SQL (0.000000)   INSERT INTO authors (`description`, `typename`) VALUES('Test Author', 'Test Author')
  SQL (0.050000)   COMMIT
  Join Table Columns (0.000000)   SHOW FIELDS FROM books_join
  Author Load (0.000000)   SELECT * FROM authors INNER JOIN books_join ON authors.id = books_join.authorsId WHERE (books_join.booksId = 4 ) 
  SQL (0.000000)   BEGIN
  books_join Columns (0.000000)   SHOW FIELDS FROM books_join
  SQL (0.000000)   INSERT INTO books_join () VALUES ()
  SQL (0.050000)   COMMIT

Change History

10/03/07 19:17:47 changed by rdobbs

Oh, and the script:

a = Author.new(:typename => "Test Author", :description => "Test Author")
b = Book.new(:typename => "Test Book", :description => "Test Description")
a.save
b.save
b.authors << a
b.save

10/03/07 19:41:35 changed by rdobbs

  • severity changed from major to minor.

Solved, PEBKC. I was using the symbols instead of strings for the foreign_key and association_foreign_key parameters. I'm not marking this invalid just yet, since I think AR shouldn't generate SQL statements like:

INSERT INTO books_join () VALUES ()

...or at least should have thrown an Exception. If not, feel free to mark Invalid!