微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ruby-on-rails – 使用Squeel时,是否可以有条件地在where块中添加子句?

首先,我使用Rails v3.2.9与squeel 1.0.13,这是我正在尝试做的事情:

我想使用三种识别信息中的任何一种搜索客户 – 姓名,出生日期(dob)和社会保险号码(罪).结果集必须包含任何具有任何标识符的记录 – 条件的OR.我以前在squeel做过这个,看起来像是这样的:

scope :by_any,->(sin,name,dob){ where{(client.sin == "#{sin}") | (client.name =~ "%#{name}%") | (client.dob == "#{dob}")} }

只要我提供所有标识符,这都可以正常工作.但是,如果我只有一个名字怎么办?以上范围导致:

SELECT "clients".* FROM "clients" WHERE ((("clients"."sin" IS NULL OR "clients"."name" ILIKE '%John Doe%') OR "clients"."dob" IS NULL))

包括sin为null的客户端集和dob为null的客户端集以及名为“John Doe”的请求客户端集.

因此,请输入我有条件地将where子句添加到where块的尝试.起初,我尝试使用nil检查值?方法

def self.by_any (sin,dob)
  where do
    (clients.sin == "#{sin}" unless sin.nil?) |
    (clients.name =~ "%#{name}" unless name.nil?) |
    (clients.dob == "#{dob}" unless dob.nil?)
  end

这导致:

SELECT "clients".* FROM "clients" WHERE ('t')

提出了许多其他问题,比如那个问题的处理方式,但这是一个切线.

如果没有为每个排列编写where子句,有没有办法可以有条件地添加子句?

解决方法

所以,这不是最漂亮的东西,但它会照顾你所追求的.

def self.by_any(sin,dob)
  where do
    [
      sin.presence && clients.sin == "#{sin}",name.presence && clients.name =~ "%#{name}",dob.presence && clients.dob == "#{dob}"
    ].compact.reduce(:|)
    # compact to remove the nils,reduce to combine the cases with |
  end
end

基本上,[a,b,c] .reduce(:f)返回(a.f(b)).f(c).在这种情况下,f,被调用方法是管道,所以我们得到(a.|(b)).|(c),在较少混淆的表示法中,是(a | b)| C.

它的工作原理是,在squeel中,谓词运算符(==,=〜等等)返回一个Predicate节点,因此我们可以在将它们与|连接之前独立构造它们.

在所有三个都为零的情况下,它返回所有记录.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