Rails 4 个范围连接以查找 either/or 关系

Rails 4 scope joins to find either/or relationships

我有一个 rails 4.2.8 应用程序,它有很多关系。我的交互模型具有并属于许多基因(具体来说,一个交互可以有 2 个基因,而一个基因可以属于任意数量的交互),而基因模型又具有许多药物和疾病。

我正在尝试允许用户根据其中一个或另一个基因是否具有与其相关的药物和/或疾病来过滤交互。如果选择了药物或疾病 'filter',则下面的代码会按要求工作,因为会显示与至少一种基因的所有相互作用以及至少其中一种关联。

然而,当检查两个过滤器时,我只显示其中一个或两个基因至少与一种药物 至少一种疾病相关的相互作用。我还想展示一个基因具有 drug/s 但没有疾病而另一个基因具有 disease/s 但没有相关药物的相互作用。

型号

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?
    ...

我还没有找到任何明显解决这个问题的方法/问题,尽管这可能是我无法找到足够简洁的词来解决问题以有效搜索的结果。

提前致谢!

在Rails4中我可以提出两个方案:

1。身份证列表

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。联盟

Gem active_record_union gem 提供 SQL UNION 对 Rails.

的支持
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。通用建议:通过通用查询而不是域设计您的数据库。