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 +9 -0
- data/lib/active_record/associations.rb +14 -6
- data/lib/active_record/associations/has_many_through_association.rb +15 -9
- data/lib/active_record/version.rb +1 -1
- data/test/aggregations_test.rb +18 -0
- data/test/associations/join_model_test.rb +18 -2
- data/test/associations_test.rb +75 -0
- data/test/fixtures/book.rb +4 -0
- data/test/fixtures/books.yml +7 -0
- data/test/fixtures/citation.rb +6 -0
- data/test/fixtures/db_definitions/schema.rb +9 -0
- metadata +5 -2
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
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
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
|
-
|
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
|
-
|
75
|
+
records.each { |associate| raise_on_type_mismatch(associate) }
|
76
|
+
|
80
77
|
through = @reflection.through_reflection
|
81
|
-
through.
|
82
|
-
|
83
|
-
|
84
|
-
|
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)
|
data/test/aggregations_test.rb
CHANGED
@@ -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
|
data/test/associations_test.rb
CHANGED
@@ -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
|
@@ -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.
|
7
|
-
date: 2007-
|
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
|