From 64747654ca661d695622c0ad9e33b8d9e6df8048 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Wed, 5 Oct 2011 18:11:25 +0100 Subject: Revert "Raise error on unknown primary key." This reverts commit ee2be435b1e5c0e94a4ee93a1a310e0471a77d07. --- activerecord/lib/active_record/relation.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record/relation.rb') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index bf61d79a2c..ecefaa633c 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -13,7 +13,7 @@ module ActiveRecord # These are explicitly delegated to improve performance (avoids method_missing) delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to => :to_a - delegate :table_name, :quoted_table_name, :primary_key, :primary_key?, :quoted_primary_key, :connection, :column_hash,:to => :klass + delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key, :connection, :column_hash,:to => :klass attr_reader :table, :klass, :loaded attr_accessor :extensions, :default_scoped @@ -36,7 +36,7 @@ module ActiveRecord def insert(values) primary_key_value = nil - if primary_key? && Hash === values + if primary_key && Hash === values primary_key_value = values[values.keys.find { |k| k.name == primary_key }] @@ -70,7 +70,7 @@ module ActiveRecord conn.insert( im, 'SQL', - primary_key? && primary_key, + primary_key, primary_key_value, nil, binds) -- cgit v1.2.3 From 562583c7667f508493ab8c5b1a4215087fafd22d Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Fri, 4 Nov 2011 16:10:18 +0000 Subject: Add ActiveRecord::Relation#uniq for toggling DISTINCT in the SQL query --- activerecord/lib/active_record/relation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/relation.rb') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index ecefaa633c..3baf9b3f49 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -7,7 +7,7 @@ module ActiveRecord JoinOperation = Struct.new(:relation, :join_class, :on) ASSOCIATION_METHODS = [:includes, :eager_load, :preload] MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :bind] - SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order] + SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order, :uniq] include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches -- cgit v1.2.3 From e7b7b4412380e7ce2d8e6ae402cb7fe02d7666b8 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Tue, 20 Sep 2011 10:50:08 -0700 Subject: implements AR::Relation#explain This is a first implementation, EXPLAIN is highly dependent on the database and I have made some compromises. On one hand, the method allows you to run the most common EXPLAIN and that's it. If you want EXPLAIN ANALYZE in PostgreSQL you need to do it by hand. On the other hand, I've tried to construct a string as close as possible to the ones built by the respective shells. The rationale is that IMO the user should feel at home with the output and recognize it at first sight. Per database. I don't know whether this implementation is going to work well. Let's see whether people like it. --- activerecord/lib/active_record/relation.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'activerecord/lib/active_record/relation.rb') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 3baf9b3f49..f0891440a6 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -143,6 +143,22 @@ module ActiveRecord super end + def explain + queries = [] + callback = lambda do |*args| + payload = args.last + queries << payload[:sql] unless payload[:exception] || %w(SCHEMA EXPLAIN).include?(payload[:name]) + end + + ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do + to_a + end + + queries.map do |sql| + @klass.connection.explain(sql) + end.join + end + def to_a return @records if loaded? -- cgit v1.2.3 From 1be9830d4d99e2bf56f1cadf74b843f22d66da35 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Fri, 25 Nov 2011 14:29:34 -0800 Subject: add the query to AR::Relation#explain output Rationale: this is more readable if serveral queries are involved in one call. Also, it will be possible to let AR log EXPLAINs automatically in production mode, where queries are not even around. --- activerecord/lib/active_record/relation.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record/relation.rb') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index f0891440a6..0c32ad5139 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- require 'active_support/core_ext/object/blank' require 'active_support/core_ext/module/delegation' @@ -155,8 +156,8 @@ module ActiveRecord end queries.map do |sql| - @klass.connection.explain(sql) - end.join + "EXPLAIN for: #{sql}\n#{@klass.connection.explain(sql)}" + end.join("\n") end def to_a -- cgit v1.2.3 From 0306f82e0c3cda3aad1b45eb0c3a359c254b62cc Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Fri, 2 Dec 2011 04:32:18 -0800 Subject: implements automatic EXPLAIN logging for slow queries --- activerecord/lib/active_record/relation.rb | 45 +++++++++++++++++++----------- 1 file changed, 29 insertions(+), 16 deletions(-) (limited to 'activerecord/lib/active_record/relation.rb') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 0c32ad5139..e69e1aeaf8 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -10,11 +10,12 @@ module ActiveRecord MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :bind] SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order, :uniq] - include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches + include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain # These are explicitly delegated to improve performance (avoids method_missing) delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to => :to_a - delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key, :connection, :column_hash,:to => :klass + delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key, + :connection, :column_hash, :auto_explain_threshold_in_seconds, :to => :klass attr_reader :table, :klass, :loaded attr_accessor :extensions, :default_scoped @@ -144,23 +145,35 @@ module ActiveRecord super end - def explain - queries = [] - callback = lambda do |*args| - payload = args.last - queries << payload[:sql] unless payload[:exception] || %w(SCHEMA EXPLAIN).include?(payload[:name]) - end + # Runs EXPLAIN on the query or queries triggered by this relation and + # returns the result as a string. The string is formatted imitating the + # ones printed by the database shell. + # + # Note that this method actually runs the queries, since the results of some + # are needed by the next ones when eager loading is going on. + # + # Please see further details in the + # {Active Record Query Interface guide}[http://edgeguides.rubyonrails.org/active_record_querying.html#running-explain]. + def explain + results, sqls, binds = collecting_sqls_for_explain { exec_query } + exec_explain(sqls, binds) + end - ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do - to_a + def to_a + # We monitor here the entire execution rather than individual SELECTs + # because from the point of view of the user fetching the records of a + # relation is a single unit of work. You want to know if this call takes + # too long, not if the individual queries take too long. + # + # It could be the case that none of the queries involved surpass the + # threshold, and at the same time the sum of them all does. The user + # should get a query plan logged in that case. + logging_query_plan do + exec_query end - - queries.map do |sql| - "EXPLAIN for: #{sql}\n#{@klass.connection.explain(sql)}" - end.join("\n") end - def to_a + def exec_query return @records if loaded? default_scoped = with_default_scope @@ -191,6 +204,7 @@ module ActiveRecord @loaded = true @records end + private :exec_query def as_json(options = nil) #:nodoc: to_a.as_json(options) @@ -543,6 +557,5 @@ module ActiveRecord # ignore raw_sql_ that is used by Oracle adapter as alias for limit/offset subqueries string.scan(/([a-zA-Z_][.\w]+).?\./).flatten.map{ |s| s.downcase }.uniq - ['raw_sql_'] end - end end -- cgit v1.2.3 From 36cc1f78eb17765f51e88085c30c39f40f3cb611 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Fri, 2 Dec 2011 09:19:13 -0800 Subject: revises some details in the previous explain patch --- activerecord/lib/active_record/relation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/relation.rb') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index e69e1aeaf8..1db26562b8 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -155,7 +155,7 @@ module ActiveRecord # Please see further details in the # {Active Record Query Interface guide}[http://edgeguides.rubyonrails.org/active_record_querying.html#running-explain]. def explain - results, sqls, binds = collecting_sqls_for_explain { exec_query } + _, sqls, binds = collecting_sqls_for_explain { exec_query } exec_explain(sqls, binds) end -- cgit v1.2.3 From 9a59475d4ab5ba0fe92fe8c4fe435597a2ae5720 Mon Sep 17 00:00:00 2001 From: Arun Agrawal Date: Fri, 2 Dec 2011 22:55:15 +0530 Subject: indentation fix warning --- activerecord/lib/active_record/relation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/relation.rb') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 1db26562b8..30cd8679fe 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -154,7 +154,7 @@ module ActiveRecord # # Please see further details in the # {Active Record Query Interface guide}[http://edgeguides.rubyonrails.org/active_record_querying.html#running-explain]. - def explain + def explain _, sqls, binds = collecting_sqls_for_explain { exec_query } exec_explain(sqls, binds) end -- cgit v1.2.3 From cfeac38e2b149d39edeb9add452fbd2ff96679b9 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Sun, 4 Dec 2011 11:29:56 -0800 Subject: =?UTF-8?q?implements=20a=20much=20faster=20auto=20EXPLAIN,=20clos?= =?UTF-8?q?es=20#3843=20[Jos=C3=A9=20Valim=20&=20Xavier=20Noria]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit vastly reduces the impact of auto explain logging when enabled, while keeping a negligible cost when disabled. The first implementation was based on the idea of subscribing to "sql.active_record" when needed, and unsubscribing once done. This is the idea behind AR::Relation#explain. Subscribe, collect, unsubscribe. But with the current implementation of notifications unsubscribing is costly, because it wipes an internal cache and that puts a penalty on the next event. So we are switching to an approach where a long-running subscriber is listening. Instead of collecting the queries with a closure in a dedicated subscriber, now we setup a thread local. If the feature is disabled by setting the threshold to nil, the subscriber will call a method that does nothing. That's totally cheap. --- activerecord/lib/active_record/relation.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'activerecord/lib/active_record/relation.rb') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 30cd8679fe..2897e354c5 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -155,8 +155,8 @@ module ActiveRecord # Please see further details in the # {Active Record Query Interface guide}[http://edgeguides.rubyonrails.org/active_record_querying.html#running-explain]. def explain - _, sqls, binds = collecting_sqls_for_explain { exec_query } - exec_explain(sqls, binds) + _, queries = collecting_queries_for_explain { exec_queries } + exec_explain(queries) end def to_a @@ -169,11 +169,11 @@ module ActiveRecord # threshold, and at the same time the sum of them all does. The user # should get a query plan logged in that case. logging_query_plan do - exec_query + exec_queries end end - def exec_query + def exec_queries return @records if loaded? default_scoped = with_default_scope @@ -204,7 +204,7 @@ module ActiveRecord @loaded = true @records end - private :exec_query + private :exec_queries def as_json(options = nil) #:nodoc: to_a.as_json(options) -- cgit v1.2.3 From de947c621d8ee18caca574451c722a6e30c4e6d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 15 Dec 2011 14:47:22 +0100 Subject: There isn't a column_hash. It was being invoked by method missing. --- activerecord/lib/active_record/relation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/relation.rb') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 2897e354c5..a127163e6c 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -15,7 +15,7 @@ module ActiveRecord # These are explicitly delegated to improve performance (avoids method_missing) delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to => :to_a delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key, - :connection, :column_hash, :auto_explain_threshold_in_seconds, :to => :klass + :connection, :columns_hash, :auto_explain_threshold_in_seconds, :to => :klass attr_reader :table, :klass, :loaded attr_accessor :extensions, :default_scoped -- cgit v1.2.3 From 1af2a1d0f569407a4b2b643c57a884920ec0fabc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 15 Dec 2011 20:01:56 +0100 Subject: Improve delegate list to avoid method missing. --- activerecord/lib/active_record/relation.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/relation.rb') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index a127163e6c..a1aa764991 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -13,7 +13,8 @@ module ActiveRecord include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain # These are explicitly delegated to improve performance (avoids method_missing) - delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to => :to_a + delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to_ary, :to => :to_a + delegate :ast, :engine, :to => :arel delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key, :connection, :columns_hash, :auto_explain_threshold_in_seconds, :to => :klass -- cgit v1.2.3 From 1e8b75181306ada87b1a4b05d1551348dd916f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 15 Dec 2011 20:26:33 +0100 Subject: Make with_scope public so we stop using send :bomb: --- activerecord/lib/active_record/relation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/relation.rb') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index a1aa764991..8aaab10b1e 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -251,7 +251,7 @@ module ActiveRecord # Please check unscoped if you want to remove all previous scopes (including # the default_scope) during the execution of a block. def scoping - @klass.send(:with_scope, self, :overwrite) { yield } + @klass.with_scope(self, :overwrite) { yield } end # Updates all records with details given if they match a set of conditions supplied, limits and order can -- cgit v1.2.3 From b17bc58c76c580911e18f2dd90a17aaae192a2a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 15 Dec 2011 20:46:30 +0100 Subject: Move delegation reponsibilities of Relation to a module. Also precompile method missing calls for rofscale. --- activerecord/lib/active_record/relation.rb | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) (limited to 'activerecord/lib/active_record/relation.rb') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 8aaab10b1e..0f78fe1ab7 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- require 'active_support/core_ext/object/blank' -require 'active_support/core_ext/module/delegation' module ActiveRecord # = Active Record Relation @@ -10,13 +9,7 @@ module ActiveRecord MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :bind] SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order, :uniq] - include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain - - # These are explicitly delegated to improve performance (avoids method_missing) - delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to_ary, :to => :to_a - delegate :ast, :engine, :to => :arel - delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key, - :connection, :columns_hash, :auto_explain_threshold_in_seconds, :to => :klass + include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain, Delegation attr_reader :table, :klass, :loaded attr_accessor :extensions, :default_scoped @@ -519,20 +512,6 @@ module ActiveRecord end end - protected - - def method_missing(method, *args, &block) - if Array.method_defined?(method) - to_a.send(method, *args, &block) - elsif @klass.respond_to?(method) - scoping { @klass.send(method, *args, &block) } - elsif arel.respond_to?(method) - arel.send(method, *args, &block) - else - super - end - end - private def references_eager_loaded_tables? -- cgit v1.2.3 From 8854bf29a3590771aa989eb7e4b79f31eba9d96d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Thu, 15 Dec 2011 20:59:05 +0100 Subject: Set up delegations also for to_a and arel branches. --- activerecord/lib/active_record/relation.rb | 7 ------- 1 file changed, 7 deletions(-) (limited to 'activerecord/lib/active_record/relation.rb') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 0f78fe1ab7..258c1959a0 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -132,13 +132,6 @@ module ActiveRecord first || new(attributes, options, &block) end - def respond_to?(method, include_private = false) - arel.respond_to?(method, include_private) || - Array.method_defined?(method) || - @klass.respond_to?(method, include_private) || - super - end - # Runs EXPLAIN on the query or queries triggered by this relation and # returns the result as a string. The string is formatted imitating the # ones printed by the database shell. -- cgit v1.2.3 From ceb33f84933639d3b61aac62e5e71fd087ab65ed Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Thu, 15 Dec 2011 20:07:41 +0000 Subject: Split out most of the AR::Base code into separate modules :cake: --- activerecord/lib/active_record/relation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/relation.rb') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 258c1959a0..ab2882516e 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -9,7 +9,7 @@ module ActiveRecord MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :bind] SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order, :uniq] - include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain, Delegation + include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain::ClassMethods, Delegation attr_reader :table, :klass, :loaded attr_accessor :extensions, :default_scoped -- cgit v1.2.3 From 0065f378262dc3f47880ce6211c7474bc7d11f0b Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Fri, 16 Dec 2011 12:12:05 -0800 Subject: AS::Concern is not really needed for AR::Explain --- activerecord/lib/active_record/relation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/relation.rb') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index ab2882516e..258c1959a0 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -9,7 +9,7 @@ module ActiveRecord MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :bind] SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order, :uniq] - include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain::ClassMethods, Delegation + include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain, Delegation attr_reader :table, :klass, :loaded attr_accessor :extensions, :default_scoped -- cgit v1.2.3 From b92a22e6eb94290bfc2f16743086caeb6e7f3fc5 Mon Sep 17 00:00:00 2001 From: Jo Liss Date: Wed, 28 Dec 2011 15:29:36 +0100 Subject: typo --- activerecord/lib/active_record/relation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/relation.rb') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 258c1959a0..80b85ce498 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -355,7 +355,7 @@ module ActiveRecord end end - # Destroy an object (or multiple objects) that has the given id, the object is instantiated first, + # Destroy an object (or multiple objects) that has the given id. The object is instantiated first, # therefore all callbacks and filters are fired off before the object is deleted. This method is # less efficient than ActiveRecord#delete but allows cleanup methods and other actions to be run. # -- cgit v1.2.3 From c99d507fccca2e9e4d12e49b4387e007c5481ae9 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Thu, 29 Dec 2011 14:26:38 +0000 Subject: Deprecate implicit eager loading. Closes #950. --- activerecord/lib/active_record/relation.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/relation.rb') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 258c1959a0..bbadca84be 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- require 'active_support/core_ext/object/blank' +require 'active_support/deprecation' module ActiveRecord # = Active Record Relation @@ -521,7 +522,18 @@ module ActiveRecord # always convert table names to downcase as in Oracle quoted table names are in uppercase joined_tables = joined_tables.flatten.compact.map { |t| t.downcase }.uniq - (tables_in_string(to_sql) - joined_tables).any? + referenced_tables = (tables_in_string(to_sql) - joined_tables) + if referenced_tables.any? + ActiveSupport::Deprecation.warn( + "Your query appears to reference tables (#{referenced_tables.join(', ')}) that are not " \ + "explicitly joined. This implicit joining is deprecated, so you must explicitly " \ + "reference the tables. For example, instead of Author.includes(:posts).where(\"posts.name = 'foo'\"), " \ + "you should write Author.eager_load(:posts).where(\"posts.name = 'foo'\")." + ) + true + else + false + end end def tables_in_string(string) -- cgit v1.2.3