在 Rails 查询中转义引号
Posted
技术标签:
【中文标题】在 Rails 查询中转义引号【英文标题】:Escaping Quotes in Rails Query 【发布时间】:2020-07-17 08:38:42 【问题描述】:我有包含以下字段的商家表
Merchant(id: integer, name: string, logo: string, description: text, categories: string, created_at: datetime, updated_at: datetime)
我想使用 name 属性运行 first_or_create 查询。问题是名称列包含单引号,例如 Brandy's Boy。
mname = "brandy's boy"
conds = "lower(name) = #mname"
Merchant.where(conds)
Merchant Load (1.5ms) SELECT "merchants".* FROM "merchants" WHERE "merchants"."deleted_at" IS NULL AND (lower(name) = 'brandy's boy ') LIMIT $1 [["LIMIT", 11]]
输出:
#<Merchant::ActiveRecord_Relation:0x000055d0f72a2ce0>
但是当我运行静态查询时,这会给我输出。
Merchant.where("lower(name) = ?", 'Brandy\'s Boy'.downcase)
Merchant Load (3.7ms) SELECT "merchants".* FROM "merchants" WHERE "merchants"."deleted_at" IS NULL AND (lower(name) = 'brandy''s boy') LIMIT $1 [["LIMIT", 11]]
#<ActiveRecord::Relation [#<Merchant id: 1413, name: "Brandy's Boy", logo: nil, description: "ABC", categories: [], created_at: "2020-07-17 07:32:29", updated_at: "2020-07-17 07:32:29">]>
但是变量 mname 是在循环中填充的,它是动态的。所以在这种情况下,我需要转义单引号并获得所需的结果(现有 Brandy's Boy Merchant 对象)
请帮忙。
【问题讨论】:
【参考方案1】:您不需要插值来为where
创建参数,只需绑定它/它们:
Merchant.where("lower(name) = ?", mname)
Active Record 会处理这个问题,您的查询很可能如下所示:
SELECT "merchants".* FROM "merchants" WHERE (lower(name) = 'brandy''s boy')
转义是在框架的内部进行的,来自文档:
如果传递一个数组,则处理数组的第一个元素 作为模板,其余元素插入到 模板来生成条件。 Active Record 负责 构建查询以避免注入攻击,并将从 ruby 类型到需要的数据库类型。元素被插入 按它们出现的顺序放入字符串中。
User.where(["name = ? and email = ?", "Joe", "joe@example.com"])
# SELECT * FROM users WHERE name = 'Joe' AND email = 'joe@example.com';
在做:
Merchant.where(["lower(name) = ?", mname])
和做的差不多一样:
Merchant.where("lower(name) = ?", mname)
因此您的查询按上述方式处理。
【讨论】:
以上是关于在 Rails 查询中转义引号的主要内容,如果未能解决你的问题,请参考以下文章