优雅地从has_many中选择属性:通过Rails中的连接模型

我想知道在has_many中通过连接模型选择属性的最简单/最优雅的方法是:通过关联。

假设我们有Items,Catalogs和CatalogItems,它们包含以下Item类:

class Item  :catalog_items end 

另外,假设CatalogueItems有一个position属性,并且在任何目录和任何项目之间只有一个CatalogueItem。

检索position属性最明显但又有点令人沮丧的方法是:

 @item = Item.find(4) @catalog = @item.catalogs.first @cat_item = @item.catalog_items.first(:conditions => {:catalog_id => @catalog.id}) position = @cat_item.position 

这很烦人,因为我们应该能够做@ item.catalogs.first.position,因为我们已经完全指定了我们想要的位置:对应于@ item目录的第一个位置。

我发现得到这个的唯一方法是:

 class Item  :catalog_items, :select => "catalogue_items.position, catalogs.*" end 

现在我可以做Item.catalogs.first.position。 但是,这看起来有点像黑客 – 我在Catalog实例上添加了一个额外的属性。 它还开辟了在两种不同情况下尝试使用视图的可能性,其中我使用Catalog.find或@ item.catalogs填充@catalogs。 在一种情况下,位置将在那里,而在另一种情况下,它不会。

有人有一个很好的解决方案吗?

谢谢。

你可以这样做:

 # which is basically same as your "frustrating way" of doing it @item.catalog_items.find_by_catalogue_id(@item.catalogs.first.id).position 

或者您可以将其包装到Item模型的实例方法中:

 def position_in_first_catalogue self.catalog_items.find_by_catalogue_id(self.catalogs.first.id).position end 

然后像这样调用它:

 @item.position_in_first_catalogue 

只需添加答案,以便它可以帮助其他人

 CatalogItem.joins(:item, :catalog). where(items: { id: 4 }).pluck(:position).first 

如果您提供关联的另一端,您应该能够执行@ catalog.catalog_item.position。

 class Catalog < ActiveRecord::Base belongs_to :catalog_item end 

现在你可以做Catalog.first.catalog_item.position。

你为什么不这样做

 @item = Item.find(4) position = @item.catalog_items.first.position 

你为什么要浏览目录? 这对我来说没有任何意义,因为你正在寻找第一个目录!?