2012-03-30 83 views
4

样的红宝石小白活动记录查询的问题:Rails的许多一对多存在查询

Magazine 
    has_many :subscriptions 

User 
    has_many :subscriptions 

Subscription 
    belongs_to :user 
    belongs_to :magazine 

在控制器,我想如果CURRENT_USER订阅a_magazine高效地问。我认为它应该像下面这样...

Subscription.where("user_id = ? and magazine_id = ?", current_user.id, a_magazine.id).count > 0 

a)看起来正确吗? b)是否有更有效的方法(假设FK上的索引)c)风格上,是否有更为接受或简洁的方法?

在此先感谢...

+0

B)假设指数这个查询应该是真正有效的(也可能是最有效的) – 2012-03-31 00:17:55

+0

喜@ Aldo'xoen'Giambelluca其实在我的'has_many through'关联中,我有类似的情况,现在我正在使用<%if product.wishlist.where(:customer_id => current_customer.id).any? %>当渲染产品#索引视图,以知道哪些列出的产品在记录的“客户”愿望清单中并突出显示它们。但我担心的是绩效;当产品清单很大时,这是一个好方法吗?或者还有另一个更有效的查询来不影响性能? – 2016-11-21 23:05:12

回答

3

执行此操作的更简洁的方法涉及使用散列方法声明查询,它读取更多eas随手并留下机会较少失误:

Subscription.where(:user_id => current_user.id, :magazine_id => a_magazine.id).any? 

您还可以添加:through关系基于用户或相应的杂志进行检查。

class User < ActiveRecord::Base 
    has_many :subscriptions 
    has_many :magazines, :through => :subscriptions 
end 

这使得测试比赛真的很容易:在FKS

user = User.find(1) 
user.magazines.where(:magazine_id => magazine_id).any? 
+0

我想要一个逗号分隔哈希,还是一​​个连词“和”?尽管如此,我想无论如何,我应该利用这个过程,并使用其他的表述。 – danh 2012-03-30 19:43:03

+0

你好!我有这样的情况,我现在正在使用这个'<%​​if product.wishlist.where(:customer_id => current_customer.id).any? %>'当呈现'产品#索引'视图时知道哪些列出的产品在记录的'客户'愿望清单中并突出显示它们。但我担心的是绩效;当产品清单是*大*是一个好方法去?或者还有另一种更有效的**查询**以不影响性能? – 2016-11-21 23:06:01

+0

这是一个经典的N + 1查询情况。您可能想要做的是使用某种查询预先加载愿望清单中与'products'列表重叠的所有'product_id'值。返回ID的模型级别的方法是放置这个的好地方。 – tadman 2016-11-21 23:31:01

2

您应该将您的关联更改为has_many :through关系。通过这种方式,您可以通过两种模型获得参考模型。

class Magazine < ActiveRecord::Base 
    has_many :users, :through => :subscriptions 
end 

class User < ActiveRecord::Base 
    has_many :magazines, :through => :subscriptions 
end 

class Subscription < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :magazine 
end 

现在,您可以检查哪些Subscriptions一个User拥有这样的...

User.find(current_user.id).subscriptions # => Returns a list of Magazine id's 

你可以检查一个UserMagazine通过Subscription是这样的...

User.find(current_user.id).subscriptions.find_by_magazine_id(1).any? 
+1

最后一行不是用户,而是订阅。应该是'@ subscription'而不是'@ user'。你也可以使用'find_by_magazine_id(1)'或'where(:magazine_id => 1)'这很难搞砸。 – tadman 2012-03-30 19:06:34

+0

我不是故意要包含一个实例变量,谢谢你的注意。也感谢您指出额外的方法! +1 – 2012-03-30 19:11:27