HABTM Woes

I’m having a hell of a time getting HABTM working as advertised.

I’ve got my models: Person and Alias.

class Person < ActiveRecord::Base
has_and_belongs_to_many :aliases
end

class Alias < ActiveRecord::Base
has_and_belongs_to_many :people
end

I’ve built my sqlite3 database using the following migration:

class CreateAndAssociatePeopleAndAliases < ActiveRecord::Migration
def self.up
create_table :people do |t|

  t.column :first_name, :string
  t.column :last_name,  :string
end

create_table :aliases do |t|
  t.column :name, :string
end

create_table :people_aliases, {:id => false} do |t|

  t.column :person_id, :integer
  t.column :alias_id,  :integer
end

end

def self.down
drop_table :people
drop_table :aliases
drop_table :people_aliases
end
end

I pop open the console, create a person:

p = Person.new(:first_name => ‘Buster’, :last_name => ‘McThunderstick’)

=> #…
p.aliases
=> []
p.save
p.id
=> 1

Now, if I attempt any action that comes within spitting distance of p.aliases, everything blows up. This includes p.aliases, p.destroy, etc.

Here’s the error:
ActiveRecord::StatementInvalid: ActiveRecord::StatementInvalid

    from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb:266:in `table_structure'
    from ./script/../config/../config/../vendor/rails/activerecord/lib/../../activesupport/lib/active_support/core_ext/object/misc.rb:23:in `returning'

    from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb:265:in `table_structure'
    from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb:203:in `columns'

    from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb:165:in `finding_with_ambigious_select?'
    from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb:55:in `find'

    from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/associations/association_collection.rb:159:in `find_target'
    from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:129:in `load_target'

    from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb:122:in `method_missing'
    from ./script/../config/../config/../vendor/rails/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb:91:in `method_missing'

    from /opt/local/lib/ruby/1.8/irb.rb:298:in `output_value'
    from /opt/local/lib/ruby/1.8/irb.rb:151:in `eval_input'
    from /opt/local/lib/ruby/1.8/irb.rb:259:in `signal_status'
    from /opt/local/lib/ruby/1.8/irb.rb:147:in `eval_input'

    from /opt/local/lib/ruby/1.8/irb.rb:146:in `eval_input'
    from /opt/local/lib/ruby/1.8/irb.rb:70:in `start'
    from /opt/local/lib/ruby/1.8/irb.rb:69:in `start'
    from /opt/local/bin/irb:13>>

I do have a workaround in place. If I include the join_table option in my habtm calls, everything suddenly works.

But why do I have to add the join_table option? I’m following the principle of convention plus redundant configuration.

This problem exists on Windows XP and OS X with both GemRails and Edge. Is this a known issue?
And for that matter, what’s an ambigious_select?

Your join table needs to be called aliases_people.

-Jonathan.

Thank you, Jonathan.

Why is the order important?

Well, of course. Now that I realize order is important, Google throws the answer at me.

http://blog.daveastels.com/articles/2006/08/19/has_and_belongs_to_many

Alphabetic order. What a caveat to leave out of the documentation.

It’s in the documentation… the first paragraph in fact.

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#M000533

-Jonathan.

You guys are awesome. My feet are thoroughly covered in saliva at this point, so I’ll just sign off with a hearty “thank you.” :slight_smile: