Rails 4范围连接以查找或/或关系

时间:2018-05-10 11:01:36

标签: ruby-on-rails named-scope

我有一个有许多关系的rails 4.2.8应用程序。我的相互作用模型具有并且属于许多基因(特别是相互作用可以有2个基因,而基因可以属于任意数量的相互作用),基因模型又有许多药物和疾病。

我试图让用户根据其基因中的一个或另一个是否有与之相关的药物和/或疾病来过滤交互。如果选择了药物或疾病“过滤器”,则下面的代码可以根据需要起作用,因为所有与至少一个具有至少一个这种关联的基因的所有相互作用都会被显示。

然而,当检查两个过滤器时,我仅显示其中一个或两个基因具有至少一种至少一种疾病相关的药物的相互作用。我想要的是也显示相互作用,其中一个基因有药物但没有疾病,另一个基因有疾病,但没有药物相关。

模型

class Interaction < ActiveRecord::Base
    has_and_belongs_to_many :genes
    ...

    scope :disease_associated, -> { joins(genes: :diseases) }
    scope :drug_target, -> { joins(genes: :drugs) }
    ...
end

class Gene < ActiveRecord::Base
    has_and_belongs_to_many :interactions
    has_and_belongs_to_many :drugs
    ...
end

class Drug < ActiveRecord::Base
    has_and_belongs_to_many :genes
end

class Disease < ActiveRecord::Base
    has_and_belongs_to_many :genes
end

互动控制器

class InteractionsController < ApplicationController
    ...
    @interactions = @interactions.disease_associated() if params[:filter_disease].present?
    @interactions = @interactions.drug_target() if params[:filter_druggable].present?
    ...

我没有找到任何明显解决这个问题的方法/问题,尽管这可能是因为我无法找到足够简单地解决问题的词语来有效搜索。

提前致谢!

1 个答案:

答案 0 :(得分:1)

在Rails 4中,我可以提出两个选择:

1。 ID列表

ids = []
ids |= Interaction.disease_associated.pluck(:id) if params[:filter_disease].present?
ids |= Interaction.drug_target.pluck(:id) if params[:filter_druggable].present?

interactions = Interaction.where(id: ids)

如果数据库中存在许多交互,则清除但不好。

2。 UNION

Gem active_record_union gem为Rails提供SQL UNION支持。

interactions = Interaction.none
interactions = interactions.union(Interaction.disease_associated) if params[:filter_disease].present?
interactions = interactions.union(Interaction.drug_target) if params[:filter_druggable].present?

P.S。常见建议:通过常见查询而不是域来设计数据库。