Search code examples
ruby-on-railsrubyactivesupport

How to subscribe to all query methods with ActiveSupport::Notifications


I am not understanding an ActiveSupport::Notifications behaviour. I'm currently using ruby 2.5.0 and rails 5.2 and I'm trying to make a custom matcher for rspec (3.7.0) to verify if a query has been triggered or not. Currently my matcher looks like this:

RSpec::Matchers.define :trigger_query do
  supports_block_expectations

  match do |block|
    count_queries(&block).positive?
  end

  def count_queries &block
    count = 0

    counter_f = ->(_name, _started, _finished, _unique_id, payload) {
      count += 1 unless %w[CACHE SCHEMA].include?(payload[:name])
    }

    ActiveSupport::Notifications.subscribed(
      counter_f,
      "sql.active_record",
      &block
    )

    count
  end
end

But when I try to use it an unexpected behaviour happens

# works
expect { Question.first(2) }.to trigger_query
# doesn't work
expect { Question.limit(2) }.to trigger_query

Can anyone tell me what I've done wrong?


Solution

  • Query methods like limit will build a relation but no queries to the database will be made until a caller tries to get data from it.

    One easy way to do this is to turn the relation into an array:

    Question.limit(2).to_a