user896715
user896715

Reputation: 109

Rails basic association

I'm trying to do a basic model association in rails. Basically I have a List table which stores item_id and user_id.

One user can create multiple "list-items."

Is this the correct way to do it?

Thanks.

class Item < ActiveRecord::Base
  has_many :users, :through => :lists
end

class User < ActiveRecord::Base
  has_many :items, :through => :lists
end


class List < ActiveRecord::Base
  belongs_to :user
  belongs_to :item
end

Upvotes: 0

Views: 134

Answers (2)

pduey
pduey

Reputation: 3786

If the "list" entity truly is a pure association/join, that is, it has no inherent attributes of its own, then you can simplify a bit and use has_and_belongs_to_many. Then you don't need a "List" class.

class Item < ActiveRecord::Base
  has_and_belongs_to_many :users
end

class User < ActiveRecord::Base
  has_and_belongs_to_many :items
end

Rails will look for the references in a "items_users" table, so in your migration, you need to create it a la:

create_table :items_users, :id => false do |t|
  t.references :users, :items
end

Many people will tell you to always use has_many :through, but others (like me) will disagree - use the right tool for job.

Upvotes: 0

mliebelt
mliebelt

Reputation: 15525

Depending on what you want to reach, your solution is the right one (or not). I see the following cases:

  1. You want to create an n:m association between items and users. So each item could be referenced by many users, and each user references many items. If this is the right context, then your solution is the right one. See the Rails Guides: Associations for more information on that.
  2. An alternative for that situation could be to use the has_and_belongs_to_many Association. The situation is the same, but it does not make sense to talk about lists, there will be no model object for it.
  3. If each users may have many lists, and each list may have many items, your solution would be wrong. This would be no n:m association with list as the join table in between, but two 1:n relations.

The code for the third example would look like that:

class User < ActiveRecord::Base
  has_many :items, :through => :lists
  has_many :lists  
end

class List < ActiveRecord::Base
  has_many :items
  belongs_to :user
end

class Item < ActiveRecord::Base
  belongs_to :list
end

In the first solution, you should add the relations for users to lists and items to list:

class Item < ActiveRecord::Base
  has_many :lists
  has_many :users, :through => :lists
end

class User < ActiveRecord::Base
  has_many :lists
  has_many :items, :through => :lists
end

Upvotes: 1

Related Questions