Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to filter association_ids for an ActiveRecord model?
    text
    copied!<p>In a domain like this:</p> <pre><code> class User has_many :posts has_many :topics, :through =&gt; :posts end class Post belongs_to :user belongs_to :topic end class Topic has_many :posts end </code></pre> <p>I can read all the Topic ids through <code>user.topic_ids</code> but I can't see a way to apply filtering conditions to this method, since it returns an <code>Array</code> instead of a <code>ActiveRecord::Relation</code>. </p> <p>The problem is, given a User and an <em>existing</em> set of Topics, marking the ones for which there is a post by the user. I am currently doing something like this:</p> <pre><code> def mark_topics_with_post(user, topics) # only returns the ids of the topics for which this user has a post topic_ids = user.topic_ids topics.each {|t| t[:has_post]=topic_ids.include(t.id)} end </code></pre> <p>But this loads all the topic ids regardless of the input set. Ideally, I'd like to do something like</p> <pre><code> def mark_topics_with_post(user, topics) # only returns the topics where user has a post within the subset of interest topic_ids = user.topic_ids.where(:id=&gt;topics.map(&amp;:id)) topics.each {|t| t[:has_post]=topic_ids.include(t.id)} end </code></pre> <p>But the only thing I can do concretely is </p> <pre><code> def mark_topics_with_post(user, topics) # needlessly create Post objects only to unwrap them later topic_ids = user.posts.where(:topic_id=&gt;topics.map(&amp;:id)).select(:topic_id).map(&amp;:topic_id) topics.each {|t| t[:has_post]=topic_ids.include(t.id)} end </code></pre> <p>Is there a better way? Is it possible to have something like <code>select_values</code> on a association or scope? FWIW, I'm on rails 3.0.x, but I'd be curious about 3.1 too.</p> <p><strong>Why am I doing this?</strong></p> <p>Basically, I have a result page for a semi-complex search (which happens based on the Topic data only), and I want to mark the results (Topics) as stuff on which the user has interacted (wrote a Post). </p> <p>So yeah, there is another option which would be doing a join [Topic,Post] so that the results come out as marked or not from the search, but this would destroy my ability to cache the Topic query (the query, even without the join, is more expensive than fetching only the ids for the user)</p> <p>Notice the approaches outlined above <em>do work</em>, they just feel suboptimal.</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