Note that there are some explanatory texts on larger screens.

plurals
  1. POElegantly selecting attributes from has_many :through join models in Rails
    text
    copied!<p>I'm wondering what the easiest/most elegant way of selecting attributes from join models in has_many :through associations is.</p> <p>Lets say we have Items, Catalogs, and CatalogItems with the following Item class:</p> <pre><code>class Item &lt; ActiveRecord::Base has_many :catalog_items has_many :catalogs, :through =&gt; :catalog_items end </code></pre> <p>Additionally, lets say that CatalogueItems has a position attribute and that there is only one CatalogueItem between any catalog and any item. </p> <p>The most obvious but slightly frustrating way to retrieve the position attribute is:</p> <pre><code>@item = Item.find(4) @catalog = @item.catalogs.first @cat_item = @item.catalog_items.first(:conditions =&gt; {:catalog_id =&gt; @catalog.id}) position = @cat_item.position </code></pre> <p>This is annoying because it seems that we should be able to do @item.catalogs.first.position since we have completely specified which position we want: the one that corresponds to the first of @item's catalogs. </p> <p>The only way I've found to get this is:</p> <pre><code>class Item &lt; ActiveRecord::Base has_many :catalog_items has_many :catalogs, :through =&gt; :catalog_items, :select =&gt; "catalogue_items.position, catalogs.*" end </code></pre> <p>Now I can do Item.catalogs.first.position. However, this seems like a bit of a hack - I'm adding an extra attribute onto a Catalog instance. It also opens up the possibility of trying to use a view in two different situations where I populate @catalogs with a Catalog.find or with a @item.catalogs. In one case, the position will be there, and in the other, it won't. </p> <p>Does anyone have a good solution to this?</p> <p>Thanks.</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