web-dev-qa-db-ja.com

Ruby on Railsの特定のActiveRecordクエリによって生成されるSQLを確認するには

特定のActiveRecordクエリが生成するSQLステートメントを見たいです。クエリが発行された後、ログからこの情報を取得できることを認識していますが、ActiveRecord Queryで呼び出すことができるメソッドがあるかどうか疑問に思っています。

例えば:

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

Irbコンソールを開き、このクエリが生成するSQLを表示するメソッドを最後に追加したいと思いますが、必ずしもクエリを実行する必要はありません。

110
rswolff

最後にこれをやろうとしたとき、公式の方法はありませんでした。私はfindとその友人が直接クエリを生成するために使用する関数を使用することに頼りました。これはプライベートAPIであるため、Rails 3が完全にそれを破るという大きなリスクがありますが、デバッグのために、それは大丈夫なソリューションです。

メソッドはconstruct_Finder_sql(options)lib/active_record/base.rb:1681)プライベートなので、sendを使用する必要があります。

編集construct_Finder_sqlRails 5.1.0.beta1 で削除されました。

11
John F. Miller

Pengerに似ていますが、クラスがロードされロガーがキャッシュされた後でもコンソールでいつでも動作します:

Rails 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
187
gtd

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
82
pathdependent

これは古い質問かもしれませんが、私は使用します:

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

explainメソッドは、何をするかについての非常に詳細なSQLステートメントを提供します

23
Akshat

単に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を実行すると機能しません。そのため、クエリにそのIDを手動で追加するか、whereを使用して実行する必要があります。

irb(main):037:0* User.where(id: 1).to_sql
=> "SELECT "users".* FROM "users"  WHERE "users"."id" = 1"
17
Itai Sagi

これは私が通常コンソールでSQLを生成するために行うことです

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

コンソールを最初に起動するときにこれを行う必要があります。コードを入力した後にこれを行うと、動作しないようです

これを本当に信用することはできず、誰かのブログからずっと前に発見し、誰がそれを覚えていない。

11
penger

ホームディレクトリに.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を出力する限り、スコープ/メソッドを構築できます。

10
nitecoder

使用するsqlを確認するための一般的な方法は、sqlに「バグ」を導入することです。その場合、問題のsqlがある通常のロガー(およびWeb画面)にエラーメッセージが表示されます。 stdoutの行き先を見つける必要はありません...

4
rogerdpack

show_sql plugin を試してください。プラグインを使用すると、SQLを実行せずに印刷できます

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

接続のログメソッドを変更して例外を発生させ、クエリが実行されないようにすることができます。

それは完全なハックですが、私にとってはうまくいくようです(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
1
also

Rails 3では、この行をconfig/environments/development.rbに追加できます

config.active_record.logger = Logger.new(STDOUT)

ただし、クエリは実行されます。しかし、半分は答えられました:

0
Timbinous