Note that there are some explanatory texts on larger screens.

plurals
  1. POIn has_many :through, what is the correct way to create object inheritance
    text
    copied!<p>I've hit something that I don't understand how to model with Rails associations and neither STI nor polymorphism seem to address it.</p> <p>I want to be able to access attributes from a join table via the collection that's created by has_many :through. </p> <p>In the code below, this means that I want to be able to access the name and description of a committee position via the objects in the .members collection but as far as I can see I can't do that. I have to go through the original join table.</p> <p><strong>e.g. modelling a club and it's committee members</strong></p> <pre><code>class User &lt; ActiveRecord::Base attr_accessible :full_name, :email has_many: committee_positions has_many: committees, :through =&gt; committee_positions end class Committee &lt; ActiveRecord::Base attr_accessible :name has_many :committee_positions has_many :members, :through =&gt; :committee_positions end class CommitteePosition &lt; ActiveRecord::Base attr_accessible :user_id, :committee_id, :member_description, :role_title belongs_to :committee belongs_to :user end </code></pre> <p><em><strong>Assume that each committee position instance has a unique description</em></strong> i.e. the description is particular to both the member and the committee and so has to be stored on the join table and not with either the user or the club.</p> <p>e.g.</p> <pre><code>Committee member: Matt Wilkins Role: "Rowing club president" Description: "Beats the heart of the rowing club to his own particular drum" </code></pre> <p><strong>Is there a way to access the data in the join table via the committee.members collection?</strong></p> <p>While active record gives us this great alias for going directly to the members, there doesn't seem to be any way to access the data on the join table that created the collection:</p> <p>I cannot do the following:</p> <pre><code>rowing_committee.members.find_by_role_title('president').name </code></pre> <p>Each item in the .members collection is a user object and doesn't seem to have access to either the role or description that's stored in the CommitteePositions join table.</p> <p>The only way to do this would be:</p> <pre><code>rowing_committee.committee_positions.find_by_role_title('president').user.name </code></pre> <p>This is perfectly do-able but is clunky and unhelpful. I feel like the use-case is sufficiently generic that I may well be missing something. </p> <p><strong>What I would like to access via objects in the committee.members collection</strong></p> <pre><code>member - full_name - email - role_title (referenced from join table attributes) - member_description (referenced from join table attributes) </code></pre> <p>This is only a small thing but it feels ugly. Is there a clean way to instruct the "member" objects to inherit the information contained within the join table?</p> <h2>-------------- addendum</h2> <p>On working through this I realise that I can get half way to solving the problem by simply defining a new class for committee member and referencing that instead of user in the has_many :through relationship. It works a little bit better but is still pretty clunky</p> <pre><code>class Committee &lt; ActiveRecord::Base ... has_many :committee_positions has_many :members, :through =&gt; :committee_positions, :class_name =&gt; 'CommitteeMember' ... end class CommitteeMember &lt; User def description( committee ) self.committees.find_by_committee_id( committee.id ).description end def role( committee ) self.committees.find_by_committee_id( committee.id ).description end end </code></pre> <p>Now this is getting closer but it still feels clunky in that the code to use it would be:</p> <pre><code>committee = Committee.first president_description = committee.members.find_by_title('president').description( committee ) </code></pre> <p>Is there any way to initialize these objects with the committee they are referencing?</p>
 

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