我想测试一段代码是否执行尽可能少的 SQL 查询。
ActiveRecord::TestCase
似乎有自己的 assert_queries
方法,可以做到这一点。但由于我没有修补 ActiveRecord,它对我来说没什么用。
RSpec 或 ActiveRecord 是否提供任何官方、公开的方法来计算代码块中执行的 SQL 查询的数量?
最佳答案
我认为您通过提及 assert_queries
回答了您自己的问题,但这里是:
我建议您查看 assert_queries
背后的代码,并使用它来构建您自己的方法,您可以使用该方法对查询进行计数。这里涉及的主要魔法是这一行:
ActiveSupport::Notifications.subscribe('sql.active_record', SQLCounter.new)
今天早上我做了一点小改动,并删除了 ActiveRecord 中执行查询计数的部分,并提出了这个:
module ActiveRecord
class QueryCounter
cattr_accessor :query_count do
0
end
IGNORED_SQL = [/^PRAGMA (?!(table_info))/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /^SHOW max_identifier_length/]
def call(name, start, finish, message_id, values)
# FIXME: this seems bad. we should probably have a better way to indicate
# the query was cached
unless 'CACHE' == values[:name]
self.class.query_count += 1 unless IGNORED_SQL.any? { |r| values[:sql] =~ r }
end
end
end
end
ActiveSupport::Notifications.subscribe('sql.active_record', ActiveRecord::QueryCounter.new)
module ActiveRecord
class Base
def self.count_queries(&block)
ActiveRecord::QueryCounter.query_count = 0
yield
ActiveRecord::QueryCounter.query_count
end
end
end
您将能够在任何地方引用 ActiveRecord::Base.count_queries
方法。向它传递一个运行查询的 block ,它将返回已执行的查询数:
ActiveRecord::Base.count_queries do
Ticket.first
end
为我返回“1”。要完成这项工作:将其放在 lib/active_record/query_counter.rb
的文件中,并在 config/application.rb
文件中要求它,如下所示:
require 'active_record/query_counter'
你好!
可能需要一点解释。当我们调用此行时:
ActiveSupport::Notifications.subscribe('sql.active_record', ActiveRecord::QueryCounter.new)
我们连接到 Rails 3 的小通知框架。它是 Rails 最新主要版本的一个 Shiny 的小补充,没有人真正知道。它允许我们使用 subscribe
方法订阅 Rails 中的事件通知。我们将要订阅的事件作为第一个参数传递,然后将响应 call
的任何对象作为第二个参数传递。
在这种情况下,当执行查询时,我们的小查询计数器将尽职尽责地增加 ActiveRecord::QueryCounter.query_count 变量,但仅限于真正的查询。
无论如何,这很有趣。希望对你有用。
https://stackoverflow.com/questions/5490411/