Forum: Ruby on Rails habtm confusion

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Frew S. (Guest)
on 2007-07-17 06:56
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.
Andy K. (Guest)
on 2007-07-17 20:11
(Received via mailing list)
Frew S. schrieb:
>   validates_presence_of :first_name, :last_name, :floor
> committee.rb
> Also, for my view I am trying the following:
> ActiveRecord::StatementInvalid
> `columns'
> 
/usr/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_view/helpers/form_options_helper.rb:116:in
> `to_select_tag'
>
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 S. (Guest)
on 2007-07-17 20:39
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?

> <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>

as for the rhtml, the docs said the following:

  select(object, method, choices, options = {}, html_options = {})

so I presumed that I wanted :senator, :committees, but now that I think
about that, that really doesn't make a whole lot of sense.

>
> ... 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

Nah, I'll do that later, once I have the basics figured out.

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

Yeah, I realized last night that :dependent really doesn't make any
sense at all for habtm, because there is the intermediary table.  I'm
sure I don't need to explain it to you guys.

Thanks a bunch for the tips.  When I get time I will make modifications
based on this and see how things go.

-fREW
Andy K. (Guest)
on 2007-07-17 20:55
(Received via mailing list)
Frew S. 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 S. (Guest)
on 2007-07-17 21:05
Andy K. wrote:
> Frew S. 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.)
Andy K. (Guest)
on 2007-07-19 03:24
(Received via mailing list)
Frew S. schrieb:
>>>
> --
>   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
This topic is locked and can not be replied to.