diff options
20 files changed, 72 insertions, 18 deletions
diff --git a/actionpack/lib/action_controller/metal/hide_actions.rb b/actionpack/lib/action_controller/metal/hide_actions.rb index 2aa6b7adaf..af36ffa240 100644 --- a/actionpack/lib/action_controller/metal/hide_actions.rb +++ b/actionpack/lib/action_controller/metal/hide_actions.rb @@ -27,7 +27,7 @@ module ActionController end def visible_action?(action_name) - action_methods.include?(action_name) + not hidden_actions.include?(action_name) end # Overrides AbstractController::Base#action_methods to remove any methods diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb index 9b42e7631f..d4f18d55a6 100644 --- a/actionpack/test/controller/base_test.rb +++ b/actionpack/test/controller/base_test.rb @@ -68,6 +68,12 @@ class RecordIdentifierWithoutDeprecationController < ActionController::Base include ActionView::RecordIdentifier end +class ActionMissingController < ActionController::Base + def action_missing(action) + render :text => "Response for #{action}" + end +end + class ControllerClassTests < ActiveSupport::TestCase def test_controller_path @@ -186,6 +192,12 @@ class PerformActionTest < ActionController::TestCase assert_raise(AbstractController::ActionNotFound) { get :hidden_action } assert_raise(AbstractController::ActionNotFound) { get :another_hidden_action } end + + def test_action_missing_should_work + use_controller ActionMissingController + get :arbitrary_action + assert_equal "Response for arbitrary_action", @response.body + end end class UrlOptionsTest < ActionController::TestCase diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 3e368407f2..771f1333f0 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,10 @@ ## Rails 4.0.0 (unreleased) ## +* Models with multiple counter cache associations now update correctly on destroy. + See #7706. + + *Ian Young* + * If inverse_of is true on an association, then when one calls +find()+ on the association, ActiveRecord will first look through the in-memory objects in the association for a particular id. Then, it will go to the DB if it diff --git a/activerecord/lib/active_record/associations/builder/belongs_to.rb b/activerecord/lib/active_record/associations/builder/belongs_to.rb index fbcb21118d..9ac561b997 100644 --- a/activerecord/lib/active_record/associations/builder/belongs_to.rb +++ b/activerecord/lib/active_record/associations/builder/belongs_to.rb @@ -31,7 +31,7 @@ module ActiveRecord::Associations::Builder end def belongs_to_counter_cache_before_destroy_for_#{name} - unless marked_for_destruction? + unless destroyed_by_association && destroyed_by_association.foreign_key.to_sym == #{foreign_key.to_sym.inspect} record = #{name} record.class.decrement_counter(:#{cache_column}, record.id) unless record.nil? end diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb index b7b4d7e3ae..29fae809da 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -22,7 +22,7 @@ module ActiveRecord else if options[:dependent] == :destroy # No point in executing the counter update since we're going to destroy the parent anyway - load_target.each(&:mark_for_destruction) + load_target.each { |t| t.destroyed_by_association = reflection } destroy_all else delete_all diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index 55542262b0..0df3e57947 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -212,6 +212,7 @@ module ActiveRecord # Reloads the attributes of the object as usual and clears <tt>marked_for_destruction</tt> flag. def reload(options = nil) @marked_for_destruction = false + @destroyed_by_association = nil super end @@ -231,6 +232,19 @@ module ActiveRecord @marked_for_destruction end + # Records the association that is being destroyed and destroying this + # record in the process. + def destroyed_by_association=(reflection) + @destroyed_by_association = reflection + end + + # Returns the association for the parent being destroyed. + # + # Used to avoid updating the counter cache unnecessarily. + def destroyed_by_association + @destroyed_by_association + end + # Returns whether or not this record has been changed in any way (including whether # any of its nested autosave associations are likewise changed) def changed_for_autosave? diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb index 9137504d15..bf2f945448 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -238,7 +238,7 @@ module ActiveRecord @checkout_timeout = spec.config[:checkout_timeout] || 5 @dead_connection_timeout = spec.config[:dead_connection_timeout] || 5 - @reaper = Reaper.new(self, spec.config[:reaping_frequency] || 10) + @reaper = Reaper.new self, spec.config[:reaping_frequency] @reaper.run # default max pool size to 5 @@ -406,7 +406,9 @@ module ActiveRecord synchronize do stale = Time.now - @dead_connection_timeout connections.dup.each do |conn| - remove conn if conn.in_use? && stale > conn.last_use && !conn.active? + if conn.in_use? && stale > conn.last_use && !conn.active? + remove conn + end end end end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index dfa4c3967a..940de7e4f6 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -519,8 +519,7 @@ module ActiveRecord # Is this connection alive and ready for queries? def active? - @connection.query 'SELECT 1' - true + @connection.connect_poll != PG::PGRES_POLLING_FAILED rescue PGError false end diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index aa56219755..968dad5844 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -427,6 +427,7 @@ module ActiveRecord @readonly = false @destroyed = false @marked_for_destruction = false + @destroyed_by_association = nil @new_record = true @txn = nil @_start_transaction_state = {} diff --git a/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb index 21fb111c91..a5a22bc30b 100644 --- a/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb @@ -90,7 +90,7 @@ protected end def table_indexes_without_name(table) - @connection.indexes('comments_with_index').delete(:name) + @connection.indexes(table).delete(:name) end def row_count(table) diff --git a/activerecord/test/cases/counter_cache_test.rb b/activerecord/test/cases/counter_cache_test.rb index 7d06fb5093..5379a70034 100644 --- a/activerecord/test/cases/counter_cache_test.rb +++ b/activerecord/test/cases/counter_cache_test.rb @@ -115,6 +115,14 @@ class CounterCacheTest < ActiveRecord::TestCase end end + test "update other counters on parent destroy" do + david, joanna = dog_lovers(:david, :joanna) + + assert_difference 'joanna.reload.dogs_count', -1 do + david.destroy + end + end + test "reset the right counter if two have the same foreign key" do michael = people(:michael) assert_nothing_raised(ActiveRecord::StatementInvalid) do diff --git a/activerecord/test/fixtures/dog_lovers.yml b/activerecord/test/fixtures/dog_lovers.yml index d3e5e4a1aa..3f4c6c9e4c 100644 --- a/activerecord/test/fixtures/dog_lovers.yml +++ b/activerecord/test/fixtures/dog_lovers.yml @@ -2,3 +2,6 @@ david: id: 1 bred_dogs_count: 0 trained_dogs_count: 1 +joanna: + id: 2 + dogs_count: 1 diff --git a/activerecord/test/fixtures/dogs.yml b/activerecord/test/fixtures/dogs.yml index 16d19be2c5..b5eb2c7b74 100644 --- a/activerecord/test/fixtures/dogs.yml +++ b/activerecord/test/fixtures/dogs.yml @@ -1,3 +1,4 @@ sophie: id: 1 trainer_id: 1 + dog_lover_id: 2 diff --git a/activerecord/test/models/dog.rb b/activerecord/test/models/dog.rb index 72b7d33a86..b02b8447b8 100644 --- a/activerecord/test/models/dog.rb +++ b/activerecord/test/models/dog.rb @@ -1,4 +1,5 @@ class Dog < ActiveRecord::Base - belongs_to :breeder, :class_name => "DogLover", :counter_cache => :bred_dogs_count - belongs_to :trainer, :class_name => "DogLover", :counter_cache => :trained_dogs_count + belongs_to :breeder, class_name: "DogLover", counter_cache: :bred_dogs_count + belongs_to :trainer, class_name: "DogLover", counter_cache: :trained_dogs_count + belongs_to :doglover, foreign_key: :dog_lover_id, class_name: "DogLover", counter_cache: true end diff --git a/activerecord/test/models/dog_lover.rb b/activerecord/test/models/dog_lover.rb index a33dc575c5..2c5be94aea 100644 --- a/activerecord/test/models/dog_lover.rb +++ b/activerecord/test/models/dog_lover.rb @@ -1,4 +1,5 @@ class DogLover < ActiveRecord::Base - has_many :trained_dogs, :class_name => "Dog", :foreign_key => :trainer_id - has_many :bred_dogs, :class_name => "Dog", :foreign_key => :breeder_id + has_many :trained_dogs, class_name: "Dog", foreign_key: :trainer_id, dependent: :destroy + has_many :bred_dogs, class_name: "Dog", foreign_key: :breeder_id + has_many :dogs end diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index a952738e84..8fd4898ad6 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -230,14 +230,16 @@ ActiveRecord::Schema.define do t.integer :access_level, :default => 1 end - create_table :dog_lovers, :force => true do |t| - t.integer :trained_dogs_count, :default => 0 - t.integer :bred_dogs_count, :default => 0 + create_table :dog_lovers, force: true do |t| + t.integer :trained_dogs_count, default: 0 + t.integer :bred_dogs_count, default: 0 + t.integer :dogs_count, default: 0 end create_table :dogs, :force => true do |t| t.integer :trainer_id t.integer :breeder_id + t.integer :dog_lover_id end create_table :edges, :force => true, :id => false do |t| diff --git a/ci/travis.rb b/ci/travis.rb index b03ac4fe35..9029c3f41c 100755 --- a/ci/travis.rb +++ b/ci/travis.rb @@ -109,7 +109,7 @@ end # puts " #{`uname -a`}" # puts " #{`ruby -v`}" # puts " #{`mysql --version`}" -# # puts " #{`pg_config --version`}" +# puts " #{`pg_config --version`}" # puts " SQLite3: #{`sqlite3 -version`}" # `gem env`.each_line {|line| print " #{line}"} # puts " Bundled gems:" @@ -117,7 +117,7 @@ end # puts " Local gems:" # `gem list`.each_line {|line| print " #{line}"} -failures = results.select { |key, value| value == false } +failures = results.select { |key, value| !value } if failures.empty? puts diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 60a823de15..3a81e0861b 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,5 +1,9 @@ ## Rails 4.0.0 (unreleased) ## +* Don't generate a scaffold.css when --no-assets is specified + + *Kevin Glowacz* + * Add support for generate scaffold password:digest * adds password_digest attribute to the migration diff --git a/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb b/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb index 36589d65e2..2a0522e81c 100644 --- a/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb +++ b/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb @@ -10,6 +10,7 @@ module Rails class_option :stylesheet_engine, desc: "Engine for Stylesheets" def handle_skip + @options = @options.merge(stylesheets: false) unless options[:assets] @options = @options.merge(stylesheet_engine: false) unless options[:stylesheets] end diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb index b29d1e018e..25f299118c 100644 --- a/railties/test/generators/scaffold_generator_test.rb +++ b/railties/test/generators/scaffold_generator_test.rb @@ -241,7 +241,7 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase def test_scaffold_generator_no_assets run_generator [ "posts", "--no-assets" ] - assert_file "app/assets/stylesheets/scaffold.css" + assert_no_file "app/assets/stylesheets/scaffold.css" assert_no_file "app/assets/javascripts/posts.js" assert_no_file "app/assets/stylesheets/posts.css" end |