Ruby on rails 在轨道上有很多

Ruby on rails 在轨道上有很多,ruby-on-rails,reverse,has-many,Ruby On Rails,Reverse,Has Many,假设我有模型:用户和项目以及它们之间的多对多关系。如何获取具有定义属性的项目的用户,即具有颜色为['red','black']的项目的用户 当然,我可以这样做: User.all :joins => [:items, :items], :conditions => {:"items.color" => "red", :"items_users.color" => 'black'} 但是对于更多的属性,它将是相当麻烦的。 我也可以做到: User.all(:conditi

假设我有模型:用户和项目以及它们之间的多对多关系。如何获取具有定义属性的项目的用户,即具有颜色为['red','black']的项目的用户

当然,我可以这样做:

User.all :joins => [:items, :items], :conditions => {:"items.color" => "red", :"items_users.color" => 'black'}
但是对于更多的属性,它将是相当麻烦的。 我也可以做到:

User.all(:conditions => ["items.color in (?), ['red', 'black']], :include => :items)
但这一个也会返回具有颜色=['red'、'black'、'blue'、'etc']的项目的用户


所以,唯一的解决方案是获取全部并使用ruby语法进行排序?如何在一个SQL查询或Rails AR语法中实现这一点?

在我看来,这是一种优化程序员时间和可读性的方式:

#get all users who have items which are both red and black but no other colors
candidate_users = User.all(:include => :items)
candidate_users.reject! do |candidate| 
  candidate.items.map {|item| item.color}.sort != ['black', 'red']
end
如果您希望在那里循环访问大量用户,那么您需要使用SQL进行查询。警告:SQL不是我的包,宝贝:使用前测试

select users.*, items.* FROM users 
  INNER JOIN items_users ON (items_users.user_id = users.id) 
  INNER JOIN items ON (items_users.item_id = items.id) 
    GROUP BY users.id HAVING COUNT(DISTINCT items.color) = 2 
我认为那邪恶的混乱会带来什么:

1) 抓住每个用户/项目组合 2) 筛选出正好有两种不同颜色的项目的用户

这意味着您需要:

candidate_users.reject! do |candidate| 
  candidate.items.map {|item| item.color}.sort != ['black', 'red']
end

在这里,您可能完全不需要ruby,但是SQL将获得七种难看的风格。(交叉连接,哦,我的…)

虽然很简单,但这打破了rails的惯例,并防止了链中的延迟加载(假定这将进入
lambda