特定のActiveRecordクエリが生成するSQLステートメントを見たいです。クエリが発行された後、ログからこの情報を取得できることを認識していますが、ActiveRecord Queryで呼び出すことができるメソッドがあるかどうか疑問に思っています。
例えば:
SampleModel.find(:all, :select => "DISTINCT(*)", :conditions => ["`date` > #{self.date}"], :limit => 1, :order => '`date`', :group => "`date`")
Irbコンソールを開き、このクエリが生成するSQLを表示するメソッドを最後に追加したいと思いますが、必ずしもクエリを実行する必要はありません。
最後にこれをやろうとしたとき、公式の方法はありませんでした。私はfind
とその友人が直接クエリを生成するために使用する関数を使用することに頼りました。これはプライベートAPIであるため、Rails 3が完全にそれを破るという大きなリスクがありますが、デバッグのために、それは大丈夫なソリューションです。
メソッドはconstruct_Finder_sql(options)
(lib/active_record/base.rb:1681
)プライベートなので、send
を使用する必要があります。
編集:construct_Finder_sql
Rails 5.1.0.beta1 で削除されました。
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
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
これは古い質問かもしれませんが、私は使用します:
SampleModel.find(:all,
:select => "DISTINCT(*)",
:conditions => ["`date` > #{self.date}"],
:limit=> 1,
:order => '`date`',
:group => "`date`"
).explain
explain
メソッドは、何をするかについての非常に詳細なSQLステートメントを提供します
単に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"
これは私が通常コンソールでSQLを生成するために行うことです
-> script/console
Loading development environment (Rails 2.1.2)
>> ActiveRecord::Base.logger = Logger.new STDOUT
>> Event.first
コンソールを最初に起動するときにこれを行う必要があります。コードを入力した後にこれを行うと、動作しないようです
これを本当に信用することはできず、誰かのブログからずっと前に発見し、誰がそれを覚えていない。
ホームディレクトリに.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を出力する限り、スコープ/メソッドを構築できます。
使用するsqlを確認するための一般的な方法は、sqlに「バグ」を導入することです。その場合、問題のsqlがある通常のロガー(およびWeb画面)にエラーメッセージが表示されます。 stdoutの行き先を見つける必要はありません...
show_sql plugin を試してください。プラグインを使用すると、SQLを実行せずに印刷できます
SampleModel.sql(:select => "DISTINCT(*)", :conditions => ["`date` > #{self.date}"], :limit => 1, :order => '`date`', :group => "`date`")
接続のログメソッドを変更して例外を発生させ、クエリが実行されないようにすることができます。
それは完全なハックですが、私にとってはうまくいくようです(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
Rails 3では、この行をconfig/environments/development.rbに追加できます
config.active_record.logger = Logger.new(STDOUT)
ただし、クエリは実行されます。しかし、半分は答えられました: