2009-08-27 65 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"