Ruby on Rails에서 주어진 ActiveRecord 쿼리에 의해 생성 될 SQL을 어떻게 볼 수 있습니까?


116

주어진 ActiveRecord 쿼리가 생성 할 SQL 문을보고 싶습니다. 쿼리가 실행 된 후 로그에서이 정보를 얻을 수 있다는 것을 알고 있지만 호출 할 수있는 메서드와 ActiveRecord 쿼리가 있는지 궁금합니다.

예를 들면 :

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

irb 콘솔을 열고이 쿼리가 생성 할 SQL을 보여 주지만 반드시 쿼리를 실행하지는 않는 메서드를 끝에 추가하고 싶습니다.

답변:


12

마지막으로 시도했을 때 공식적인 방법이 없었습니다. 나는 find그들과 그 친구들이 쿼리를 직접 생성하는 데 사용하는 함수를 사용했습니다. 프라이빗 API이므로 Rails 3가 완전히 망가뜨릴 위험이 크지 만 디버깅을 위해서는 괜찮은 솔루션입니다.

방법은 construct_finder_sql(options)( lib/active_record/base.rb:1681) send개인용이므로 사용해야 합니다.

편집 : construct_finder_sql 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

1
DataMapper를 사용하면 쿼리를 바로 실행하지 않기 때문에 가능합니다. 반면 ActiveRecord는 쿼리를 즉시 실행합니다. show_generated_sql에서 이미 검색된 데이터 세트에서 작동 find합니다.
John F. Miller

4
레일에서 3 construct_finder_sql실제로 제거
Veger

190

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

이것은에서 나를 위해 작동하지 않습니다 rails console. 쉘에서 직접로드 된 irb에서만 작동합니까? (또는 레일 3에서 제거 되었습니까?)
Eric Hu

2
그들은 Rails 3를 위해 더 합리적인 장소로 옮겼습니다. 업데이트 된 버전을보세요.
gtd

콘솔을 시작할 때마다이 작업을 자동으로 수행 할 수있는 방법이 있습니까? 로드 전 후크와 같은 것?
stream7 2011-07-06

1
@ stream7 environment.rb.. if "irb" == $0;ActiveRecord::Base.logger = Logger.new(STDOUT);end나는 지금 이것이 필요한지 모르겠지만이 코드를 .. .. http://weblog.jamisbuck.org/2007/1/8/watching-activerecord-do의
rubyprince

이것은 쿼리를 실행하지 않고 디버깅하는 동안 특정 쿼리에 대한 SQL을 표시하는 방법이라는 질문에 대답하지 않습니다.
bradw2k

87

막대기 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

3
이 답변이 찬성되지 않는 이유는 무엇입니까? Rails 3의 경우 더 나은 답변입니다. 끝에 ".to_sql"을 입력하여 AR :: Relation 문의 결과를 얻을 수 있습니다. 이 질문은 그 대답을 제공합니다 stackoverflow.com/questions/3814738/...을
스티브 Midgley

5
주의 : includes관계에 있는 경우 모든 SQL을 얻을 수는 없습니다
Barry Kelly

3
@BarryKelly 왜 그럴까요?
Vishnu Narang

25

이것은 오래된 질문 일 수 있지만 다음을 사용합니다.

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

그만큼 explain 메서드는 수행 할 작업에 대한 자세한 SQL 문을 제공합니다.


3
또한 레코드를 위해 사람들이 원하는 것이 아닐 수도있는 쿼리를 실행합니다.
Ibrahim

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작동하지 않으므로 해당 ID를 쿼리에 수동으로 추가하거나 where를 사용하여 실행해야합니다.

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
나는 그것이 Jamis Buck의 블로그 였다고 확신한다 : weblog.jamisbuck.org/2007/1/8/…
rswolff

1
Rails 2.3 때문인지 내 환경에 있는지 확실하지 않지만 이것은 나를 위해 작동하지 않습니다. 아래 내 응답을 참조하십시오.
gtd

이것은 훌륭한 솔루션 IMO입니다.
Benjamin Atkin

10

홈 디렉토리에 .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을 출력합니다.


이것이 제가했던 일이지만 ActiveRecord 쿼리가 생성 할 예상 SQL을 보는 데 더 관심이 있습니다. 이 작업을 수행하는 간단한 방법이 없다는 것에 놀랐습니다 ...
rswolff

5

내가 사용하는 SQL을 확인하는 일반적인 방법은 SQL에 "버그"를 도입하는 것입니다. 그러면 해당 SQL이있는 일반 로거 (및 웹 화면)에 오류 메시지가 뱉어집니다. stdout이 어디로 가는지 찾을 필요가 없습니다 ...


1
화려한하지만 빠른 솔루션 :
얀 Janočko

2

show_sql 플러그인을 사용해보십시오 . 플러그인을 사용하면 SQL을 실행하지 않고도 인쇄 할 수 있습니다.

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

1
링크가 끊어진 것 같습니다 (404 오류). 아마도 Ryan Bigg가 플러그인을 삭제했을 것입니다.
DNNX

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

0

Rails 3에서는이 줄을 config / environments / development.rb에 추가 할 수 있습니다.

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

그러나 쿼리를 실행합니다. 그러나 절반은 답을 얻었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.