2009-08-27 70 views
96

我希望看到给定的ActiveRecord Query将生成的SQL语句。我知道我可以在查询发布后从日志中获取这些信息,但我想知道是否有可以调用的方法和ActiveRecord Query。我如何看到由Ruby on Rails中的给定ActiveRecord查询生成的SQL

例如:

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

我想打开IRB控制台和粘性末端有一个方法,将显示该查询将生成SQL,但不一定执行查询。

回答

11

上次我试图做到这一点时,没有官方的方法来做到这一点。我诉诸于使用find及其朋友直接生成查询的功能。这是私有API,因此Rails 3将会完全破坏它,但是对于调试来说,这是一个很好的解决方案。

方法是construct_finder_sql(options)lib/active_record/base.rb:1681)您将不得不使用send,因为它是私人的。

编辑construct_finder_sqlwas removed in Rails 5.1.0.beta1

+1

这是接近我在想什么。我想一个人可以编写一个插件,它可以执行如下操作: SampleModel.find(:all,:select =>“DISTINCT(*)”,:conditions => [“'date'>#{self.date} “],:limit => 1,:order =>''date'',:group =>”'date'“)。show_generated_sql 并将此调用为construct_finder_sql方法。 – rswolff 2009-08-28 17:02:43

+1

使用DataMapper你可以,因为它不会马上运行查询。另一方面ActiveRecord立即执行查询。 'show_generated_sql'将作用于已经从'find'检索到的数据集。 – 2009-08-28 20:55:05

+4

In Rails 3'construct_finder_sql'确实被删除 – Veger 2011-12-26 14:21:29

9

在你的home目录创建一个.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。

+0

+1勇敢的努力 – MattC 2009-08-27 23:58:44

+0

这是我一直在做什么,但我更感兴趣的是简单地看到投影SQL ActiveRecord的查询将产生。我很惊讶没有简单的方法来做到这一点... – rswolff 2009-08-28 16:59:04

1

你可以更改连接的日志方法抛出一个异常,防止查询从正在运行。

这是一个总的黑客,但它似乎对我(的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 
9

这是我平时做的就是在控制台

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

你必须这样做,当你第一次启动控制台,如果你这样做后,你已经键入了一些代码,它似乎并不工作

不能真正承认这一点,发现很久以前谁家博客,并不记得它是谁。

+1

我很确定这是Jamis Buck的博客:http://weblog.jamisbuck.org/2007/1/8/watching-activerecord-do-it-s-thing – rswolff 2009-08-28 17:03:41

+1

我不确定这是由于Rails 2.3还是我的环境中的原因,但这对我不起作用。请参阅下面的回复。 – gtd 2009-10-16 05:23:56

+0

完美无瑕地为我工作。即使输入了一些代码。 – pungoyal 2013-05-09 06:18:14

181

到penger的类似,但作品随时在控制台即使类已经被加载并记录器已被缓存:

对于梁2:

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

对于Rails的3.0.x中:

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

对于滑轨> = 3.1。0这已经在控制台中默认完成。如果它太嘈杂,你想关闭它你可以这样做:

ActiveRecord::Base.logger = nil 
+0

这在'rails console'中不适用于我。它只适用于直接从shell加载的irb吗? (或者它被移除了轨道3?) – 2011-03-23 19:34:04

+2

他们将它移到了Rails 3更明智的地方...请参阅我的更新版本。 – gtd 2011-04-07 03:08:12

+0

每次启动控制台时,有没有办法自动执行此操作?就像一个前负荷钩? – stream7 2011-07-06 07:20:45

2

尝试show_sql plugin。该插件允许您打印SQL不运行它

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

看起来像链接被破坏(404错误)。 Ryan Bigg可能会删除该插件。 – DNNX 2012-01-25 20:45:35

69

puts query_object.class某处看到你的工作是什么类型的对象,然后查找的文档。

例如,在滑轨3.0,范围使用ActiveRecord::Relation具有#to_sql方法。例如:

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

然后,地方你可以这样做:

puts Contact.frequently_contacted.to_sql 
+2

为什么这个答案没有upvoted?对于Rails 3来说,这是一个更好的解决方案 - 只需将“.to_sql”放在最后,即可获得任何AR :: Relation语句的结果。这个问题也提供了答案:http://stackoverflow.com/questions/3814738/how-can-i-get-sql-statement-created-by-activerecordfind-without-actually-execut – 2014-09-17 05:03:26

+4

当心:你不会得到所有的SQL,如果你在你的关系中有'includes' – 2015-01-23 18:25:05

+1

@BarryKelly为什么? – 2016-05-17 07:27:55

0

在Rails 3,您可以将此行添加到config /环境/ development.rb

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

它将然而执行查询。但一半得到了回答:

+0

这是简单的部分... – 2013-04-23 02:06:07

18

这可能是一个老问题,但我使用:

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

explain方法会给什么它打算做

+2

它也会运行查询,这可能不是人们想要的,只是为了记录。 – Ibrahim 2016-08-24 16:48:25

1

我的典型方式相当详细的SQL语句看看它使用什么SQL是在sql中引入一个“bug”,那么你会得到一个错误消息吐出到正常的记录器(和网页屏幕),有问题的SQL。没有必要找到标准输出去哪里...

11

只是使用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来查询或使用其中运行它。

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