Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Say you have two models: <code>User</code> and <code>Group</code>.</p> <p>If you wanted to have users belong to groups, then you could do something like this:</p> <pre><code>class Group &lt; ActiveRecord::Base has_many :users end class User &lt; ActiveRecord::Base belongs_to :group end </code></pre> <p>What if you wanted to track additional metadata around the association? For example, when the user joined the group, or perhaps what the user's role is in the group?</p> <p>This is where you make the association a first class object:</p> <pre><code>class GroupMembership &lt; ActiveRecord::Base belongs_to :user belongs_to :group # has attributes for date_joined and role end </code></pre> <p>This introduces a new table, and eliminates the <code>group_id</code> column from the user's table.</p> <p>The problem with this code is that you'd have to update every where else you use the user class and change it:</p> <pre><code>user.groups.first.name # becomes user.group_memberships.first.group.name </code></pre> <p>This type of code sucks, and it makes introducing changes like this painful.</p> <p><strong><code>has_many :through</code></strong> gives you the best of both worlds:</p> <pre><code>class User &lt; ActiveRecord::Base has_many :groups, :through =&gt; :group_memberships # Edit :needs to be plural same as the has_many relationship has_many :group_memberships end </code></pre> <p>Now you can treat it like a normal <code>has_many</code>, but get the benefit of the association model when you need it.</p> <p>Note that you can also do this with <code>has_one</code>.</p> <p><strong>Edit: Making it easy to add a user to a group</strong></p> <pre><code>def add_group(group, role = "member") self.group_associations.build(:group =&gt; group, :role =&gt; role) end </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload