activerecord 1.15.5 → 1.15.6

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

data/CHANGELOG CHANGED
@@ -1,3 +1,12 @@
1
+ *1.15.6* (November 24th, 2007)
2
+
3
+ * Allow association redefinition in subclasses. #9346 [wildchild]
4
+
5
+ * Fix has_many :through delete with custom foreign keys. #6466 [naffis]
6
+
7
+ * Fix regression where the association would not construct new finder SQL on save causing bogus queries for "WHERE owner_id = NULL" even after owner was saved. #8713 [Bryan Helmkamp]
8
+
9
+
1
10
  *1.15.5* (October 12th, 2007)
2
11
 
3
12
  * Depend on Action Pack 1.4.4
@@ -50,6 +50,12 @@ module ActiveRecord
50
50
  end
51
51
  end
52
52
 
53
+ class HasManyThroughCantDissociateNewRecords < ActiveRecordError #:nodoc:
54
+ def initialize(owner, reflection)
55
+ super("Cannot dissociate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to delete the has_many :through record associating them.")
56
+ end
57
+ end
58
+
53
59
  class EagerLoadPolymorphicError < ActiveRecordError #:nodoc:
54
60
  def initialize(reflection)
55
61
  super("Can not eagerly load the polymorphic association #{reflection.name.inspect}")
@@ -862,7 +868,7 @@ module ActiveRecord
862
868
  # Don't use a before_destroy callback since users' before_destroy
863
869
  # callbacks will be executed after the association is wiped out.
864
870
  old_method = "destroy_without_habtm_shim_for_#{reflection.name}"
865
- class_eval <<-end_eval
871
+ class_eval <<-end_eval unless method_defined?(old_method)
866
872
  alias_method :#{old_method}, :destroy_without_callbacks
867
873
  def destroy_without_callbacks
868
874
  #{reflection.name}.clear
@@ -1002,10 +1008,10 @@ module ActiveRecord
1002
1008
  []
1003
1009
  end
1004
1010
 
1005
- if !records_to_save.blank?
1006
- records_to_save.each { |record| association.send(:insert_record, record) }
1007
- association.send(:construct_sql) # reconstruct the SQL queries now that we know the owner's id
1008
- end
1011
+ records_to_save.each { |record| association.send(:insert_record, record) } unless records_to_save.blank?
1012
+
1013
+ # reconstruct the SQL queries now that we know the owner's id
1014
+ association.send(:construct_sql) if association.respond_to?(:construct_sql)
1009
1015
  end_eval
1010
1016
 
1011
1017
  # Doesn't use after_save as that would save associations added in after_create/after_update twice
@@ -1286,7 +1292,9 @@ module ActiveRecord
1286
1292
  defined_callbacks = options[callback_name.to_sym]
1287
1293
  if options.has_key?(callback_name.to_sym)
1288
1294
  class_inheritable_reader full_callback_name.to_sym
1289
- write_inheritable_array(full_callback_name.to_sym, [defined_callbacks].flatten)
1295
+ write_inheritable_attribute(full_callback_name.to_sym, [defined_callbacks].flatten)
1296
+ else
1297
+ write_inheritable_attribute(full_callback_name.to_sym, [])
1290
1298
  end
1291
1299
  end
1292
1300
  end
@@ -71,20 +71,26 @@ module ActiveRecord
71
71
 
72
72
  # Remove +records+ from this association. Does not destroy +records+.
73
73
  def delete(*records)
74
- records = flatten_deeper(records)
75
- records.each { |associate| raise_on_type_mismatch(associate) }
76
- records.reject! { |associate| @target.delete(associate) if associate.new_record? }
77
74
  return if records.empty?
78
-
79
- @delete_join_finder ||= "find_all_by_#{@reflection.source_reflection.association_foreign_key}"
75
+ records.each { |associate| raise_on_type_mismatch(associate) }
76
+
80
77
  through = @reflection.through_reflection
81
- through.klass.transaction do
82
- records.each do |associate|
83
- joins = @owner.send(through.name).send(@delete_join_finder, associate.id)
84
- @owner.send(through.name).delete(joins)
78
+ raise ActiveRecord::HasManyThroughCantDissociateNewRecords.new(@owner, through) if @owner.new_record?
79
+
80
+ load_target
81
+
82
+ klass = through.klass
83
+ klass.transaction do
84
+ flatten_deeper(records).each do |associate|
85
+ raise_on_type_mismatch(associate)
86
+ raise ActiveRecord::HasManyThroughCantDissociateNewRecords.new(@owner, through) unless associate.respond_to?(:new_record?) && !associate.new_record?
87
+
88
+ @owner.send(@reflection.through_reflection.name).proxy_target.delete(klass.delete_all(construct_join_attributes(associate)))
85
89
  @target.delete(associate)
86
90
  end
87
91
  end
92
+
93
+ self
88
94
  end
89
95
 
90
96
  def build(attrs = nil)
@@ -2,7 +2,7 @@ module ActiveRecord
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 1
4
4
  MINOR = 15
