【问题标题】:Arel Relation Reference to has_many relationship对 has_many 关系的 Arel 关系参考
【发布时间】:2013-11-10 22:30:41
【问题描述】:

我有一个基本的 has_many 关系,建模如下:

class Term < ActiveRecord::Base
    has_many :acroynms
end

class Acronym < ActiveRecord::Base
    belongs_to :term    
end

我想写一个 arel 关系,它将根据术语的名称或首字母缩略词的名称提取术语。我的关系不正确,但我想做一些看起来像这样的事情:

terms = Term.arel_table
relation = terms[name].matches("%#{params['a']}%")
relation = relation.or(terms[:acronyms.name].matches("%#{params['a']}%"))
@results = Term.where(relation)

我想将其保留在关系中,因为我将许多其他组合条件组合到该关系中(为简洁起见,我在此省略)。

我使用的是关系,而不是仅在最后一行将所有内容组合在一起,需要组合的项目直到运行时才会知道,具体取决于用户输入。我的想法是使用这个模型,我将能够设置我的关系,无论它可能多么复杂,然后只需一行来设置@results,而不管用户输入如何。

有没有办法把这一切写成关系?否则,我想我需要求助于使用 arel 的联接,但仅在用户输入需要它的情况下才加入,对吗?

【问题讨论】:

    标签: ruby-on-rails ruby activerecord arel


    【解决方案1】:

    我不完全确定如何使用 arel 来执行此操作,但如果您想根据参数(或其他输入)链接 where 子句并在构建完成后执行:

    query = User.scoped
    
    query = query.where("name like ?", "%#{params[:name]}%") if params[:name].present?
    query = query.where("email like ?", "%#{params[:email]}%") if params[:email].present?
    
    @users = query.all
    

    再说一次,我知道这不是你想要的,但可能是一个可能的替代方案。

    注意:如果您在控制台中运行它,这将不会达到您的预期,因为 REPL 的 print 步骤将执行每个步骤,使其在 Rails 中看起来像多个查询应用程序它实际上只会执行一个。

    【讨论】:

    • 感谢您的选择。我选择 arel 的主要原因之一是因为我的参数之一是一个数组,它应该被视为 OR 条件。使用 arel,我可以遍历参数数组并链接 OR 语句。在您的范式中,是否有一种方法可以做到这一点?我是 activerecord 和 arel 的新手,所以如果这是我在文档中遗漏的基本查询,我深表歉意。
    • 因此,鉴于上面的链接,您将根据您的数组构建 arel where 子句,然后您可以将其插入 where,然后执行。
    • 这绝对有助于清理我的代码的可读性。我仍然认为我有我最初的问题,我会编辑问题以更好地反映这一点,因为我认为我没有说清楚。基本上,我想搜索名称类似于参数的术语或具有名称类似于参数的同义词的术语。
    【解决方案2】:

    为了解决使用 OR 运算符的问题,我使用 3 个查询解决了这个问题,这是次优的,但可以使用。

    我的第一个查询查找名称类似于搜索参数的首字母缩略词。

    acronymQuery = query.includes(:acronyms).where('acronyms.name like ?', wildcard_search).select("terms.id")
    

    第二个查找名称类似于搜索参数的术语。

    termQuery = query.where('terms.name like ?', wildcard_search).select("terms.id")
    

    然后我结合每个查询的唯一 ID,我的第三个查询搜索这些 ID。

    acronymQueryResults = acronymQuery.all.map {|row| row.id}
    termQueryResults = termQuery.all.map {|row| row.id}
    ids = (acronymQueryResults + termQueryResults).uniq
    query = Term.where('id' => ids)
    

    【讨论】:

      猜你喜欢
      • 2021-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-13
      • 1970-01-01
      相关资源
      最近更新 更多