我想将网址字段与网址前缀(可能包含百分号)匹配,例如.where("url LIKE ?", "#{some_url}%")
。
什么是最多的Rails方式?
答案 0 :(得分:22)
如果我理解正确,你会担心{%}出现在some_url
内,这是正确的;你也应该担心嵌入式下划线(“_”),它们是“。”的LIKE版本。在正则表达式。我不认为有任何特定于Rails的方法,所以你留下了gsub
:
.where('url like ?', some_url.gsub('%', '\\\\\%').gsub('_', '\\\\\_') + '%')
这里也不需要字符串插值。您需要将反斜杠加倍以从数据库的字符串解析器中删除它们的含义,以便LIKE解析器看到简单的“\%”并知道忽略转义的百分号。
您应该检查日志以确保两个反斜杠通过。我通过检查irb
中的内容得到了令人困惑的结果,使用五个(!)得到正确的输出,但我没有看到它的意义;如果有人确实在其中五个中看到了这个意义,那么解释性评论将会受到赞赏。
更新:Jason King慷慨地提供了对逃脱逃脱角色的噩梦的简化。这允许您指定temporary escape character,以便您可以执行以下操作:
.where("url LIKE ? ESCAPE '!'", some_url.gsub(/[!%_]/) { |x| '!' + x })
我也改用了gsub
的块形式,使它不那么讨厌。
这是标准的SQL92语法,因此可以在任何支持它的数据库中使用,包括PostgreSQL,MySQL和SQLite。
将一种语言嵌入另一种语言中总是有点噩梦般的克服,而且你无法做到这一点。总是会有丑陋的小点,你只需要笑着忍受。
答案 1 :(得分:17)
从Rails版本4.2.x开始,有一个名为sanitize_sql_like
的活动记录方法。因此,您可以在模型中执行以下搜索范围:
scope :search, -> search { where('"accounts"."name" LIKE ?', "#{sanitize_sql_like(search)}%") }
并调用范围,如:
Account.search('Test_%')
生成的转义sql字符串是:
SELECT "accounts".* FROM "accounts" WHERE ("accounts"."name" LIKE 'Test\_\%%')
在此处阅读更多内容:http://edgeapi.rubyonrails.org/classes/ActiveRecord/Sanitization/ClassMethods.html
答案 2 :(得分:6)
https://gist.github.com/3656283
使用此代码,
Item.where(Item.arel_table[:name].matches("%sample!%code%"))
在"示例"之间正确地转义%
和"代码",并匹配" AAAsample%codeBBB"但不适用于" AAAsampleBBBcodeCCC"至少在MySQL,PostgreSQL和SQLite3上。
答案 3 :(得分:-3)
Post.where('url like ?', "%#{some_url + '%'}%)