Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Your <code>has_one</code> condition will never work in Rails, as far as I know.</p> <p>You need one explicit <code>has_one</code> or <code>belongs_to</code> or has_many per "link", on both tables. So if you have two "links", you need two <code>has_one</code> and two <code>belongs_to</code>. That is how it works.</p> <p>Secondly, I think you should reconsider your models. The way you are doing it, one person can not be the president of a club and an employee, at the same time. Or be the president of two clubs. Even if you don't have these right now, they can come in the future - it is easier to stay flexible right now.</p> <p>A flexible way of doing this is using a <code>has_many :through</code> with an intermediate table that specifies the role. In other words:</p> <pre><code># The memberships table has a person_id, club_id and role_id, all integers class Membership &lt; ActiveRecord::Base belongs_to :club belongs_to :person validates_presence_of :role_id validates_numericality_of :role_id end class Club &lt; ActiveRecord::Base has_many :memberships, :dependent =&gt; :delete_all has_many :people, :through =&gt; :memberships end class Person &lt; ActiveRecord::Base has_many :memberships, :dependent =&gt; :delete_all has_many :clubs, :through =&gt; :memberships end </code></pre> <p>Now, assuming that role_id=0 means employee, role_id=1 means president, and role_id=2 means vice_president, you can use it like this:</p> <pre><code>tyler = Person.find(1) # person_id is 1 other = Person.find(2) # person_id is 2 c = Club.find(1) # club_id is 1 tyler.clubs # returns all the clubs this person is "member" of c.people # returns all the "members" of this club, no matter their role #make tyler the president of c tyler.memberships.create(:club_id =&gt; 1, :role_id =&gt; 1) #make other the vicepresident of c #but using c.memberships instead of other.memberships (works both ways) c.memberships.create(:person_id =&gt; 2, :role_id =&gt; 1) #find the (first) president of c c.memberships.find_by_role_id(1).person #find the (first) vicepresident of c c.memberships.find_by_role_id(2).person #find all the employees of c c.memberships.find_all_by_role_id(0).collect { |m| m.person } #find all the clubs of which tyler is president tyler.memberships.find_all_by_role_id(1).collect { |m| m.club } </code></pre> <p>Additional notes:</p> <ul> <li>You could complement this with a roles table and model. Roles would have just a a name, roles would <code>have_many</code> relationships and memberships would <code>belong_to</code> role. Or, you could define methods in memberships for getting the role name (if 0, it returns "employee", if 1, "president", etc</li> <li>You can add validations on memberhips so no more than 1 person can be made president of a given club, or the same employee on the same club twice. Later on, if you start getting "exceptional cases" in which a person needs to be in two places, you will just have to adapt your validations.</li> </ul>
 

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