0

I try to learn the has_and_belongs_to_many relationship between my 2 fresh new and simple models Product and Author, where a Product can have many authors and where author can have a lots of products.

I wrote this :

class Author < ActiveRecord::Base
  has_and_belongs_to_many :products
end

class Product < ActiveRecord::Base
  has_and_belongs_to_many :authors
end

In the partial form of view for the products, I have :

<p>Products</p>
<%= collection_select(:product, :author_ids, @authors, :id, :name, :prompt => " ",  :multiple => true) %>

but when I hit the update button, I get this strange message I can't resolve myself :

NoMethodError in ProductsController#update undefined method `reject' for "1":String

Rails.root: /home/stephane/www/HABTM Application Trace | Framework Trace | Full Trace app/controllers/products_controller.rb:63:in block in update' app/controllers/products_controller.rb:62:inupdate' Request

Parameters: {"utf8"=>"✓", "_method"=>"put", "authenticity_token"=>"2GlTssOFjTVZ9BikrIFgx22cdTOIJuAB70liYhhLf+4=", "product"=>{"title"=>"Le trésor des Templiers", "original_title"=>"", "number"=>"1", "added_by"=>"", "author_ids"=>"1"}, "commit"=>"Update Product", "id"=>"1"}

What's wrong ? Is there a problem with :product_ids... I saw on internet I had to pu a "s" but I'm not sure of what it represents....

How can I link the table authors_products to the key which is given back by the drop-down menu ? (here "author_ids"=>"1") Thx !

More info : May be solved with this info, but still no saving of the relationship :

collection_select("sales_agent", "customer_id", @customers, "id", "name")

Assuming you had a customer model with an ID attribute and a name attribute, this would produce exactly the above code. So looking at the values we pass into the collection_select call:

  • The first parameter is the model that contains one element from the collection (eg. sales_agent)
  • Next is the field name in the model that refers to the collection element it contains (eg. customer_id)
  • Next is the variable containing the collection of items that we want to list (eg. @customers)
  • Next is the value attribute of the option tag (eg. the customer id)
  • Next is the display attribute of the option tag (eg. the customer name)

So I now wrote

<p>Products</p>
<%= collection_select(:author, :author_id, @authors, :id, :name, :prompt => " ",  :multiple => true) %>

and it worked, but without saving the link, for the moment... (only the update of the normal fields are saved, not the relationship :-(

Stéphane V
  • 1,094
  • 2
  • 11
  • 25

1 Answers1

2

Do you have a separate model called author_products for the HABTM relationship?

You'll need to run another migration by doing something like rails g model author_product and the table should only contain two fields:

belongs_to :author
belongs_to :product

Make sure there is no primary key.

Something like:

  def self.up
    create_table(:author_products), :id => false do |t|
       t.references :author
       t.references :product
    end
  end
Dex
  • 12,527
  • 15
  • 69
  • 90
  • Yes, I did this migration and I have the table, with no :id. I only wrote t.integer in place of t.references. Is that a source of problem ? – Stéphane V Jun 23 '11 at 08:54
  • No it will be fine as long as the columns are named author_id and product_id. They must also be in alphabetical order I believe. So author must come before product. – Dex Jun 23 '11 at 22:33