views:

655

answers:

2

Hi..Im trying to figure out this HABTM relationship issue to store in the interests of users within my database. The interests table has a list of different interests with id and name (i.e: id=1 , name = 'Music')

I have a users model => user.rb

has_and_belongs_to_many :interests

and an interests model => interest.rb

has_and_belongs_to_many :users

Now I'm trying to edit or update the users choice of interests from a list of checkboxes. The controller looks like so =>

def edit
#@interests = Interest.find(:all)

  @title = "Edit Interest"
  @user = User.find(session[:user_id])
  @user.interest ||= Interest.new
  interest = @user.interest
  if param_posted?(:interest)
      if @user.interest.update_attributes(params[:interest])
          flash[:notice] = "Changes saved."
          redirect_to :controller => "users", :action => "index"
      end
  end
end

and the param_posted function looks like this

  def param_posted?(sym)
  request.post? and params[sym]
  end

The view logic looks like this:

<% for interest in @interest %>
<div>
<%= check_box_tag "user[interest_id][]", interest.id, @user.interests.include (interest) %>
<%= interest.name %>
</div>
<% end %>

I thought everything looked kosher but when I run the view I get the error :

NoMethodError in InterestController#edit - undefined method `interest' for # User:0x4797ddc

Do i need to create a separate model/table that connects the interest of users to events? like InterestsofUsers ( id, user_id, interest_id)? I thought the HABTM relationship would eliminate the need for that...

Confused

+2  A: 

There are a couple issues. First, you do need to create a join table for interests and users. Its name is combination of the two tables, in alphabetical order. It must not have a primary key. Here's an example:

class CreateInterestsUsersJoinTable < ActiveRecord::Migration
  self.up
    create_table :interests_users, :id => false do |t|
      t.integer :interest_id
      t.integer :user_id
    end
  end

  self.down
    drop_table :interests_users
  end
end

Naming the join table this specific way is how Rails knows how to find it automatically.

Also, remember that a user doesn't have one interest, a user has many. That's why there's no @user.interest method. There is a @user.interests method, which returns an array of all the interests of that user, which you can cycle through as needed.

Aside from that, I'd really make your controller more RESTful. That edit action is trying to handle at least 2 different kinds of requests, edit AND update, when they should be separate.

After you get this part fixed, post another question about how to make your controller more restful, and I or someone else can help you there. It's better to keep the two issues in separate questions for those who search the stackoverflow database in the future.

UPDATE: questions about many-to-many relationships in Rails have come up often enough that I wrote an article called basic many-to-many associations to explain how to use habtm vs has_many :through, and the differences between them.

Jaime Bellmyer
A: 

Hey,

  1. join table - interests_users
  2. user has....to_many, so it's plural, you'll need to make there a list of checkboxes
  3. try to stick to RESTful conventions :) post should go to update method
Devenv
I think this really just summarized point-for-point the answer I gave an hour earlier.
Jaime Bellmyer
Yes, in much less words... Didn't mean in any way to step on your points, just to summarize...
Devenv