首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >元程序在keypaths上进行搜索

元程序在keypaths上进行搜索
EN

Stack Overflow用户
提问于 2012-11-27 15:51:51
回答 2查看 390关注 0票数 2

问题是

我试图把我的头脑围绕着arel和squeel,但我觉得我缺乏词汇来询问谷歌我在寻找什么。

有人知道如何在组合的Squeel::Node对象中模仿Squeel的Model.where{related.objects.field.matches string}语法吗?

问题所在

This question演示了如何从字符串构建Squeel,如下所示:

代码语言:javascript
复制
search_relation = 'person.pets'
User.joins{Squeel::Nodes::KeyPath.new(search_relation.split('.'))}
# Mimics User.joins{person.pets}

this post中,情况变得更加复杂,我在那里学习了如何对跨多列的搜索进行元编程。使用documented Squeel trick (页面上的最后一行)清理后,它看起来如下所示:

代码语言:javascript
复制
search_columns = %w[first_name last_name]
search_term = 'chris'
User.where{
  search_columns.map do |column|
    column_stub = Squeel::Nodes::Stub.new(column)
    Squeel::Nodes::Predicate.new(column_stub, :matches, "%#{search_term}%")
  end.compact.inject(&:|)
}
# Mimics User.where{(last_name.matches '%chris%') | (first_name.matches '%chris%')} 

我想要的是能够将两者结合起来,模仿

代码语言:javascript
复制
User.joins{person.pets}.where{person.pets.name.matches '%polly%'}

通过我自己构建的squeel对象。

第一部分很简单,如第一个示例所示。第二部分,我可以直接对被查询的表上的列执行操作,如第二个示例所示。

但是,我不知道如何处理连接在表中的列的第二部分。我认为我需要使用第一个示例中的KeyPath对象来确定第二个示例中的Predicate对象的范围。Predicate对象似乎只适用于表示单个表上的单个列的Stub对象,而不是KeyPath

以前的尝试

求和

代码语言:javascript
复制
search_relation = 'key.path'
search_column = 'field'
search_term = '%search%'
keypath = Squeel::Nodes::KeyPath.new(search_relation.split('.') << search_column)

我尝试在KeyPath上调用matches方法:

代码语言:javascript
复制
Model.where{keypath.matches search_term}
#=> NoMethodError: undefined method `matches' for Squeel::Nodes::KeyPath

我尝试过使用matches操作符=~

代码语言:javascript
复制
Model.where{keypath =~ search_term}
#=> TypeError: type mismatch: String given

我也尝试过通过传入:matches参数来手动构建Predicate

代码语言:javascript
复制
Model.where{Squeel::Nodes::Predicate.new(keypath, :matches, search_term)}
#=> ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column
#=>   'model.key.path.field' in 'where clause':
#=>   SELECT `model`.* FROM `model`
#=>     INNER JOIN `key` ON `key`.`id` = `model`.`key_id`
#=>     INNER JOIN `path` ON `path`.`id` = `key`.`path_id`
#=>     WHERE `model`.`key.path.field` LIKE '%search%'

在这里,它成功地生成了SQL (像上面一样使用Model.joins{search_relation}正确连接,为了可读性而省略了),然后假定KeyPath是一个字段,而不是遍历它。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-11-28 02:06:29

虽然第一个示例中的KeyPath足以连接表,但是需要更仔细地构造要在WHERE子句中使用的KeyPath,以确保最后一个值确实是Stub

代码语言:javascript
复制
search_relation = 'key.path'
search_column = 'field'
search_stub = Squeel::Nodes::Stub(search_column)
search_term = '%search%'
keypath = Squeel::Nodes::KeyPath.new(search_relation.split('.') << search_stub)

Model.where{Squeel::Nodes::Predicate.new(keypath, :matches, search_term)}
#=> SELECT `model`.* FROM `model`
#=>   INNER JOIN `key` ON `key`.`id` = `model`.`key_id`
#=>   INNER JOIN `path` ON `path`.`id` = `key`.`path_id`
#=>   WHERE `path`.`field` LIKE '%search%'
票数 1
EN

Stack Overflow用户

发布于 2012-11-27 21:19:10

克里斯,

你在正确的轨道上。只需在KeyPath对象上调用matches方法,就会创建一个matches谓词,其keypath位于左侧,matches的参数位于右侧。Squeel的访问者将遍历左侧的keypath,到达有问题的属性,并根据它构建匹配的ARel谓词。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13579613

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档