रूबी ऑन रूल्स में किसी दिए गए ActiveRecord क्वेरी द्वारा उत्पन्न SQL को कैसे देख सकता हूं


116

मैं एसक्यूएल स्टेटमेंट को देखना चाहूंगा जो कि किसी दिए गए ActiveRecord Query को जनरेट करेगा। मैं मानता हूं कि क्वेरी जारी किए जाने के बाद मैं लॉग से यह जानकारी प्राप्त कर सकता हूं, लेकिन मैं सोच रहा हूं कि क्या कोई विधि है जिस पर और ActiveRecord क्वेरी को कॉल किया जा सकता है।

उदाहरण के लिए:

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

मैं irb कंसोल को खोलना चाहता हूं और अंत में एक विधि से निपटना चाहता हूं जो SQL को दिखाएगा कि यह क्वेरी उत्पन्न करेगा, लेकिन जरूरी नहीं कि क्वेरी निष्पादित हो।

जवाबों:


12

जब आखिरी बार मैंने ऐसा करने की कोशिश की, तो इसे करने का कोई आधिकारिक तरीका नहीं था। मैंने उस फ़ंक्शन का उपयोग करने का सहारा लिया जो findऔर उसके दोस्त सीधे अपने प्रश्नों को उत्पन्न करने के लिए उपयोग करते हैं। यह निजी एपीआई है इसलिए एक बड़ा जोखिम है कि रेल 3 पूरी तरह से इसे तोड़ देगा, लेकिन डिबगिंग के लिए, यह एक ठीक समाधान है।

विधि है construct_finder_sql(options)( lib/active_record/base.rb:1681) आपको इसका उपयोग करना होगा sendक्योंकि यह निजी है।

संपादित करें : construct_finder_sql रेल 5.1.0.beta1 में हटा दिया गया था


1
यह वही है जो मैं सोच रहा हूँ। मुझे लगता है कि कोई व्यक्ति एक ऐसा प्लगइन लिख सकता है जो कुछ ऐसा करेगा: SampleModel.find (: all,: select => "DISTINCT (*)",: conditions => [" date> " # {self.date} "]: सीमा => 1,: आदेश => ' date',: समूह => " date") .show_generated_sql और यह कॉल build_finder_sql विधि है।
रस्सोल्फ 17

1
DataMapper के साथ आप क्योंकि यह क्वेरी अभी नहीं चला सकता है। दूसरी ओर ActiveRecord क्वेरी को तुरंत निष्पादित करता है। show_generated_sqlसे पहले से ही पुनः प्राप्त डेटासेट पर अभिनय किया जाएगा find
जॉन एफ। मिलर

4
रेल में 3 construct_finder_sqlवास्तव में निकाल दिया जाता है
Veger

190

पेजर के समान, लेकिन कक्षाओं में लोड होने के बाद भी कभी भी कंसोल में काम करता है और लकड़हारा कैश किया गया है:

रेल 2 के लिए:

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

रेल के लिए 3.0.x:

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

रेल के लिए = = 3.1.0 यह पहले से ही कंसोल में डिफ़ॉल्ट रूप से किया जाता है। मामले में यह बहुत शोर है और आप इसे बंद करना चाहते हैं आप कर सकते हैं:

ActiveRecord::Base.logger = nil

यह मेरे लिए काम नहीं कर रहा है rails console। क्या यह केवल शेल से सीधे लोड किए गए irb के लिए काम करता है? (या यह रेल 3 के लिए हटा दिया गया था?)
एरिक हू

2
उन्होंने इसे रेल 3 के लिए एक अधिक समझदार स्थान पर स्थानांतरित कर दिया ... मेरा अद्यतन संस्करण देखें।
gtd

क्या सांत्वना शुरू करने पर हर बार स्वचालित रूप से ऐसा करने का कोई तरीका है? पहले लोड हुक जैसा कुछ?
स्ट्रीम

1
@ stream7..मुझे नहीं पता कि यू को अभी इसकी आवश्यकता है, लेकिन आप इस कोड को स्थानांतरित कर सकते हैं environment.rb.. .. http://weblog.jamisbuck.org/2007/1/8/watching-activerecord-doif "irb" == $0;ActiveRecord::Base.logger = Logger.new(STDOUT);end में टिप्पणियों से इसे भूल गए
-इट

यह प्रश्न का उत्तर नहीं देता है: क्वेरी को चलाए बिना डीबग करते समय किसी विशेष क्वेरी के लिए sql कैसे दिखाएं।
bradw2k

87

एक छड़ी 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

3
यह जवाब क्यों नहीं दिया गया? रेल 3 के लिए यह एक बेहतर उत्तर है - आप अंत में ".to_sql" डालकर किसी भी AR :: संबंध कथन के परिणाम प्राप्त कर सकते हैं। यह प्रश्न उस उत्तर को भी प्रदान करता है: stackoverflow.com/questions/3814738/…
स्टीव मिडग्ली सेप

5
खबरदार: यदि includesआपके संबंध में आपके पास सभी एसक्यूएल नहीं हैं
बैरी केली

3
@BarryKelly ऐसा क्यों है?
विष्णु नारंग

25

यह एक पुराना प्रश्न हो सकता है लेकिन मैं इसका उपयोग करता हूं:

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

explainविधि अपने क्या करने जा क्या पर काफी विस्तृत SQL विवरण दे देंगे


3
यह क्वेरी भी चलाएगा, जो शायद लोग नहीं चाहते, सिर्फ रिकॉर्ड के लिए।
इब्राहिम

22

बस 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यह काम करेगा, तो यह काम नहीं करेगा, इसलिए आपको उस आईडी को मैन्युअल रूप से क्वेरी में जोड़ना होगा या जहां इसे इस्तेमाल करना होगा।

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

11

यह वही है जो मैं आमतौर पर कंसोल में SQL जनरेट करने के लिए करता हूं

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

आपको यह तब करना है जब आप पहली बार कंसोल शुरू करते हैं, यदि आप कुछ कोड टाइप करने के बाद ऐसा करते हैं, तो यह काम नहीं करता है

वास्तव में इसके लिए श्रेय नहीं लिया जा सकता है, यह बहुत समय पहले किसी के ब्लॉग से मिला था और यह याद नहीं है कि यह किसका है।


1
मुझे पूरा यकीन है कि यह जामिस बक का ब्लॉग था: weblog.jamisbuck.org/2007/1/8/…
rswolff

1
मुझे यकीन नहीं है कि यह रेल 2.3 या मेरे वातावरण में कुछ के कारण है, लेकिन यह मेरे लिए काम नहीं करता है। मेरी प्रतिक्रिया नीचे देखें।
gtd

यह एक बेहतरीन समाधान IMO है।
बेंजामिन एटकिन

10

अपने घर निर्देशिका में .irbrc फ़ाइल बनाएँ और इसे इसमें चिपकाएँ:

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

जैसे ही आप जाते हैं आपके SQL सत्र में SQL स्टेटमेंट आउटपुट होंगे।

संपादित करें: क्षमा करें जो क्वेरी को अभी भी निष्पादित करेगा, लेकिन यह निकटतम है जो मुझे पता है।

EDIT: अब arel के साथ, आप स्कॉप / तरीके बना सकते हैं, जब तक कि ऑब्जेक्ट ActiveRecord ::ationation और call .to_sql को लौटाता है और यह निष्पादित होने जा रहे sql को बाहर कर देगा।


यह वही है जो मैं कर रहा हूं, लेकिन मैं अधिक दिलचस्पी रखता हूं कि अनुमानित एसक्यूएल ActiveRecord क्वेरी उत्पन्न करेगा। मुझे आश्चर्य है कि ऐसा करने का कोई सरल तरीका नहीं है ...
rswolff

5

यह देखने के लिए मेरा विशिष्ट तरीका है कि sql क्या उपयोग करता है, यह sql में "बग" को पेश करता है, फिर आपको सामान्य लॉगर (और वेब स्क्रीन) पर एक त्रुटि संदेश मिलेगा, जिसमें प्रश्न में sql है। कोई जरूरत नहीं है, जहां stdout जा रहा है ...


1
शानदार लेकिन तेज समाधान :)
JAN Janočko

2

Show_sql प्लगइन आज़माएं । प्लगइन आपको SQL को चलाने के बिना प्रिंट करने में सक्षम बनाता है

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

1
ऐसा लगता है कि लिंक टूट गया (404 त्रुटि)। शायद, रयान बिग ने प्लगइन को हटा दिया।
DNNX

1

आप अपवाद को बढ़ाने के लिए कनेक्शन की लॉग विधि को बदल सकते हैं, क्वेरी को चलने से रोक सकते हैं।

यह कुल हैक है, लेकिन यह मेरे लिए काम करता है (रेल 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

0

रेल 3 में आप इस लाइन को विन्यास / वातावरण / विकास में जोड़ सकते हैं

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

हालांकि यह क्वेरी को निष्पादित करेगा। लेकिन आधा जवाब मिला:

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.