habtm confusion

Frew Schmidt schrieb:

Hello friends!

I am trying to make a database that will have a group of people set to
committees, and a person can be in multiple committees, and a committee
obviously has multiple people. The people are senators at my
university. These are my current models:

senator.rb:
--
class Senator < ActiveRecord::Base
  validates_presence_of :first_name, :last_name, :floor
  has_and_belongs_to_many :committees#, :dependent => :nullify
  #has_many :chairs, :class_name => "Committee"#, :dependent => :nullify
end
--

The last has_many is commented out so that I can at least get this
working, and then I'll add that in later. Also note that the :dependent
has been commented out. Is this deprecated or no longer supported?
What's the deal?

committee.rb
--
class Committee < ActiveRecord::Base
  validates_presence_of :name
  has_and_belongs_to_many :senators #, :dependent => :nullify
  #has_one :head, :class_name => "Senator" #, :dependent => :nullify
end
--

Same as before on the comments.

Also, for my view I am trying the following:
--
<p><label for="senator_committee">Committee</label><br/>
<%= select(:senator, :committees,
           Committee.find(:all).map {|c| [c.name, c.id]},
{:include_blank => true}, {:multiple => true}) %>
</p>
--

On the view I get the following error:

ActiveRecord::StatementInvalid

and the trace:

/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/sqlite_adapter.rb:360:in
`table_structure'
/usr/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/core_ext/object/misc.rb:23:in
`returning'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/sqlite_adapter.rb:359:in
`table_structure'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/sqlite_adapter.rb:210:in
`columns'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/associations/has_and_belongs_to_many_association.rb:165:in
`finding_with_ambigious_select?'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/associations/has_and_belongs_to_many_association.rb:55:in
`find'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/associations/association_collection.rb:159:in
`find_target'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/associations/association_proxy.rb:131:in
`load_target'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/associations/association_proxy.rb:29:in
`respond_to?'
/usr/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_view/helpers/form_options_helper.rb:116:in
`options_for_select'
/usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1358:in
`inject'
/usr/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_view/helpers/form_options_helper.rb:114:in
`each'
/usr/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_view/helpers/form_options_helper.rb:114:in
`inject'
/usr/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_view/helpers/form_options_helper.rb:114:in
`options_for_select'
/usr/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_view/helpers/form_options_helper.rb:302:in
`to_select_tag'
/usr/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_view/helpers/form_options_helper.rb:66:in
`select'
#{RAILS_ROOT}/app/views/admin/_form.rhtml:26:in
`_run_rhtml_47app47views47admin47_form46rhtml'
#{RAILS_ROOT}/app/views/admin/edit.rhtml:4:in
`_run_rhtml_47app47views47admin47edit46rhtml'
#{RAILS_ROOT}/app/views/admin/edit.rhtml:3:in
`_run_rhtml_47app47views47admin47edit46rhtml'

Any help at all would be much appreciated.

first, you have a "committees_senators" table to manage your many-many join

second, your rhtml looks odd to me, I haven't used that in a while but I think the bit...

:senator, :committees,

... looks wrong

I'm guessing you want a list of committees. You should have something more like...

<p><label for="senator_committee">Committee</label><br/>
> <%= select('committee', 'committee_id',
> Committee.find(:all).map {|c| [c.name, c.id]},
> {:include_blank => true}, {:multiple => true}) %>
> </p>

... if you want the committees a senator is associated with you'll need to add some extra code, something like ":selected => [Arr of Committee Id's]" should work

finally, I think :dependent is for has_many, not habtm. You should check the documentation to be certain. http://api.rubyonrails.org

good luck,

andy koch

Frew Schmidt schrieb:

Thanks for the reply Andy!

first, you have a "committees_senators" table to manage your many-many join

I know that, but that's abstracted away right? I don't need to deal with it, do I?

-fREW

correct, but you must first create the table in your DB with appropriate structure

/ak

Frew Schmidt schrieb:

Andy Koch wrote:

Frew Schmidt schrieb:

Thanks for the reply Andy!

first, you have a "committees_senators" table to manage your many-many join

I know that, but that's abstracted away right? I don't need to deal with it, do I?

-fREW

correct, but you must first create the table in your DB with appropriate
structure

Oooh!

I never made that connection. Here is the migration that I have made to define the table. Tell me if anything looks totally wrong with it:

005_create_committees_senators.rb
--
class CreateCommitteesSenators < ActiveRecord::Migration
  def self.up
    create_table :committees_senators do |t|
      t.column :committee_id, :integer
      t.column :senator_id, :integer
    end
  end

  def self.down
    drop_table :committees
  end
end
--

(It seems to have worked so far.)

close, but you're missing a few bits. See this rewrite...

def self.up
create_table :committees_senators, :id => false do |t|
       t.column :committee_id, :integer, :null => false
       t.column :senator_id, :integer, :null => false
end

say "Add unique index on 'committees_senators'", true
add_index(:committees_senators, [:committee_id, :senator_id], :unique => true)
end

...
The difference is:
1. this removes the 'id' column from your join table with the ":id => false", it is not needed since the joined pairs are the key
2. enforces in DB that neither ID in a pair may ever be null (:null => false)
3. creates a unique index on the table, while this isn't a true primary key index it does ensure you won't have any duplicity in the table.

And that should do it.

andy