Rails:多对一(0-n),查找记录

时间:2013-02-18 17:11:03

标签: ruby-on-rails-3

我有表格itemscards,其中一张卡属于user,而item可能有也可能没有给定用户的任何卡片。< / p>

基本关联设置如下:

Class User
   has_many :cards

Class Item
   has_many :cards

Class Card
   belongs_to :user
   has_and_belongs_to_many :items

我还创建了一个包含items_cardsitem_id列的联接表card_id。我想做一个查询,告诉我是否有给定用户/项目的卡片。在纯SQL中,我可以很容易地完成这个任务:

SELECT   count(id) 
FROM     cards 
JOIN     items_cards
ON       items_cards.card_id = cards.id
WHERE    cards.user_id = ?
AND      items_cards.item_id = ?

我正在寻找一些关于如何通过ActiveRecord进行此操作的指导。谢谢!

1 个答案:

答案 0 :(得分:1)

假设您在@item中有一个项目,在@user中有一个用户,如果该用户和该项目的卡片存在,则会返回'true':

Card.joins(:items).where('cards.user_id = :user_id and items.id = :item_id', :user_id => @user, :item_id => @item).exists?

这是发生了什么:

Card. - 您正在查询卡片型号。

joins(:items) - Rails知道如何为它支持的关联类型(通常 - 至少)组合联接。您告诉它要做任何必要的连接,以便您也可以查询关联的items。在这种情况下,这将导致JOIN items_cards ON items_cards.card_id = cards.id JOIN items ON items_cards.item_id = items.id

where('cards.user_id = :user_id and items.id = :item_id', :user_id => @user, :item_id => @item) - 您的条件,与纯SQL几乎相同。 Rails将使用散列(:user_id)中的值插入您使用冒号(:user_id => @user)指定的值。如果您将ActiveRecord对象作为值,则Rails将自动使用该对象的id。在这里,您说您只想要卡片属于您指定的用户的结果,并且您想要的项目有一行。

.exists? - 加载ActiveRecord对象效率低下,因此如果您只想知道是否存在某些内容,Rails可以节省一些时间并使用基于count的查询(非常类似于您的SQL版本)。还有.count,如果您希望查询返回结果数,而不是truefalse,则可以使用{{1}}。