简体   繁体   English

为什么ActiveRecord为大多数操作生成参数化查询,而不是为find_by生成参数化查询?

[英]Why does ActiveRecord generate parameterized queries for most operations, but not for find_by?

I'm working on a basic Rails 4.0 app to learn how it works, and I've run into something that I can't seem to figure out. 我正在研究一个基本的Rails 4.0应用程序,以了解它是如何工作的,而且我遇到了一些我似乎无法弄清楚的东西。 I've been doing queries to the default Sqlite DB via ActiveRecord, and for most queries, according to the debug output, it seems to generate parameterized queries, like so: 我一直在通过ActiveRecord对默认的Sqlite DB进行查询,对于大多数查询,根据调试输出,它似乎生成参数化查询,如下所示:

2.0.0-p247 :070 > file.save
   (0.2ms)  begin transaction
   SQL (0.6ms)  UPDATE "rep_files" SET "report_id" = ?, "file_name" = ?, "updated_at" = ?
   WHERE "rep_files"."id" = 275  [["report_id", 3], ["file_name", "hello.jpg"],
   ["updated_at", Mon, 09 Sep 2013 04:30:19 UTC +00:00]]
   (28.8ms)  commit transaction

However, whenever I do a query using find_by, it seems to just stick the provided parameters into the generated SQL: 但是,每当我使用find_by进行查询时,似乎只是将提供的参数粘贴到生成的SQL中:

2.0.0-p247 :063 > file = RepFile.find_by(report_id: "29", file_name: "1.png")
  RepFile Load (6.2ms)  SELECT "rep_files".* FROM "rep_files" WHERE
  "rep_files"."report_id" = 29 AND "rep_files"."file_name" = '1.png' LIMIT 1

It does seem to be escaping the parameters properly to prevent SQL injection: 它确实似乎正在逃避参数以防止SQL注入:

2.0.0-p247 :066 > file = RepFile.find_by(report_id: "29", file_name: "';")
  RepFile Load (0.3ms)  SELECT "rep_files".* FROM "rep_files" WHERE
  "rep_files"."report_id" = 29 AND "rep_files"."file_name" = ''';' LIMIT 1

However, it was my understanding that sending parameterized queries to the database was considered a better option than trying to escape query strings, since the parameterized option will cause the query data to bypass the database's parsing engine entirely. 但是,我的理解是,将参数化查询发送到数据库被认为是比尝试转义查询字符串更好的选择,因为参数化选项将导致查询数据完全绕过数据库的解析引擎。

So what's going on here? 那么这里发生了什么? Is this some oddity in the Sqlite adapter or the way that the debug output is generated? 这是Sqlite适配器中的一些奇怪之处还是生成调试输出的方式? If ActiveRecord is actually working like this, is there some reason for it? 如果ActiveRecord实际上是这样工作的,有什么理由吗? I can't find anything about this anywhere I've looked. 在我看过的任何地方,我找不到任何关于此事的信息。 I've started looking through the ActiveRecord code, but haven't figured anything out yet. 我已经开始查看ActiveRecord代码了,但还没有想出任何东西。

If we look at find_by in the source , we see this: 如果我们在源代码中查看find_by ,我们会看到:

def find_by(*args)
  where(*args).take
end

The take just tacks the limit 1 onto the query so we're left with where . take刚刚大头针的limit 1 ,所以我们只剩下到查询where The where method can deal with arguments in various forms with various placeholder formats, in particular, you can call where like this: where方法可以应对各种形式的各种占位符格式的论点,特别是,你可以叫where是这样的:

where('c = :pancakes', :pancakes => 6)

Using named placeholders is quite nice when you have a complicated query that is best expressed with an SQL snippet or a query that uses the same value several times so named placeholders are quite a valuable feature. 当您使用SQL片段或使用相同值的查询多次表达的复杂查询时,使用命名占位符非常好,因此命名占位符是非常有价值的功能。 Also, you can apply where to the ActiveRecord::Relation that you got from a where call and you can build the final query in pieces spread across several methods and scopes that don't know about each other. 此外,您还可以申请whereActiveRecord::Relation ,你从了where电话,你可以建立跨越多种方法和范围不知道对方的存在蔓延片最终的查询。 So, where has a problem: multiple things that don't know about each other can use the same named placeholder and conflicts can arise. 那么, where有问题:多个彼此不了解的事情可以使用相同的命名占位符,并且可能出现冲突。 One way around this problem would be to rename the named placeholders to ensure uniqueness, another way is to manually fill in the placeholders through string wrangling. 解决此问题的一种方法是重命名命名占位符以确保唯一性,另一种方法是通过字符串争论手动填充占位符。 Another problem is that different databases support different placeholder syntaxes. 另一个问题是不同的数据库支持不同的占位符语法。 ActiveRecord has chosen to manually fill in the placeholders. ActiveRecord已选择手动填写占位符。

Summary: find_by doesn't use placeholders because where doesn't and where doesn't because it is easier to build the query piecemeal through string interpolation than it is to keep track of all the placeholders and database-specific syntaxes. 简介: find_by不使用占位符,因为where不存在, where不存在,因为通过字符串插值更容易构建查询,而不是跟踪所有占位符和特定于数据库的语法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM