aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Kemper <jeremy@bitsweat.net>2006-08-29 17:06:27 +0000
committerJeremy Kemper <jeremy@bitsweat.net>2006-08-29 17:06:27 +0000
commit3704088ebde5ef074d186bff0d380858a9a01055 (patch)
treecae788b86554be381aff084f7b3da48a4fc428b4
parent92f1e26a1c9f48ac575414976012d6dfa127bdac (diff)
downloadrails-3704088ebde5ef074d186bff0d380858a9a01055.tar.gz
rails-3704088ebde5ef074d186bff0d380858a9a01055.tar.bz2
rails-3704088ebde5ef074d186bff0d380858a9a01055.zip
has_one supports the :dependent => :delete option which skips the typical callback chain and deletes the associated object directly from the database. Closes #5927.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@4848 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
-rw-r--r--activerecord/CHANGELOG2
-rwxr-xr-xactiverecord/lib/active_record/associations.rb9
-rwxr-xr-xactiverecord/test/associations_test.rb18
-rw-r--r--activerecord/test/calculations_test.rb16
-rw-r--r--activerecord/test/finder_test.rb4
-rw-r--r--activerecord/test/fixtures/accounts.yml7
-rw-r--r--activerecord/test/fixtures/companies.yml7
-rwxr-xr-xactiverecord/test/fixtures/company.rb15
-rwxr-xr-xactiverecord/test/inheritance_test.rb2
9 files changed, 64 insertions, 16 deletions
diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG
index f6cf49f35a..5846d11b58 100644
--- a/activerecord/CHANGELOG
+++ b/activerecord/CHANGELOG
@@ -1,5 +1,7 @@
*SVN*
+* has_one supports the :dependent => :delete option which skips the typical callback chain and deletes the associated object directly from the database. #5927 [Chris Mear, Jonathan Viney]
+
* Nested subclasses are not prefixed with the parent class' table_name since they should always use the base class' table_name. #5911 [Jonathan Viney]
* SQLServer: work around bug where some unambiguous date formats are not correctly identified if the session language is set to german. #5894 [Tom Ward, kruth@bfpi]
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 8f45ce5428..65db5f9b23 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -570,8 +570,9 @@ module ActiveRecord
# sql fragment, such as "rank = 5".
# * <tt>:order</tt> - specify the order from which the associated object will be picked at the top. Specified as
# an "ORDER BY" sql fragment, such as "last_name, first_name DESC"
- # * <tt>:dependent</tt> - if set to :destroy (or true) all the associated objects are destroyed when this object is. Also,
- # association is assigned.
+ # * <tt>:dependent</tt> - if set to :destroy (or true) the associated object is destroyed when this object is. If set to
+ # :delete the associated object is deleted *without* calling its destroy method. If set to :nullify the associated
+ # object's foreign key is set to NULL. Also, association is assigned.
# * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name
# of this class in lower-case and "_id" suffixed. So a +Person+ class that makes a has_one association will use "person_id"
# as the default foreign_key.
@@ -1020,12 +1021,14 @@ module ActiveRecord
case reflection.options[:dependent]
when :destroy, true
module_eval "before_destroy '#{reflection.name}.destroy unless #{reflection.name}.nil?'"
+ when :delete
+ module_eval "before_destroy '#{reflection.class_name}.delete(#{reflection.name}.id) unless #{reflection.name}.nil?'"
when :nullify
module_eval "before_destroy '#{reflection.name}.update_attribute(\"#{reflection.primary_key_name}\", nil)'"
when nil, false
# pass
else
- raise ArgumentError, "The :dependent option expects either :destroy or :nullify."
+ raise ArgumentError, "The :dependent option expects either :destroy, :delete or :nullify."
end
end
diff --git a/activerecord/test/associations_test.rb b/activerecord/test/associations_test.rb
index 6e93b7430c..100b30f126 100755
--- a/activerecord/test/associations_test.rb
+++ b/activerecord/test/associations_test.rb
@@ -91,6 +91,10 @@ end
class HasOneAssociationsTest < Test::Unit::TestCase
fixtures :accounts, :companies, :developers, :projects, :developers_projects
+ def setup
+ Account.destroyed_account_ids.clear
+ end
+
def test_has_one
assert_equal companies(:first_firm).account, Account.find(1)
assert_equal Account.find(1).credit_limit, companies(:first_firm).account.credit_limit
@@ -168,8 +172,22 @@ class HasOneAssociationsTest < Test::Unit::TestCase
num_accounts = Account.count
firm = Firm.find(1)
assert !firm.account.nil?
+ account_id = firm.account.id
+ assert_equal [], Account.destroyed_account_ids[firm.id]
firm.destroy
assert_equal num_accounts - 1, Account.count
+ assert_equal [account_id], Account.destroyed_account_ids[firm.id]
+ end
+
+ def test_exclusive_dependence
+ num_accounts = Account.count
+ firm = ExclusivelyDependentFirm.find(9)
+ assert !firm.account.nil?
+ account_id = firm.account.id
+ assert_equal [], Account.destroyed_account_ids[firm.id]
+ firm.destroy
+ assert_equal num_accounts - 1, Account.count
+ assert_equal [], Account.destroyed_account_ids[firm.id]
end
def test_succesful_build_association
diff --git a/activerecord/test/calculations_test.rb b/activerecord/test/calculations_test.rb
index 9a0d0434a5..397b7a9026 100644
--- a/activerecord/test/calculations_test.rb
+++ b/activerecord/test/calculations_test.rb
@@ -8,7 +8,7 @@ class CalculationsTest < Test::Unit::TestCase
fixtures :companies, :accounts, :topics
def test_should_sum_field
- assert_equal 265, Account.sum(:credit_limit)
+ assert_equal 318, Account.sum(:credit_limit)
end
def test_should_average_field
@@ -49,13 +49,13 @@ class CalculationsTest < Test::Unit::TestCase
def test_should_order_by_grouped_field
c = Account.sum(:credit_limit, :group => :firm_id, :order => "firm_id")
- assert_equal [1, 2, 6], c.keys.compact
+ assert_equal [1, 2, 6, 9], c.keys.compact
end
def test_should_order_by_calculation
c = Account.sum(:credit_limit, :group => :firm_id, :order => "sum_credit_limit desc, firm_id")
- assert_equal [105, 60, 50, 50], c.keys.collect { |k| c[k] }
- assert_equal [6, 2, 1], c.keys.compact
+ assert_equal [105, 60, 53, 50, 50], c.keys.collect { |k| c[k] }
+ assert_equal [6, 2, 9, 1], c.keys.compact
end
def test_should_limit_calculation
@@ -114,8 +114,8 @@ class CalculationsTest < Test::Unit::TestCase
end
def test_should_calculate_with_invalid_field
- assert_equal 5, Account.calculate(:count, '*')
- assert_equal 5, Account.calculate(:count, :all)
+ assert_equal 6, Account.calculate(:count, '*')
+ assert_equal 6, Account.calculate(:count, :all)
end
def test_should_calculate_grouped_with_invalid_field
@@ -193,7 +193,7 @@ class CalculationsTest < Test::Unit::TestCase
end
def test_should_count_selected_field_with_include
- assert_equal 5, Account.count(:distinct => true, :include => :firm)
- assert_equal 3, Account.count(:distinct => true, :include => :firm, :select => :credit_limit)
+ assert_equal 6, Account.count(:distinct => true, :include => :firm)
+ assert_equal 4, Account.count(:distinct => true, :include => :firm, :select => :credit_limit)
end
end
diff --git a/activerecord/test/finder_test.rb b/activerecord/test/finder_test.rb
index 4a79f129c0..bd72348916 100644
--- a/activerecord/test/finder_test.rb
+++ b/activerecord/test/finder_test.rb
@@ -454,8 +454,8 @@ class FinderTest < Test::Unit::TestCase
end
def test_select_values
- assert_equal ["1","2","3","4","5","6","7","8"], Company.connection.select_values("SELECT id FROM companies ORDER BY id").map! { |i| i.to_s }
- assert_equal ["37signals","Summit","Microsoft", "Flamboyant Software", "Ex Nihilo", "RailsCore", "Leetsoft", "Jadedpixel"], Company.connection.select_values("SELECT name FROM companies ORDER BY id")
+ assert_equal ["1","2","3","4","5","6","7","8","9"], Company.connection.select_values("SELECT id FROM companies ORDER BY id").map! { |i| i.to_s }
+ assert_equal ["37signals","Summit","Microsoft", "Flamboyant Software", "Ex Nihilo", "RailsCore", "Leetsoft", "Jadedpixel", "Odegy"], Company.connection.select_values("SELECT name FROM companies ORDER BY id")
end
protected
diff --git a/activerecord/test/fixtures/accounts.yml b/activerecord/test/fixtures/accounts.yml
index a3d6742d79..b2d0191900 100644
--- a/activerecord/test/fixtures/accounts.yml
+++ b/activerecord/test/fixtures/accounts.yml
@@ -20,4 +20,9 @@ last_account:
rails_core_account_2:
id: 5
firm_id: 6
- credit_limit: 55 \ No newline at end of file
+ credit_limit: 55
+
+odegy_account:
+ id: 6
+ firm_id: 9
+ credit_limit: 53
diff --git a/activerecord/test/fixtures/companies.yml b/activerecord/test/fixtures/companies.yml
index f2e638d382..c61128c09b 100644
--- a/activerecord/test/fixtures/companies.yml
+++ b/activerecord/test/fixtures/companies.yml
@@ -47,4 +47,9 @@ leetsoft:
jadedpixel:
id: 8
name: Jadedpixel
- client_of: 6 \ No newline at end of file
+ client_of: 6
+
+odegy:
+ id: 9
+ name: Odegy
+ type: ExclusivelyDependentFirm
diff --git a/activerecord/test/fixtures/company.rb b/activerecord/test/fixtures/company.rb
index 250deebb21..a55632360f 100755
--- a/activerecord/test/fixtures/company.rb
+++ b/activerecord/test/fixtures/company.rb
@@ -42,6 +42,9 @@ class DependentFirm < Company
has_many :companies, :foreign_key => 'client_of', :order => "id", :dependent => :nullify
end
+class ExclusivelyDependentFirm < Company
+ has_one :account, :foreign_key => "firm_id", :dependent => :delete
+end
class Client < Company
belongs_to :firm, :foreign_key => "client_of"
@@ -83,6 +86,18 @@ end
class Account < ActiveRecord::Base
belongs_to :firm
+ def self.destroyed_account_ids
+ @destroyed_account_ids ||= Hash.new { |h,k| h[k] = [] }
+ end
+
+ before_destroy do |account|
+ if account.firm
+ Account.destroyed_account_ids[account.firm.id] << account.id
+ end
+ true
+ end
+
+
protected
def validate
errors.add_on_empty "credit_limit"
diff --git a/activerecord/test/inheritance_test.rb b/activerecord/test/inheritance_test.rb
index db10e1f048..65f5d70a1f 100755
--- a/activerecord/test/inheritance_test.rb
+++ b/activerecord/test/inheritance_test.rb
@@ -58,7 +58,7 @@ class InheritanceTest < Test::Unit::TestCase
end
def test_inheritance_condition
- assert_equal 8, Company.count
+ assert_equal 9, Company.count
assert_equal 2, Firm.count
assert_equal 3, Client.count
end