diff options
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/CHANGELOG.md | 11 | ||||
-rw-r--r-- | activerecord/lib/active_record/base.rb | 1 | ||||
-rw-r--r-- | activerecord/lib/active_record/railtie.rb | 6 | ||||
-rw-r--r-- | activerecord/lib/active_record/relation/calculations.rb | 4 | ||||
-rw-r--r-- | activerecord/lib/active_record/relation/delegation.rb | 24 | ||||
-rw-r--r-- | activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb | 17 | ||||
-rw-r--r-- | activerecord/test/cases/associations/has_many_associations_test.rb | 7 | ||||
-rw-r--r-- | activerecord/test/cases/associations/has_many_through_associations_test.rb | 19 | ||||
-rw-r--r-- | activerecord/test/cases/base_test.rb | 7 | ||||
-rw-r--r-- | activerecord/test/cases/calculations_test.rb | 6 | ||||
-rw-r--r-- | activerecord/test/cases/finder_test.rb | 5 | ||||
-rw-r--r-- | activerecord/test/models/topic.rb | 6 |
12 files changed, 87 insertions, 26 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index dee398177c..580a580ba5 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,7 +1,16 @@ ## Rails 4.0.0 (unreleased) ## +* `#pluck` can be used on a relation with `select` clause + Fix #7551 + + Example: + + Topic.select([:approved, :id]).order(:id).pluck(:id) + + *Yves Senn* + * Do not create useless database transaction when building `has_one` association. - + Example: User.has_one :profile diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index a694a292fe..83047c1845 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -332,7 +332,6 @@ module ActiveRecord #:nodoc: extend Translation extend DynamicMatchers extend Explain - extend ConnectionHandling include Persistence include ReadonlyAttributes diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index 4ba35fe513..5464ca6066 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -149,8 +149,10 @@ module ActiveRecord ActiveSupport.on_load(:active_record) do ActionDispatch::Reloader.send(hook) do - ActiveRecord::Base.clear_reloadable_connections! - ActiveRecord::Base.clear_cache! + if ActiveRecord::Base.connected? + ActiveRecord::Base.clear_reloadable_connections! + ActiveRecord::Base.clear_cache! + end end end end diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index a7d2f4bd24..df27318678 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -165,7 +165,9 @@ module ActiveRecord if has_include?(column_names.first) construct_relation_for_association_calculations.pluck(*column_names) else - result = klass.connection.select_all(select(column_names).arel, nil, bind_values) + relation = spawn + relation.select_values = column_names + result = klass.connection.select_all(relation.arel, nil, bind_values) columns = result.columns.map do |key| klass.column_types.fetch(key) { result.column_types.fetch(key) { diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb index ab8b36c8ab..dbfa92bbbd 100644 --- a/activerecord/lib/active_record/relation/delegation.rb +++ b/activerecord/lib/active_record/relation/delegation.rb @@ -1,3 +1,4 @@ +require 'thread' module ActiveRecord module Delegation # :nodoc: @@ -6,6 +7,8 @@ module ActiveRecord delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key, :connection, :columns_hash, :auto_explain_threshold_in_seconds, :to => :klass + @@delegation_mutex = Mutex.new + def self.delegate_to_scoped_klass(method) if method.to_s =~ /\A[a-zA-Z_]\w*[!?]?\z/ module_eval <<-RUBY, __FILE__, __LINE__ + 1 @@ -32,13 +35,28 @@ module ActiveRecord def method_missing(method, *args, &block) if @klass.respond_to?(method) - ::ActiveRecord::Delegation.delegate_to_scoped_klass(method) + @@delegation_mutex.synchronize do + unless ::ActiveRecord::Delegation.method_defined?(method) + ::ActiveRecord::Delegation.delegate_to_scoped_klass(method) + end + end + scoping { @klass.send(method, *args, &block) } elsif Array.method_defined?(method) - ::ActiveRecord::Delegation.delegate method, :to => :to_a + @@delegation_mutex.synchronize do + unless ::ActiveRecord::Delegation.method_defined?(method) + ::ActiveRecord::Delegation.delegate method, :to => :to_a + end + end + to_a.send(method, *args, &block) elsif arel.respond_to?(method) - ::ActiveRecord::Delegation.delegate method, :to => :arel + @@delegation_mutex.synchronize do + unless ::ActiveRecord::Delegation.method_defined?(method) + ::ActiveRecord::Delegation.delegate method, :to => :arel + end + end + arel.send(method, *args, &block) else super diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb index 42f5b69d4e..1b1b479f1a 100644 --- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb @@ -799,12 +799,6 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase assert_equal 1, developer.projects.count end - def test_counting_should_not_fire_sql_if_parent_is_unsaved - assert_no_queries do - assert_equal 0, Developer.new.projects.count - end - end - unless current_adapter?(:PostgreSQLAdapter) def test_count_with_finder_sql assert_equal 3, projects(:active_record).developers_with_finder_sql.count @@ -862,4 +856,15 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase def klass.name; 'Foo'; end assert_deprecated { klass.has_and_belongs_to_many :posts, :delete_sql => 'lol' } end + + test "has and belongs to many associations on new records use null relations" do + projects = Developer.new.projects + assert_no_queries do + assert_equal [], projects + assert_equal [], projects.where(title: 'omg') + assert_equal [], projects.pluck(:title) + assert_equal 0, projects.count + end + end + end diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 45b0a76f5a..b1066fb24c 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -262,12 +262,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal firm.limited_clients.length, firm.limited_clients.count end - def test_counting_should_not_fire_sql_if_parent_is_unsaved - assert_no_queries do - assert_equal 0, Person.new.readers.count - end - end - def test_finding assert_equal 2, Firm.all.merge!(:order => "id").first.clients.length end @@ -1665,6 +1659,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal [], post.comments.where(body: 'omg') assert_equal [], post.comments.pluck(:body) assert_equal 0, post.comments.sum(:id) + assert_equal 0, post.comments.count end end end diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index b2a5d9d6f7..8e52ce1d91 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -766,12 +766,6 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase assert_equal 1, authors(:mary).categories.general.count end - def test_counting_should_not_fire_sql_if_parent_is_unsaved - assert_no_queries do - assert_equal 0, Person.new.posts.count - end - end - def test_has_many_through_belongs_to_should_update_when_the_through_foreign_key_changes post = posts(:eager_other) @@ -876,4 +870,17 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase post = tags(:general).tagged_posts.create! :title => "foo", :body => "bar" assert_equal [tags(:general)], post.reload.tags end + + test "has many through associations on new records use null relations" do + person = Person.new + + assert_no_queries do + assert_equal [], person.posts + assert_equal [], person.posts.where(body: 'omg') + assert_equal [], person.posts.pluck(:body) + assert_equal 0, person.posts.sum(:tags_count) + assert_equal 0, person.posts.count + end + end + end diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 203e44857a..c02d8f7760 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -1442,6 +1442,13 @@ class BasicsTest < ActiveRecord::TestCase assert_match(/\/#{dev.id}$/, dev.cache_key) end + def test_cache_key_format_is_precise_enough + dev = Developer.first + key = dev.cache_key + dev.touch + assert_not_equal key, dev.cache_key + end + def test_uniq_delegates_to_scoped scope = stub Bird.stubs(:all).returns(mock(:uniq => scope)) diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index abbf2a765e..65d28ea028 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -580,4 +580,10 @@ class CalculationsTest < ActiveRecord::TestCase assert_equal ["Over There"], Possession.pluck(:where) end + + def test_pluck_replaces_select_clause + taks_relation = Topic.select(:approved, :id).order(:id) + assert_equal [1,2,3,4], taks_relation.pluck(:id) + assert_equal [false, true, true, true], taks_relation.pluck(:approved) + end end diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index d44ac21b05..7db7953313 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -610,6 +610,11 @@ class FinderTest < ActiveRecord::TestCase assert_nil Topic.find_by_heading("The First Topic!") end + def test_find_by_one_attribute_bang_with_blank_defined + blank_topic = BlankTopic.create(title: "The Blank One") + assert_equal blank_topic, BlankTopic.find_by_title!("The Blank One") + end + def test_find_by_one_attribute_with_conditions assert_equal accounts(:rails_core_account), Account.where('firm_id = ?', 6).find_by_credit_limit(50) end diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb index ab31d85e46..f7f4cebc5a 100644 --- a/activerecord/test/models/topic.rb +++ b/activerecord/test/models/topic.rb @@ -107,6 +107,12 @@ class ImportantTopic < Topic serialize :important, Hash end +class BlankTopic < Topic + def blank? + true + end +end + module Web class Topic < ActiveRecord::Base has_many :replies, :dependent => :destroy, :foreign_key => "parent_id", :class_name => 'Web::Reply' |