Как я могу увидеть SQL, который будет сгенерирован данным запросом ActiveRecord в Ruby on Rails - PullRequest
109 голосов
/ 28 августа 2009

Я хотел бы увидеть оператор SQL, который сгенерирует данный запрос ActiveRecord. Я понимаю, что могу получить эту информацию из журнала после выполнения запроса, но мне интересно, есть ли метод, который можно вызвать, и запрос ActiveRecord.

Например:

SampleModel.find(:all, :select => "DISTINCT(*)", :conditions => ["`date` > #{self.date}"], :limit => 1, :order => '`date`', :group => "`date`")

Я хотел бы открыть консоль irb и добавить в конец метод, который будет показывать SQL, который сгенерирует этот запрос, но не обязательно выполнит запрос.

Ответы [ 11 ]

187 голосов
/ 16 октября 2009

Аналогично Пенджеру, но работает в любое время в консоли даже после загрузки классов и кэширования регистратора:

Для рельсов 2:

ActiveRecord::Base.connection.instance_variable_set :@logger, Logger.new(STDOUT)

Для Rails 3.0.x:

ActiveRecord::Base.logger = Logger.new(STDOUT)

Для Rails> = 3.1.0 это уже сделано по умолчанию в консолях. Если он слишком шумный и вы хотите отключить его , вы можете сделать:

ActiveRecord::Base.logger = nil
80 голосов
/ 06 января 2011

Вставьте puts query_object.class куда-нибудь, чтобы увидеть, с каким типом объекта вы работаете, затем найдите документы.

Например, в Rails 3.0 области используют ActiveRecord::Relation, который имеет метод #to_sql. Например:

class Contact < ActiveRecord::Base
  scope :frequently_contacted, where('messages_count > 10000')
end

Тогда где-то можно сделать:

puts Contact.frequently_contacted.to_sql
22 голосов
/ 20 января 2013

Это может быть старый вопрос, но я использую:

SampleModel.find(:all,
                 :select => "DISTINCT(*)",
                 :conditions => ["`date` > #{self.date}"], 
                 :limit=> 1, 
                 :order => '`date`',
                 :group => "`date`"
                 ).explain

Метод explain даст довольно подробный SQL-оператор о том, что он собирается делать

17 голосов
/ 04 января 2016

просто используйте метод to_sql, и он выведет SQL-запрос, который будет запущен. он работает с активным отношением записи.

irb(main):033:0> User.limit(10).where(:username => 'banana').to_sql
=> "SELECT  "users".* FROM "users"  WHERE "users"."username" = 'banana'
LIMIT 10"

при выполнении find он не будет работать, поэтому вам нужно будет добавить этот идентификатор вручную в запрос или запустить его, используя where.

irb(main):037:0* User.where(id: 1).to_sql
=> "SELECT "users".* FROM "users"  WHERE "users"."id" = 1"
11 голосов
/ 28 августа 2009

Это то, что я обычно делаю, чтобы генерировать SQL в консоли

-> script/console
Loading development environment (Rails 2.1.2)
>> ActiveRecord::Base.logger = Logger.new STDOUT
>> Event.first

Вы должны сделать это при первом запуске консоли, если вы делаете это после того, как набрали какой-то код, похоже, он не работает

На самом деле не могу взять кредит на себя, нашел его давным-давно в чьем-то блоге и не могу вспомнить, чей это.

11 голосов
/ 28 августа 2009

Когда я в последний раз пытался это сделать, не было никакого официального способа сделать это. Я прибег к использованию функции, которую find и ее друзья используют для генерации своих запросов напрямую. Это частный API, поэтому существует огромный риск, что Rails 3 полностью его сломает, но для отладки это нормальное решение.

Метод - construct_finder_sql(options) (lib/active_record/base.rb:1681), вам придется использовать send, потому что он приватный.

Edit : construct_finder_sql был удален в Rails 5.1.0.beta1 .

10 голосов
/ 28 августа 2009

Создайте файл .irbrc в вашем домашнем каталоге и вставьте его в:

if ENV.include?('RAILS_ENV') && !Object.const_defined?('RAILS_DEFAULT_LOGGER')
  require 'logger'
  RAILS_DEFAULT_LOGGER = Logger.new(STDOUT)
end

Это будет выводить операторы SQL в ваш сеанс irb по ходу работы.

РЕДАКТИРОВАТЬ: Извините, что по-прежнему выполнит запрос, но он мне ближе всего известен.

РЕДАКТИРОВАТЬ: Теперь с arel, вы можете создавать области / методы, пока объект возвращает ActiveRecord :: Relation и вызывает .to_sql, и он будет помещать sql, который будет выполнен.

4 голосов
/ 30 января 2013

Мой типичный способ увидеть, какой sql он использует, - это ввести «ошибку» в sql, тогда вы получите сообщения об ошибках, выпадающие на обычный регистратор (и веб-экран), в котором есть sql. Не нужно искать, куда идет стандартный вывод ...

2 голосов
/ 10 февраля 2010

Попробуйте плагин show_sql . Плагин позволяет печатать SQL без запуска

SampleModel.sql(:select => "DISTINCT(*)", :conditions => ["`date` > #{self.date}"], :limit => 1, :order => '`date`', :group => "`date`")
1 голос
/ 28 августа 2009

Вы можете изменить метод журнала подключения, чтобы вызвать исключение, предотвращающее выполнение запроса.

Это полный взлом, но, похоже, он мне подходит (Rails 2.2.2, MySQL):

module ActiveRecord
  module ConnectionAdapters
    class AbstractAdapter
      def log_with_raise(sql, name, &block)
        puts sql
        raise 'aborting select' if caller.any? { |l| l =~ /`select'/ }
        log_without_raise(sql, name, &block)
      end
      alias_method_chain :log, :raise
    end
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...