简体   繁体   English

如何查看Ruby on Rails中给定ActiveRecord查询将生成的SQL

[英]How can I see the SQL that will be generated by a given ActiveRecord query in Ruby on Rails

I would like to see the SQL statement that a given ActiveRecord Query will generate. 我想查看给定ActiveRecord查询将生成的SQL语句。 I recognize I can get this information from the log after the query has been issued, but I'm wondering if there is a method that can be called on and ActiveRecord Query. 我知道可以在发出查询后从日志中获取此信息,但是我想知道是否存在可以调用的方法和ActiveRecord Query。

For example: 例如:

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

I would like to open the irb console and tack a method on the end that would show the SQL that this query will generate, but not necessarily execute the query. 我想打开irb控制台并在最后添加一个方法,该方法将显示此查询将生成的SQL,但不一定执行该查询。

Similar to penger's, but works anytime in the console even after classes have been loaded and the logger has been cached: 与penger相似,但是即使在加载了类并且记录器已缓存之后,控制台也可以在控制台中随时运行:

For Rails 2: 对于Rails 2:

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

For Rails 3.0.x: 对于Rails 3.0.x:

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

For Rails >= 3.1.0 this is already done by default in consoles. 对于Rails> = 3.1.0,默认情况下已在控制台中完成此操作。 In case it's too noisy and you want to turn it off you can do: 如果它太嘈杂,并且您想要将其关闭 ,可以执行以下操作:

ActiveRecord::Base.logger = nil

Stick a puts query_object.class somewhere to see what type of object your working with, then lookup the docs. puts query_object.class放在某个地方以查看您使用的对象类型,然后查找文档。

For example, in Rails 3.0, scopes use ActiveRecord::Relation which has a #to_sql method. 例如,在Rails 3.0中,范围使用具有#to_sql方法的ActiveRecord::Relation For example: 例如:

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

Then, somewhere you can do: 然后,您可以在某处执行以下操作:

puts Contact.frequently_contacted.to_sql

This may be an old question but I use: 这可能是一个老问题,但我使用:

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

The explain method will give quite a detailed SQL statement on what its going to do explain方法将给出相当详细的SQL语句,说明其作用

just use to_sql method and it'll output the sql query that will be run. 只需使用to_sql方法,它将输出将要运行的sql查询。 it works on an active record relation. 它适用于活动记录关系。

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

when doing find , it won't work, so you'll need to add that id manually to the query or run it using where. 当执行find ,它将不起作用,因此您需要将该ID手动添加到查询中或使用where运行它。

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

When last I tried to do this there was no official way to do it. 我上一次尝试执行此操作时,还没有正式的方法可以执行此操作。 I resorted to using the function that find and its friends use to generate their queries directly. 我求助于使用find及其朋友用来直接生成查询的功能。 It is private API so there is a huge risk that Rails 3 will totally break it, but for debugging, it is an ok solution. 它是私有API,因此Rails 3可能会完全破坏它,但是对于调试来说,这是一个好的解决方案。

The method is construct_finder_sql(options) ( lib/active_record/base.rb:1681 ) you will have to use send because it is private. 该方法是construct_finder_sql(options)lib/active_record/base.rb:1681 ),因为它是私有的,所以您必须使用send

Edit : construct_finder_sql was removed in Rails 5.1.0.beta1 . 编辑construct_finder_sql 在Rails的5.1.0.beta1删除

This is what I usually do to get SQL generated in console 我通常这样做是为了在控制台中生成SQL

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

You have to do this when you first start the console, if you do this after you have typed some code, it doesn't seem to work 首次启动控制台时必须执行此操作,如果在键入一些代码后执行此操作,则它似乎不起作用

Can't really take credit for this, found it long time ago from someone's blog and can't remember whose it is. 无法真正相信这一点,是很久以前从某人的博客中找到它的,也不记得是谁了。

Create a .irbrc file in your home directory and paste this in: 在您的主目录中创建一个.irbrc文件,并将其粘贴到:

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

That will output SQL statements into your irb session as you go. 这样,您就可以将SQL语句输出到irb会话中。

EDIT: Sorry that will execute the query still, but it's closest I know of. 编辑:对不起,仍将执行查询,但它是我所知道的最接近的。

EDIT: Now with arel, you can build up scopes/methods as long as the object returns ActiveRecord::Relation and call .to_sql on it and it will out put the sql that is going to be executed. 编辑:现在有了arel,只要对象返回ActiveRecord :: Relation并对其调用.to_sql,就可以建立范围/方法,它将输出将要执行的sql。

My typical way to see what sql it uses is to introduce a "bug" in the sql, then you'll get an error messages spit out to the normal logger (and web screen) that has the sql in question. 我查看其使用的sql的典型方法是在sql中引入“错误”,然后您会收到一条错误消息,将其发送到具有该sql的普通记录器(和Web屏幕)。 No need to find where stdout is going... 无需找到stdout的去向...

Try the show_sql plugin . 尝试使用show_sql插件 The plugin enables you to print the SQL without running it 该插件使您无需运行即可打印SQL

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

You could change the connection's log method to raise an exception, preventing the query from being run. 您可以更改连接的日志方法以引发异常,从而阻止运行查询。

It's a total hack, but it seems to work for me (Rails 2.2.2, MySQL): 这是一个完全的hack,但是它似乎对我有用(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

In Rails 3 you can add this line to the config/environments/development.rb 在Rails 3中,您可以将此行添加到config / environments / development.rb

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

It will however execute the query. 但是它将执行查询。 But half got answered : 但是一半得到了回答:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM