Элегантный выбор атрибутов из has_many: через модели соединения в Rails - PullRequest
5 голосов
/ 09 января 2009

Мне интересно, каков самый простой / самый элегантный способ выбора атрибутов из моделей соединения в has_many: через ассоциации.

Допустим, у нас есть элементы, каталоги и элементы каталога со следующим классом элементов:

class Item < ActiveRecord::Base
      has_many :catalog_items
      has_many :catalogs, :through => :catalog_items
end    

Кроме того, допустим, что CatalogueItems имеет атрибут позиции и что между любым каталогом и любым элементом существует только один CatalogueItem.

Наиболее очевидный, но слегка разочаровывающий способ получения атрибута позиции:

@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 < ActiveRecord::Base
      has_many :catalog_items
      has_many :catalogs, :through => :catalog_items, :select => "catalogue_items.position, catalogs.*"
end

Теперь я могу сделать Item.catalogs.first.position. Тем не менее, это похоже на хак - я добавляю дополнительный атрибут в экземпляр каталога. Это также открывает возможность попытки использовать представление в двух разных ситуациях, когда я заполняю @catalogs с помощью Catalog.find или с помощью @ item.catalogs. В одном случае позиция будет там, а в другом - нет.

У кого-нибудь есть хорошее решение для этого?

Спасибо.

Ответы [ 4 ]

0 голосов
/ 03 апреля 2018

Просто добавив ответ, чтобы он мог помочь другим

CatalogItem.joins(:item, :catalog).
  where(items: { id: 4 }).pluck(:position).first
0 голосов
/ 09 января 2009

Вы должны быть в состоянии сделать @ catalog.catalog_item.position, если предоставите другой конец ассоциации.

class Catalog < ActiveRecord::Base
  belongs_to :catalog_item
end

Теперь вы можете сделать Catalog.first.catalog_item.position.

0 голосов
/ 10 января 2009

Почему бы тебе не просто

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

почему вы ходите по каталогам? Это не имеет никакого смысла для меня, так как вы ищете первый ЛЮБОЙ каталог!?

0 голосов
/ 09 января 2009

Вы можете сделать что-то вроде этого:

# 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
...