首先,我使用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 举报,一经查实,本站将立刻删除。