Permalink
Browse files

Merge remote branch 'jonleighton/deprecate_habtm_attributes-3-0-stabl…

…e' into 3-0-stable

* jonleighton/deprecate_habtm_attributes-3-0-stable:
  Added deprecation warning for has_and_belongs_to_many associations where the join table has additional attributes other than the keys. Access to these attributes is removed in 3.1. Please use has_many :through instead.
  • Loading branch information...
2 parents 683cb50 + bcbff10 commit f420c2ece8015c15c75f25d3f37347e8f51747b4 @tenderlove tenderlove committed Jan 24, 2011
View
@@ -1,3 +1,9 @@
+*Rails 3.0.4 (unreleased)*
+
+* Added deprecation warning for has_and_belongs_to_many associations where the join table has
+ additional attributes other than the keys. Access to these attributes is removed in 3.1.
+ Please use has_many :through instead. [Jon Leighton]
+
*Rails 3.0.3 (November 16, 2010)*
* Support find by class like this: Post.where(:name => Post)
@@ -1,7 +1,16 @@
+require 'active_support/deprecation'
+
module ActiveRecord
# = Active Record Has And Belongs To Many Association
module Associations
class HasAndBelongsToManyAssociation < AssociationCollection #:nodoc:
+ def initialize(owner, reflection)
+ super
+ if columns.size > 2
+ ActiveSupport::Deprecation.warn "Having additional attributes on the join table of a has_and_belongs_to_many association is deprecated and will be removed in Rails 3.1. Please use a has_many :through association instead."
+ end
+ end
+
def create(attributes = {})
create_record(attributes) { |record| insert_record(record) }
end
@@ -12,6 +12,14 @@ def setup
@thinking = posts(:thinking)
@authorless = posts(:authorless)
assert @david.post_log.empty?
+
+ # Silence deprecation warnings to avoid the warning about attributes on the join table, which
+ # would otherwise appear in most of these tests.
+ ActiveSupport::Deprecation.silenced = true
+ end
+
+ def teardown
+ ActiveSupport::Deprecation.silenced = false
end
def test_adding_macro_callbacks
@@ -773,11 +773,15 @@ def test_load_with_sti_sharing_association
end
def test_conditions_on_join_table_with_include_and_limit
- assert_equal 3, Developer.find(:all, :include => 'projects', :conditions => 'developers_projects.access_level = 1', :limit => 5).size
+ ActiveSupport::Deprecation.silence do
+ assert_equal 3, Developer.find(:all, :include => 'projects', :conditions => 'developers_projects.access_level = 1', :limit => 5).size
+ end
end
def test_order_on_join_table_with_include_and_limit
- assert_equal 5, Developer.find(:all, :include => 'projects', :order => 'developers_projects.joined_on DESC', :limit => 5).size
+ ActiveSupport::Deprecation.silence do
+ assert_equal 5, Developer.find(:all, :include => 'projects', :order => 'developers_projects.joined_on DESC', :limit => 5).size
+ end
end
def test_eager_loading_with_order_on_joined_table_preloads
@@ -8,6 +8,16 @@
class AssociationsExtensionsTest < ActiveRecord::TestCase
fixtures :projects, :developers, :developers_projects, :comments, :posts
+ # Silence deprecation warnings to avoid the warning about attributes on the join table, which
+ # would otherwise appear in most of these tests.
+ def setup
+ ActiveSupport::Deprecation.silenced = true
+ end
+
+ def teardown
+ ActiveSupport::Deprecation.silenced = false
+ end
+
def test_extension_on_has_many
assert_equal comments(:more_greetings), posts(:welcome).comments.find_most_recent
end
@@ -79,6 +79,16 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
fixtures :accounts, :companies, :categories, :posts, :categories_posts, :developers, :projects, :developers_projects,
:parrots, :pirates, :treasures, :price_estimates, :tags, :taggings
+ # Silence deprecation warnings to avoid the warning about attributes on the join table, which
+ # would otherwise appear in most of these tests.
+ def setup
+ ActiveSupport::Deprecation.silenced = true
+ end
+
+ def teardown
+ ActiveSupport::Deprecation.silenced = false
+ end
+
def setup_data_for_habtm_case
ActiveRecord::Base.connection.execute('delete from countries_treaties')
@@ -865,3 +875,12 @@ def test_include_method_in_has_and_belongs_to_many_association_should_return_tru
assert project.developers.include?(developer)
end
end
+
+class HasAndBelongsToManyAssociationsDeprecationTest < ActiveRecord::TestCase
+ fixtures :developers
+
+ def test_attributes_on_join_table_deprecated
+ jamis = developers(:jamis)
+ assert_deprecated { jamis.projects }
+ end
+end
@@ -430,7 +430,9 @@ def test_create_with_bang_on_has_many_raises_when_record_not_saved
def test_create_with_bang_on_habtm_when_parent_is_new_raises
assert_raise(ActiveRecord::RecordNotSaved) do
- Developer.new("name" => "Aredridel").projects.create!
+ ActiveSupport::Deprecation.silence do
+ Developer.new("name" => "Aredridel").projects.create!
+ end
end
end
@@ -776,14 +778,18 @@ def test_deleting_a_item_which_is_not_in_the_collection
def test_deleting_type_mismatch
david = Developer.find(1)
- david.projects.reload
- assert_raise(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(1) }
+ ActiveSupport::Deprecation.silence do
+ david.projects.reload
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(1) }
+ end
end
def test_deleting_self_type_mismatch
david = Developer.find(1)
- david.projects.reload
- assert_raise(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(Project.find(1).developers) }
+ ActiveSupport::Deprecation.silence do
+ david.projects.reload
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(Project.find(1).developers) }
+ end
end
def test_destroying
@@ -188,9 +188,11 @@ def test_push_does_not_lose_additions_to_new_record
def test_save_on_parent_does_not_load_target
david = developers(:david)
- assert !david.projects.loaded?
- david.update_attribute(:created_at, Time.now)
- assert !david.projects.loaded?
+ ActiveSupport::Deprecation.silence do
+ assert !david.projects.loaded?
+ david.update_attribute(:created_at, Time.now)
+ assert !david.projects.loaded?
+ end
end
def test_inspect_does_not_reload_a_not_yet_loaded_target
@@ -229,7 +231,9 @@ def test_failed_reset_returns_nil
def test_reload_returns_assocition
david = developers(:david)
assert_nothing_raised do
- assert_equal david.projects, david.projects.reload.reload
+ ActiveSupport::Deprecation.silence do
+ assert_equal david.projects, david.projects.reload.reload
+ end
end
end
@@ -1209,8 +1209,10 @@ def test_scoped_find_limit_offset_including_has_many_association
end
def test_scoped_find_order_including_has_many_association
- developers = Developer.send(:with_scope, :find => { :order => 'developers.salary DESC', :include => :projects }) do
- Developer.find(:all)
+ developers = ActiveSupport::Deprecation.silence do
+ Developer.send(:with_scope, :find => { :order => 'developers.salary DESC', :include => :projects }) do
+ Developer.find(:all)
+ end
end
assert developers.size >= 2
for i in 1...developers.size
@@ -119,8 +119,10 @@ def test_exists_with_aggregate_having_three_mappings_with_one_difference
end
def test_exists_with_scoped_include
- Developer.send(:with_scope, :find => { :include => :projects, :order => "projects.name" }) do
- assert Developer.exists?
+ ActiveSupport::Deprecation.silence do
+ Developer.send(:with_scope, :find => { :include => :projects, :order => "projects.name" }) do
+ assert Developer.exists?
+ end
end
end
@@ -103,8 +103,10 @@ def test_scoped_count
def test_scoped_find_include
# with the include, will retrieve only developers for the given project
- scoped_developers = Developer.send(:with_scope, :find => { :include => :projects }) do
- Developer.find(:all, :conditions => 'projects.id = 2')
+ scoped_developers = ActiveSupport::Deprecation.silence do
+ Developer.send(:with_scope, :find => { :include => :projects }) do
+ Developer.find(:all, :conditions => 'projects.id = 2')
+ end
end
assert scoped_developers.include?(developers(:david))
assert !scoped_developers.include?(developers(:jamis))
@@ -339,44 +341,50 @@ def test_nested_scoped_find
end
def test_nested_scoped_find_include
- Developer.send(:with_scope, :find => { :include => :projects }) do
- Developer.send(:with_scope, :find => { :conditions => "projects.id = 2" }) do
- assert_nothing_raised { Developer.find(1) }
- assert_equal('David', Developer.find(:first).name)
+ ActiveSupport::Deprecation.silence do
+ Developer.send(:with_scope, :find => { :include => :projects }) do
+ Developer.send(:with_scope, :find => { :conditions => "projects.id = 2" }) do
+ assert_nothing_raised { Developer.find(1) }
+ assert_equal('David', Developer.find(:first).name)
+ end
end
end
end
def test_nested_scoped_find_merged_include
# :include's remain unique and don't "double up" when merging
- Developer.send(:with_scope, :find => { :include => :projects, :conditions => "projects.id = 2" }) do
- Developer.send(:with_scope, :find => { :include => :projects }) do
- assert_equal 1, Developer.scoped.includes_values.uniq.length
- assert_equal 'David', Developer.find(:first).name
+ ActiveSupport::Deprecation.silence do
+ Developer.send(:with_scope, :find => { :include => :projects, :conditions => "projects.id = 2" }) do
+ Developer.send(:with_scope, :find => { :include => :projects }) do
+ assert_equal 1, Developer.scoped.includes_values.uniq.length
+ assert_equal 'David', Developer.find(:first).name
+ end
end
- end
- # the nested scope doesn't remove the first :include
- Developer.send(:with_scope, :find => { :include => :projects, :conditions => "projects.id = 2" }) do
- Developer.send(:with_scope, :find => { :include => [] }) do
- assert_equal 1, Developer.scoped.includes_values.uniq.length
- assert_equal('David', Developer.find(:first).name)
+ # the nested scope doesn't remove the first :include
+ Developer.send(:with_scope, :find => { :include => :projects, :conditions => "projects.id = 2" }) do
+ Developer.send(:with_scope, :find => { :include => [] }) do
+ assert_equal 1, Developer.scoped.includes_values.uniq.length
+ assert_equal('David', Developer.find(:first).name)
+ end
end
- end
- # mixing array and symbol include's will merge correctly
- Developer.send(:with_scope, :find => { :include => [:projects], :conditions => "projects.id = 2" }) do
- Developer.send(:with_scope, :find => { :include => :projects }) do
- assert_equal 1, Developer.scoped.includes_values.uniq.length
- assert_equal('David', Developer.find(:first).name)
+ # mixing array and symbol include's will merge correctly
+ Developer.send(:with_scope, :find => { :include => [:projects], :conditions => "projects.id = 2" }) do
+ Developer.send(:with_scope, :find => { :include => :projects }) do
+ assert_equal 1, Developer.scoped.includes_values.uniq.length
+ assert_equal('David', Developer.find(:first).name)
+ end
end
end
end
def test_nested_scoped_find_replace_include
- Developer.send(:with_scope, :find => { :include => :projects }) do
- Developer.send(:with_exclusive_scope, :find => { :include => [] }) do
- assert_equal 0, Developer.scoped.includes_values.length
+ ActiveSupport::Deprecation.silence do
+ Developer.send(:with_scope, :find => { :include => :projects }) do
+ Developer.send(:with_exclusive_scope, :find => { :include => [] }) do
+ assert_equal 0, Developer.scoped.includes_values.length
+ end
end
end
end
@@ -34,8 +34,10 @@ def test_module_spanning_associations
def test_module_spanning_has_and_belongs_to_many_associations
project = MyApplication::Business::Project.find(:first)
- project.developers << MyApplication::Business::Developer.create("name" => "John")
- assert_equal "John", project.developers.last.name
+ ActiveSupport::Deprecation.silence do
+ project.developers << MyApplication::Business::Developer.create("name" => "John")
+ assert_equal "John", project.developers.last.name
+ end
end
def test_associations_spanning_cross_modules
@@ -421,7 +421,7 @@ def test_update_attributes!
def test_destroyed_returns_boolean
developer = Developer.first
assert_equal false, developer.destroyed?
- developer.destroy
+ ActiveSupport::Deprecation.silence { developer.destroy }
assert_equal true, developer.destroyed?
developer = Developer.last
@@ -438,7 +438,7 @@ def test_persisted_returns_boolean
developer = Developer.first
assert_equal true, developer.persisted?
- developer.destroy
+ ActiveSupport::Deprecation.silence { developer.destroy }
assert_equal false, developer.persisted?
developer = Developer.last
@@ -52,10 +52,12 @@ def test_find_with_joins_option_implies_readonly
def test_habtm_find_readonly
dev = Developer.find(1)
- assert !dev.projects.empty?
- assert dev.projects.all?(&:readonly?)
- assert dev.projects.find(:all).all?(&:readonly?)
- assert dev.projects.readonly(true).all?(&:readonly?)
+ ActiveSupport::Deprecation.silence do
+ assert !dev.projects.empty?
+ assert dev.projects.all?(&:readonly?)
+ assert dev.projects.find(:all).all?(&:readonly?)
+ assert dev.projects.readonly(true).all?(&:readonly?)
+ end
end
def test_has_many_find_readonly
@@ -102,7 +104,7 @@ def test_readonly_scoping
end
def test_association_collection_method_missing_scoping_not_readonly
- assert !Developer.find(1).projects.foo.readonly?
+ ActiveSupport::Deprecation.silence { assert !Developer.find(1).projects.foo.readonly? }
assert !Post.find(1).comments.foo.readonly?
end
end
@@ -85,8 +85,10 @@ def test_scoped_count
def test_scoped_find_include
# with the include, will retrieve only developers for the given project
- scoped_developers = Developer.includes(:projects).scoping do
- Developer.where('projects.id = 2').all
+ scoped_developers = ActiveSupport::Deprecation.silence do
+ Developer.includes(:projects).scoping do
+ Developer.where('projects.id = 2').all
+ end
end
assert scoped_developers.include?(developers(:david))
assert !scoped_developers.include?(developers(:jamis))
@@ -351,7 +353,7 @@ def test_default_scoping_with_inheritance
end
def test_default_scope_called_twice_merges_conditions
- Developer.destroy_all
+ ActiveSupport::Deprecation.silence { Developer.destroy_all }
Developer.create!(:name => "David", :salary => 80000)
Developer.create!(:name => "David", :salary => 100000)
Developer.create!(:name => "Brian", :salary => 100000)
@@ -365,7 +367,7 @@ def test_default_scope_called_twice_merges_conditions
end
def test_default_scope_called_twice_in_different_place_merges_where_clause
- Developer.destroy_all
+ ActiveSupport::Deprecation.silence { Developer.destroy_all }
Developer.create!(:name => "David", :salary => 80000)
Developer.create!(:name => "David", :salary => 100000)
Developer.create!(:name => "Brian", :salary => 100000)

0 comments on commit f420c2e

Please sign in to comment.