5
- TINY = 5
5
+ TINY = 6
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -93,3 +93,21 @@ class AggregationsTest < Test::Unit::TestCase
93
93
  assert_raises(NoMethodError) { customers(:david).balance = nil }
94
94
  end
95
95
  end
96
+
97
+ class OverridingAggregationsTest < Test::Unit::TestCase
98
+ class Name; end
99
+ class DifferentName; end
100
+
101
+ class Person < ActiveRecord::Base
102
+ composed_of :composed_of, :mapping => %w(person_first_name first_name)
103
+ end
104
+
105
+ class DifferentPerson < Person
106
+ composed_of :composed_of, :class_name => 'DifferentName', :mapping => %w(different_person_first_name first_name)
107
+ end
108
+
109
+ def test_composed_of_aggregation_redefinition_reflections_should_differ_and_not_inherited
110
+ assert_not_equal Person.reflect_on_aggregation(:composed_of),
111
+ DifferentPerson.reflect_on_aggregation(:composed_of)
112
+ end
113
+ end
@@ -8,10 +8,12 @@ require 'fixtures/category'
8
8
  require 'fixtures/categorization'
9
9
  require 'fixtures/vertex'
10
10
  require 'fixtures/edge'
11
+ require 'fixtures/book'
12
+ require 'fixtures/citation'
11
13
 
12
14
  class AssociationsJoinModelTest < Test::Unit::TestCase
13
15
  self.use_transactional_fixtures = false
14
- fixtures :posts, :authors, :categories, :categorizations, :comments, :tags, :taggings, :author_favorites, :vertices
16
+ fixtures :posts, :authors, :categories, :categorizations, :comments, :tags, :taggings, :author_favorites, :vertices, :books
15
17
 
16
18
  def test_has_many
17
19
  assert authors(:david).categories.include?(categories(:general))
@@ -450,7 +452,21 @@ class AssociationsJoinModelTest < Test::Unit::TestCase
450
452
  tags = posts(:thinking).tags
451
453
  assert_equal tags, posts(:thinking).tags.push(tags(:general))
452
454
  end
453
-
455
+
456
+ def test_delete_associate_when_deleting_from_has_many_through_with_non_standard_id
457
+ count = books(:awdr).references.count
458
+ references_before = books(:awdr).references
459
+ book = Book.create!(:name => 'Getting Real')
460
+ book_awdr = books(:awdr)
461
+ book_awdr.references << book
462
+ assert_equal(count + 1, book_awdr.references(true).size)
463
+
464
+ assert_nothing_raised { book_awdr.references.delete(book) }
465
+ assert_equal(count, book_awdr.references.size)
466
+ assert_equal(count, book_awdr.references(true).size)
467
+ assert_equal(references_before.sort, book_awdr.references.sort)
468
+ end
469
+
454
470
  def test_delete_associate_when_deleting_from_has_many_through
455
471
  count = posts(:thinking).tags.count
456
472
  tags_before = posts(:thinking).tags
@@ -10,6 +10,8 @@ require 'fixtures/order'
10
10
  require 'fixtures/category'
11
11
  require 'fixtures/post'
12
12
  require 'fixtures/author'
13
+ require 'fixtures/person'
14
+ require 'fixtures/reader'
13
15
 
14
16
 
15
17
  class AssociationsTest < Test::Unit::TestCase
@@ -21,6 +23,14 @@ class AssociationsTest < Test::Unit::TestCase
21
23
  Class.new(ActiveRecord::Base).has_many(:wheels, :name => 'wheels')
22
24
  end
23
25
  end
26
+
27
+ def test_should_construct_new_finder_sql_after_create
28
+ person = Person.new
29
+ assert_equal [], person.readers.find(:all)
30
+ person.save!
31
+ reader = Reader.create! :person => person, :post => Post.new(:title => "foo", :body => "bar")
32
+ assert_equal [reader], person.readers.find(:all)
33
+ end
24
34
 
25
35
  def test_force_reload
26
36
  firm = Firm.new("name" => "A New Firm, Inc")
@@ -1840,3 +1850,68 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
1840
1850
  assert_equal %w(1 2), projects.scan(/\d/).sort
1841
1851
  end
1842
1852
  end
1853
+
1854
+
1855
+ class OverridingAssociationsTest < Test::Unit::TestCase
1856
+ class Person < ActiveRecord::Base; end
1857
+ class DifferentPerson < ActiveRecord::Base; end
1858
+
1859
+ class PeopleList < ActiveRecord::Base
1860
+ has_and_belongs_to_many :has_and_belongs_to_many, :before_add => :enlist
1861
+ has_many :has_many, :before_add => :enlist
1862
+ belongs_to :belongs_to
1863
+ has_one :has_one
1864
+ end
1865
+
1866
+ class DifferentPeopleList < PeopleList
1867
+ # Different association with the same name, callbacks should be omitted here.
1868
+ has_and_belongs_to_many :has_and_belongs_to_many, :class_name => 'DifferentPerson'
1869
+ has_many :has_many, :class_name => 'DifferentPerson'
1870
+ belongs_to :belongs_to, :class_name => 'DifferentPerson', :foreign_key => 'belongs_to_id'
1871
+ has_one :has_one, :class_name => 'DifferentPerson'
1872
+ end
1873
+
1874
+ def test_habtm_association_redefinition_callbacks_should_differ_and_not_inherited
1875
+ # redeclared association on AR descendant should not inherit callbacks from superclass
1876
+ callbacks = PeopleList.read_inheritable_attribute(:before_add_for_has_and_belongs_to_many)
1877
+ assert_equal([:enlist], callbacks)
1878
+ callbacks = DifferentPeopleList.read_inheritable_attribute(:before_add_for_has_and_belongs_to_many)
1879
+ assert_equal([], callbacks)
1880
+ end
1881
+
1882
+ def test_has_many_association_redefinition_callbacks_should_differ_and_not_inherited
1883
+ # redeclared association on AR descendant should not inherit callbacks from superclass
1884
+ callbacks = PeopleList.read_inheritable_attribute(:before_add_for_has_many)
1885
+ assert_equal([:enlist], callbacks)
1886
+ callbacks = DifferentPeopleList.read_inheritable_attribute(:before_add_for_has_many)
1887
+ assert_equal([], callbacks)
1888
+ end
1889
+
1890
+ def test_habtm_association_redefinition_reflections_should_differ_and_not_inherited
1891
+ assert_not_equal(
1892
+ PeopleList.reflect_on_association(:has_and_belongs_to_many),
1893
+ DifferentPeopleList.reflect_on_association(:has_and_belongs_to_many)
1894
+ )
1895
+ end
1896
+
1897
+ def test_has_many_association_redefinition_reflections_should_differ_and_not_inherited
1898
+ assert_not_equal(
1899
+ PeopleList.reflect_on_association(:has_many),
1900
+ DifferentPeopleList.reflect_on_association(:has_many)
1901
+ )
1902
+ end
1903
+
1904
+ def test_belongs_to_association_redefinition_reflections_should_differ_and_not_inherited
1905
+ assert_not_equal(
1906
+ PeopleList.reflect_on_association(:belongs_to),
1907
+ DifferentPeopleList.reflect_on_association(:belongs_to)
1908
+ )
1909
+ end
1910
+
1911
+ def test_has_one_association_redefinition_reflections_should_differ_and_not_inherited
1912
+ assert_not_equal(
1913
+ PeopleList.reflect_on_association(:has_one),
1914
+ DifferentPeopleList.reflect_on_association(:has_one)
1915
+ )
1916
+ end
1917
+ end
@@ -0,0 +1,4 @@
1
+ class Book < ActiveRecord::Base
2
+ has_many :citations, :foreign_key => 'book1_id'
3
+ has_many :references, :through => :citations, :source => :reference_of, :uniq => true
4
+ end
@@ -0,0 +1,7 @@
1
+ awdr:
2
+ id: 1
3
+ name: "Agile Web Development with Rails"
4
+
5
+ rfr:
6
+ id: 2
7
+ name: "Ruby for Rails"
@@ -0,0 +1,6 @@
1
+ class Citation < ActiveRecord::Base
2
+ belongs_to :reference_of, :class_name => "Book", :foreign_key => :book2_id
3
+
4
+ belongs_to :book1, :class_name => "Book", :foreign_key => :book1_id
5
+ belongs_to :book2, :class_name => "Book", :foreign_key => :book2_id
6
+ end
@@ -62,4 +62,13 @@ ActiveRecord::Schema.define do
62
62
  t.column :message, :string, :null=>false
63
63
  t.column :developer_id, :integer, :null=>false
64
64
  end
65
+
66
+ create_table :books, :force => true do |t|
67
+ t.column :name, :string
68
+ end
69
+
70
+ create_table :citations, :force => true do |t|
71
+ t.column :book1_id, :integer
72
+ t.column :book2_id, :integer
73
+ end
65
74
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: activerecord
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.15.5
7
- date: 2007-10-12 00:00:00 -05:00
6
+ version: 1.15.6
7
+ date: 2007-11-24 00:00:00 +13:00
8
8
  summary: Implements the ActiveRecord pattern for ORM.
9
9
  require_paths:
10
10
  - lib
@@ -169,6 +169,8 @@ files:
169
169
  - test/fixtures/bad_fixtures/missing_value
170
170
  - test/fixtures/binaries.yml
171
171
  - test/fixtures/binary.rb
172
+ - test/fixtures/book.rb
173
+ - test/fixtures/books.yml
172
174
  - test/fixtures/categories
173
175
  - test/fixtures/categories/special_categories.yml
174
176
  - test/fixtures/categories/subsubdir
@@ -179,6 +181,7 @@ files:
179
181
  - test/fixtures/categorization.rb
180
182
  - test/fixtures/categorizations.yml
181
183
  - test/fixtures/category.rb
184
+ - test/fixtures/citation.rb
182
185
  - test/fixtures/column_name.rb
183
186
  - test/fixtures/comment.rb
184
187
  - test/fixtures/comments.yml