我正在尝试构建一个复选框过滤器,它会进一步减少每个额外复选框的结果数量,其中每个复选框表示has_many中关联的关系。
我有一个包含以下型号的应用程序:
以下是关联:
class Hospital < ActiveRecord::Base
has_many :hospital_features
has_many :features, through: :hospital_features
end
class HospitalFeature < ActiveRecord::Base
belongs_to :hospital
belongs_to :feature
end
class Feature < ActiveRecord::Base
has_many :hospital_features
has_many :hospitals, through: :hospital_features
end
我有一个复选框表单,其中列出了所有可用功能。
<%= label_tag("helipad", "Helipad") %>
<%= check_box_tag("features[]", "helipad" %>
<%= label_tag("telesurgery", "Telesurgery") %>
<%= check_box_tag("features[]", "telesurgery" %>
<%= label_tag("emergency room", "Emergency Room") %>
<%= check_box_tag("features[]", "emergency room" %>
我试图像在购物网站上那样进行过滤,其中每个复选框都会过滤到仅具有所有已检查功能的医院。
我现在正在使用的查询:
hospitals = Hospital.joins(:features).where(features: {name: features} )
恰恰相反。每个检查的额外框都会增加结果数量,因为它会返回带有任何一个已检查功能的医院,而不是具有所有已检查功能的医院。
所以如果你检查&#34;直升机停机坪&#34;和&#34;远程手术&#34;,它应该只返回医院同时使用&#34;直升机停机坪&#34;和&#34;远程手术&#34;而不是任何医院都有&#34;直升机停机坪&#34;或者&#34;远程手术&#34;。
环顾四周,似乎无法找到明显的解决方案。我感谢任何帮助。提前谢谢。
答案 0 :(得分:1)
也许这不是最美丽的解决方案,但它对我有用。
Hospital.joins(:features).where(features: {name: features}).group('hospitals.id').having("count(*) >= ?", features.size)
答案 1 :(得分:1)
有一个解决方案。首先将医院连接到功能,然后进行过滤,其中'features.name in(?)'将features数组插入到查询中。
因此,对于该医院的每个功能,这将返回同一家医院。因此,如果该列表包含4个功能,并且医院全部为4个,那么该医院将被退回4次。同样,如果它只有4个特征中的3个,它将返回3次。
然后按医院ID分组,并添加“HAVING COUNT(*)”等于过滤后的功能数。
然后结果是:
hospitals = Hospital.joins(:features)
.where('features.name in (?)', searched_features)
.group("hospitals.id")
.having('COUNT(*) = ?', searched_features.length)
希望最终帮助别人。如果有人发现更优雅的方式,请告诉我。
答案 2 :(得分:0)
我认为有很多选择可以做到这一点 - 对我来说效果很好的是Sunspot Solr过滤方面。 Railscasts很好地解释了它:http://railscasts.com/episodes/278-search-with-sunspot。
答案 3 :(得分:0)
使用我的Where Exists gem:
result = Hospital.all
features.each do |feature|
result = scope.where_exists(:features, name: feature)
end