There are basically two ways: has_and_belongs_to_many
( habtm
) and has_many
with the: through option, which points to another connection. Both require joining tables; the latter is what we call the join model, because you usually add additional information to the connection.
For example, consider an application with a user model that has bookmarking sites. One way would be to implement it as a habtm
relationship
class User < ActiveRecord::Base has_and_belongs_to_many :sites end class Site < ActiveRecord::Base has_and_belongs_to_many :users end user.sites << Site.find(...)
This simulation will also require the creation of a sites_users
table, in which there will be no primary key.
The problem with this is that you most likely want to keep additional information about it, so that you can go with the connection model, in this case Bookmark:
class User < ActiveRecord::Base has_many :bookmarks has_many :sites, :through => :bookmarks end class Site < ActiveRecord::Base has_many :bookmarks has_many :users, :through => :bookmarks #edit: adding validation for requiring at least one bookmark validate_before_create :at_least_one_bookmark private def at_least_one_bookmark errors.add_to_base("requires at least one bookmark") unless bookmarks.count > 0 end end class Bookmark < ActiveRecord::Base belongs_to :user belongs_to :site end user.bookmarks.create(:site => Site.find(...) )
A more common pattern is the union model approach for its versatility and better modeling, although habtm
is still used somewhat. They are just so two-dimensional that you really need to study what you are doing and make sure that there is no richer behavior that also needs to be modeled.
source share