tenacity 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/EXTEND.rdoc +9 -13
- data/Rakefile +6 -0
- data/history.txt +17 -0
- data/lib/tenacity.rb +13 -9
- data/lib/tenacity/associate_proxy.rb +56 -0
- data/lib/tenacity/associates_proxy.rb +5 -3
- data/lib/tenacity/association.rb +81 -9
- data/lib/tenacity/associations/belongs_to.rb +28 -16
- data/lib/tenacity/associations/has_many.rb +113 -53
- data/lib/tenacity/associations/has_one.rb +33 -14
- data/lib/tenacity/class_methods.rb +117 -9
- data/lib/tenacity/errors.rb +9 -0
- data/lib/tenacity/instance_methods.rb +40 -3
- data/lib/tenacity/orm_ext/activerecord.rb +114 -95
- data/lib/tenacity/orm_ext/couchrest.rb +132 -113
- data/lib/tenacity/orm_ext/datamapper.rb +138 -112
- data/lib/tenacity/orm_ext/helpers.rb +36 -0
- data/lib/tenacity/orm_ext/mongo_mapper.rb +102 -84
- data/lib/tenacity/orm_ext/mongoid.rb +106 -87
- data/lib/tenacity/orm_ext/sequel.rb +137 -110
- data/lib/tenacity/version.rb +1 -1
- data/tenacity.gemspec +2 -1
- data/test/association_features/belongs_to_test.rb +46 -1
- data/test/association_features/has_many_test.rb +187 -2
- data/test/association_features/has_one_test.rb +57 -2
- data/test/associations/belongs_to_test.rb +41 -7
- data/test/associations/has_many_test.rb +59 -10
- data/test/associations/has_one_test.rb +57 -2
- data/test/fixtures/active_record_car.rb +5 -4
- data/test/fixtures/active_record_climate_control_unit.rb +1 -0
- data/test/fixtures/active_record_engine.rb +1 -0
- data/test/fixtures/active_record_has_many_target.rb +7 -0
- data/test/fixtures/active_record_has_one_target.rb +7 -0
- data/test/fixtures/active_record_object.rb +19 -0
- data/test/fixtures/couch_rest_has_many_target.rb +7 -0
- data/test/fixtures/couch_rest_has_one_target.rb +7 -0
- data/test/fixtures/couch_rest_object.rb +14 -0
- data/test/fixtures/data_mapper_has_many_target.rb +23 -3
- data/test/fixtures/data_mapper_has_one_target.rb +23 -3
- data/test/fixtures/data_mapper_object.rb +14 -0
- data/test/fixtures/mongo_mapper_air_filter.rb +6 -0
- data/test/fixtures/mongo_mapper_alternator.rb +7 -0
- data/test/fixtures/mongo_mapper_autosave_false_has_many_target.rb +8 -0
- data/test/fixtures/mongo_mapper_autosave_false_has_one_target.rb +8 -0
- data/test/fixtures/mongo_mapper_autosave_true_has_many_target.rb +8 -0
- data/test/fixtures/mongo_mapper_autosave_true_has_one_target.rb +8 -0
- data/test/fixtures/mongo_mapper_circuit_board.rb +6 -0
- data/test/fixtures/mongo_mapper_dashboard.rb +5 -2
- data/test/fixtures/mongo_mapper_has_many_target.rb +7 -0
- data/test/fixtures/mongo_mapper_has_one_target.rb +7 -0
- data/test/fixtures/mongo_mapper_object.rb +14 -0
- data/test/fixtures/mongo_mapper_wheel.rb +2 -0
- data/test/fixtures/mongo_mapper_windows.rb +6 -0
- data/test/fixtures/mongoid_has_many_target.rb +7 -0
- data/test/fixtures/mongoid_has_one_target.rb +7 -0
- data/test/fixtures/mongoid_object.rb +14 -0
- data/test/fixtures/sequel_has_many_target.rb +7 -0
- data/test/fixtures/sequel_has_one_target.rb +7 -0
- data/test/fixtures/sequel_object.rb +14 -0
- data/test/helpers/active_record_test_helper.rb +87 -8
- data/test/helpers/couch_rest_test_helper.rb +7 -0
- data/test/helpers/data_mapper_test_helper.rb +41 -3
- data/test/helpers/sequel_test_helper.rb +65 -9
- data/test/orm_ext/activerecord_test.rb +1 -1
- data/test/orm_ext/datamapper_test.rb +33 -24
- data/test/orm_ext/mongo_mapper_test.rb +6 -6
- data/test/orm_ext/mongoid_test.rb +6 -6
- data/test/orm_ext/sequel_test.rb +1 -1
- data/test/test_helper.rb +18 -9
- metadata +119 -55
@@ -1,134 +1,161 @@
|
|
1
1
|
module Tenacity
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
model.
|
50
|
-
|
2
|
+
module OrmExt
|
3
|
+
# Tenacity relationships on Sequel objects require that certain columns
|
4
|
+
# exist on the associated table, and that join tables exist for one-to-many
|
5
|
+
# relationships. Take the following class for example:
|
6
|
+
#
|
7
|
+
# class Car < Sequel::Model
|
8
|
+
# include Tenacity
|
9
|
+
#
|
10
|
+
# t_has_many :wheels
|
11
|
+
# t_has_one :dashboard
|
12
|
+
# t_belongs_to :driver
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
#
|
16
|
+
# == t_belongs_to
|
17
|
+
#
|
18
|
+
# The +t_belongs_to+ association requires that a property exist in the table
|
19
|
+
# to hold the id of the assoicated object.
|
20
|
+
#
|
21
|
+
# DB.create_table :cars do
|
22
|
+
# primary_key :id
|
23
|
+
# String :driver_id
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
#
|
27
|
+
# == t_has_one
|
28
|
+
#
|
29
|
+
# The +t_has_one+ association requires no special column in the table, since
|
30
|
+
# the associated object holds the foreign key.
|
31
|
+
#
|
32
|
+
#
|
33
|
+
# == t_has_many
|
34
|
+
#
|
35
|
+
# The +t_has_many+ association requires that a join table exist to store the
|
36
|
+
# associations. The name of the join table follows ActiveRecord conventions.
|
37
|
+
# The name of the join table in this example would be cars_wheels, since cars
|
38
|
+
# comes before wheels when shorted alphabetically.
|
39
|
+
#
|
40
|
+
# DB.create_table :cars_wheels do
|
41
|
+
# Integer :car_id
|
42
|
+
# String :wheel_id
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
module Sequel
|
46
|
+
|
47
|
+
def self.setup(model)
|
48
|
+
require 'sequel'
|
49
|
+
if model.ancestors.include?(::Sequel::Model)
|
50
|
+
model.send :include, Sequel::InstanceMethods
|
51
|
+
model.extend Sequel::ClassMethods
|
52
|
+
end
|
53
|
+
rescue LoadError
|
54
|
+
# Sequel not available
|
51
55
|
end
|
52
|
-
rescue LoadError
|
53
|
-
# Sequel not available
|
54
|
-
end
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
attr_accessor :_t_belongs_to_associations
|
57
|
+
module ClassMethods #:nodoc:
|
58
|
+
include Tenacity::OrmExt::Helpers
|
59
59
|
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
attr_accessor :_t_has_one_associations
|
61
|
+
attr_accessor :_t_has_many_associations
|
62
|
+
attr_accessor :_t_belongs_to_associations
|
63
63
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
64
|
+
def _t_id_type
|
65
|
+
Integer
|
66
|
+
end
|
68
67
|
|
69
|
-
|
70
|
-
|
71
|
-
|
68
|
+
def _t_find(id)
|
69
|
+
self[_t_serialize(id)]
|
70
|
+
end
|
72
71
|
|
73
|
-
|
74
|
-
|
75
|
-
|
72
|
+
def _t_find_bulk(ids)
|
73
|
+
return [] if ids.nil? || ids.empty?
|
74
|
+
filter(:id => _t_serialize_ids(ids)).to_a
|
75
|
+
end
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
end
|
77
|
+
def _t_find_first_by_associate(property, id)
|
78
|
+
first(property.to_sym => _t_serialize(id))
|
79
|
+
end
|
81
80
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
end
|
81
|
+
def _t_find_all_by_associate(property, id)
|
82
|
+
filter(property => _t_serialize(id)).to_a
|
83
|
+
end
|
86
84
|
|
87
|
-
|
88
|
-
if run_callbacks
|
89
|
-
filter(:id => ids).destroy
|
90
|
-
else
|
91
|
-
filter(:id => ids).delete
|
85
|
+
def _t_initialize_tenacity
|
92
86
|
end
|
93
|
-
end
|
94
|
-
end
|
95
87
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
super
|
101
|
-
end
|
88
|
+
def _t_initialize_has_one_association(association)
|
89
|
+
@_t_has_one_associations ||= []
|
90
|
+
@_t_has_one_associations << association
|
91
|
+
end
|
102
92
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
end
|
93
|
+
def _t_initialize_has_many_association(association)
|
94
|
+
@_t_has_many_associations ||= []
|
95
|
+
@_t_has_many_associations << association
|
96
|
+
end
|
108
97
|
|
109
|
-
|
110
|
-
|
111
|
-
|
98
|
+
def _t_initialize_belongs_to_association(association)
|
99
|
+
@_t_belongs_to_associations ||= []
|
100
|
+
@_t_belongs_to_associations << association
|
101
|
+
end
|
112
102
|
|
113
|
-
|
114
|
-
|
103
|
+
def _t_delete(ids, run_callbacks=true)
|
104
|
+
if run_callbacks
|
105
|
+
filter(:id => _t_serialize_ids(ids)).destroy
|
106
|
+
else
|
107
|
+
filter(:id => _t_serialize_ids(ids)).delete
|
108
|
+
end
|
109
|
+
end
|
115
110
|
end
|
116
111
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
112
|
+
module InstanceMethods #:nodoc:
|
113
|
+
include Tenacity::OrmExt::Helpers
|
114
|
+
|
115
|
+
def after_save
|
116
|
+
_t_save_autosave_associations
|
117
|
+
|
118
|
+
associations = self.class._t_has_many_associations || []
|
119
|
+
associations.each { |association| self.class._t_save_associates(self, association) }
|
120
|
+
super
|
121
|
+
end
|
122
|
+
|
123
|
+
def after_destroy
|
124
|
+
associations = self.class._t_belongs_to_associations || []
|
125
|
+
associations.each { |association| self._t_cleanup_belongs_to_association(association) }
|
126
|
+
|
127
|
+
associations = self.class._t_has_one_associations || []
|
128
|
+
associations.each { |association| self._t_cleanup_has_one_association(association) }
|
129
|
+
|
130
|
+
associations = self.class._t_has_many_associations || []
|
131
|
+
associations.each { |association| self._t_cleanup_has_many_association(association) }
|
132
|
+
super
|
133
|
+
end
|
134
|
+
|
135
|
+
def _t_reload
|
136
|
+
reload
|
137
|
+
end
|
138
|
+
|
139
|
+
def _t_clear_associates(association)
|
140
|
+
db["delete from #{association.join_table} where #{association.association_key} = #{_t_serialize_id_for_sql(self.id)}"].delete
|
141
|
+
end
|
142
|
+
|
143
|
+
def _t_associate_many(association, associate_ids)
|
144
|
+
db.transaction do
|
145
|
+
_t_clear_associates(association)
|
146
|
+
associate_ids.each do |associate_id|
|
147
|
+
db["insert into #{association.join_table} (#{association.association_key}, #{association.association_foreign_key}) values (#{_t_serialize_id_for_sql(self.id)}, #{_t_serialize_id_for_sql(associate_id)})"].insert
|
148
|
+
end
|
122
149
|
end
|
123
150
|
end
|
124
|
-
end
|
125
151
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
152
|
+
def _t_get_associate_ids(association)
|
153
|
+
return [] if self.id.nil?
|
154
|
+
rows = db["select #{association.association_foreign_key} from #{association.join_table} where #{association.association_key} = #{_t_serialize_id_for_sql(self.id)}"].all
|
155
|
+
rows.map { |row| row[association.association_foreign_key.to_sym] }
|
156
|
+
end
|
130
157
|
end
|
131
|
-
end
|
132
158
|
|
159
|
+
end
|
133
160
|
end
|
134
161
|
end
|
data/lib/tenacity/version.rb
CHANGED
data/tenacity.gemspec
CHANGED
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.add_development_dependency "rake", "~> 0.8.7"
|
23
23
|
s.add_development_dependency "rcov", "~> 0.9.9"
|
24
24
|
s.add_development_dependency "shoulda", "~> 2.11.3"
|
25
|
+
s.add_development_dependency "mocha", "~> 0.9.10"
|
25
26
|
s.add_development_dependency "yard", "~> 0.6.4"
|
26
27
|
|
27
28
|
# Relational DBs
|
@@ -33,7 +34,7 @@ Gem::Specification.new do |s|
|
|
33
34
|
|
34
35
|
# MongoDB
|
35
36
|
s.add_development_dependency "mongo_mapper", "~> 0.8.6"
|
36
|
-
s.add_development_dependency "bson_ext", "~> 1.
|
37
|
+
s.add_development_dependency "bson_ext", "~> 1.2.4"
|
37
38
|
s.add_development_dependency "mongoid", "~> 2.0.0.beta"
|
38
39
|
|
39
40
|
# CouchDB
|
@@ -30,13 +30,58 @@ class BelongsToTest < Test::Unit::TestCase
|
|
30
30
|
should "be able to specify the foreign key to use for the associated class" do
|
31
31
|
car = ActiveRecordCar.create
|
32
32
|
windshield = CouchRestWindshield.create(:active_record_car => car)
|
33
|
-
assert_equal car.id
|
33
|
+
assert_equal car.id, windshield.car_id
|
34
34
|
assert !windshield.respond_to?(:active_record_car_id)
|
35
35
|
|
36
36
|
engine = ActiveRecordEngine.create(:active_record_car => car)
|
37
37
|
assert_equal car.id, engine.car_id
|
38
38
|
assert !engine.respond_to?(:active_record_car_id)
|
39
39
|
end
|
40
|
+
|
41
|
+
should "not be able to modify the associated object if the readonly option is set" do
|
42
|
+
engine = ActiveRecordEngine.create
|
43
|
+
air_filter = MongoMapperAirFilter.create(:active_record_engine => engine)
|
44
|
+
engine = air_filter.active_record_engine
|
45
|
+
engine.prop = "value"
|
46
|
+
assert_raises(Tenacity::ReadOnlyError) { engine.save }
|
47
|
+
end
|
48
|
+
|
49
|
+
should "save the associated object if autosave is true" do
|
50
|
+
source = MongoMapperAutosaveTrueHasOneTarget.create
|
51
|
+
target = ActiveRecordObject.create(:prop => 'abc')
|
52
|
+
source.active_record_object = target
|
53
|
+
source.save
|
54
|
+
assert_equal 'abc', source.active_record_object.prop
|
55
|
+
|
56
|
+
source.active_record_object.prop = 'xyz'
|
57
|
+
source.save
|
58
|
+
source.reload && source.active_record_object(true)
|
59
|
+
assert_equal 'xyz', source.active_record_object.prop
|
60
|
+
end
|
61
|
+
|
62
|
+
should "destroy the associated object if autosave is true and object is marked for destruction" do
|
63
|
+
source = MongoMapperAutosaveTrueHasOneTarget.create
|
64
|
+
target = ActiveRecordObject.create
|
65
|
+
source.active_record_object = target
|
66
|
+
source.save
|
67
|
+
assert_not_nil source.active_record_object(true)
|
68
|
+
|
69
|
+
source.active_record_object.mark_for_destruction
|
70
|
+
assert source.active_record_object.marked_for_destruction?
|
71
|
+
source.save
|
72
|
+
source.reload
|
73
|
+
assert_nil source.active_record_object(true)
|
74
|
+
end
|
75
|
+
|
76
|
+
should "be able to create a polymorphic association" do
|
77
|
+
circuit_board = MongoMapperCircuitBoard.create
|
78
|
+
alternator = MongoMapperAlternator.create
|
79
|
+
circuit_board.diagnosable = alternator
|
80
|
+
circuit_board.save
|
81
|
+
|
82
|
+
assert_equal alternator, MongoMapperCircuitBoard.find(circuit_board.id).diagnosable
|
83
|
+
assert_equal 'MongoMapperAlternator', circuit_board.diagnosable_type
|
84
|
+
end
|
40
85
|
end
|
41
86
|
|
42
87
|
end
|
@@ -4,7 +4,7 @@ class HasManyTest < Test::Unit::TestCase
|
|
4
4
|
|
5
5
|
context "A class with a belongs_to association to another class" do
|
6
6
|
setup do
|
7
|
-
|
7
|
+
setup_all_fixtures
|
8
8
|
@car = ActiveRecordCar.create
|
9
9
|
@wheels = [MongoMapperWheel.create, MongoMapperWheel.create, MongoMapperWheel.create]
|
10
10
|
|
@@ -43,7 +43,7 @@ class HasManyTest < Test::Unit::TestCase
|
|
43
43
|
car.save
|
44
44
|
|
45
45
|
assert_set_equal [door_1, door_2, door_3], ActiveRecordCar.find(car.id).couch_rest_doors
|
46
|
-
assert_set_equal [door_1.id
|
46
|
+
assert_set_equal [door_1.id, door_2.id, door_3.id], ActiveRecordCar.find(car.id).couch_rest_door_ids
|
47
47
|
end
|
48
48
|
|
49
49
|
should "save the associate object when it is added as an associate if the parent object is saved" do
|
@@ -79,6 +79,113 @@ class HasManyTest < Test::Unit::TestCase
|
|
79
79
|
assert_set_equal [door_1], ActiveRecordCar.find(car.id).couch_rest_doors
|
80
80
|
end
|
81
81
|
|
82
|
+
should "not be able to modify an associated object if the readonly option is set" do
|
83
|
+
car = ActiveRecordCar.create
|
84
|
+
wheel_1 = MongoMapperWheel.create
|
85
|
+
wheel_2 = MongoMapperWheel.create
|
86
|
+
wheel_3 = MongoMapperWheel.create
|
87
|
+
car.mongo_mapper_wheels = [wheel_1, wheel_2, wheel_3]
|
88
|
+
car.save
|
89
|
+
|
90
|
+
wheel = car.mongo_mapper_wheels.first
|
91
|
+
wheel.prop = "value"
|
92
|
+
assert_raises(Tenacity::ReadOnlyError) { wheel.save }
|
93
|
+
end
|
94
|
+
|
95
|
+
should "only return the number of results specified by the :limit option" do
|
96
|
+
car = ActiveRecordCar.create
|
97
|
+
wheel_1 = MongoMapperWheel.create
|
98
|
+
wheel_2 = MongoMapperWheel.create
|
99
|
+
wheel_3 = MongoMapperWheel.create
|
100
|
+
wheel_4 = MongoMapperWheel.create
|
101
|
+
wheel_5 = MongoMapperWheel.create
|
102
|
+
wheel_6 = MongoMapperWheel.create
|
103
|
+
wheel_7 = MongoMapperWheel.create
|
104
|
+
wheel_8 = MongoMapperWheel.create
|
105
|
+
car.mongo_mapper_wheels = [wheel_1, wheel_2, wheel_3, wheel_4, wheel_5, wheel_6, wheel_7, wheel_8]
|
106
|
+
car.save
|
107
|
+
|
108
|
+
sorted_wheels = car.mongo_mapper_wheels.sort { |a,b| a.id.to_s <=> b.id.to_s }
|
109
|
+
sorted_wheel_ids = sorted_wheels.map { |wheel| wheel.id.to_s }
|
110
|
+
|
111
|
+
assert_set_equal [sorted_wheels[0], sorted_wheels[1], sorted_wheels[2], sorted_wheels[3], sorted_wheels[4]],
|
112
|
+
ActiveRecordCar.find(car.id).mongo_mapper_wheels
|
113
|
+
assert_set_equal [sorted_wheel_ids[0], sorted_wheel_ids[1], sorted_wheel_ids[2], sorted_wheel_ids[3], sorted_wheel_ids[4]],
|
114
|
+
ActiveRecordCar.find(car.id).mongo_mapper_wheel_ids
|
115
|
+
end
|
116
|
+
|
117
|
+
should "skip over the first group of results, as specified by the :offset option" do
|
118
|
+
car = ActiveRecordCar.create
|
119
|
+
window_1 = MongoMapperWindow.create
|
120
|
+
window_2 = MongoMapperWindow.create
|
121
|
+
window_3 = MongoMapperWindow.create
|
122
|
+
window_4 = MongoMapperWindow.create
|
123
|
+
window_5 = MongoMapperWindow.create
|
124
|
+
window_6 = MongoMapperWindow.create
|
125
|
+
window_7 = MongoMapperWindow.create
|
126
|
+
window_8 = MongoMapperWindow.create
|
127
|
+
window_9 = MongoMapperWindow.create
|
128
|
+
car.mongo_mapper_windows = [window_1, window_2, window_3, window_4, window_5, window_6, window_7, window_8, window_9]
|
129
|
+
car.save
|
130
|
+
|
131
|
+
sorted_windows = car.mongo_mapper_windows.sort { |a,b| a.id.to_s <=> b.id.to_s }
|
132
|
+
sorted_window_ids = sorted_windows.map { |window| window.id.to_s }
|
133
|
+
|
134
|
+
assert_set_equal [sorted_windows[3], sorted_windows[4], sorted_windows[5], sorted_windows[6], sorted_windows[7]],
|
135
|
+
ActiveRecordCar.find(car.id).mongo_mapper_windows
|
136
|
+
assert_set_equal [sorted_window_ids[3], sorted_window_ids[4], sorted_window_ids[5], sorted_window_ids[6], sorted_window_ids[7]],
|
137
|
+
ActiveRecordCar.find(car.id).mongo_mapper_window_ids
|
138
|
+
end
|
139
|
+
|
140
|
+
should "be able to store objects via their polymorphic interface" do
|
141
|
+
circuit_board_1 = MongoMapperCircuitBoard.create
|
142
|
+
circuit_board_2 = MongoMapperCircuitBoard.create
|
143
|
+
circuit_board_3 = MongoMapperCircuitBoard.create
|
144
|
+
engine = ActiveRecordEngine.create
|
145
|
+
engine.diagnosable = [circuit_board_1, circuit_board_2, circuit_board_3]
|
146
|
+
engine.save
|
147
|
+
|
148
|
+
components = ActiveRecordEngine.find(engine.id).diagnosable
|
149
|
+
assert_set_equal [circuit_board_1, circuit_board_2, circuit_board_3], components
|
150
|
+
assert_set_equal ['ActiveRecordEngine', 'ActiveRecordEngine', 'ActiveRecordEngine'], components.map {|c| c.diagnosable_type}
|
151
|
+
end
|
152
|
+
|
153
|
+
context "with an autosave association" do
|
154
|
+
setup do
|
155
|
+
@source = ActiveRecordObject.create
|
156
|
+
@targets = [MongoMapperAutosaveTrueHasManyTarget.create(:prop => 'abc'), MongoMapperAutosaveTrueHasManyTarget.create(:prop => 'def')]
|
157
|
+
@source.mongo_mapper_autosave_true_has_many_targets = @targets
|
158
|
+
@source.save
|
159
|
+
assert_equal 'abc', @source.mongo_mapper_autosave_true_has_many_targets(true).first.prop
|
160
|
+
end
|
161
|
+
|
162
|
+
should "save the associated object if autosave is true" do
|
163
|
+
@source.mongo_mapper_autosave_true_has_many_targets.first.prop = 'xyz'
|
164
|
+
@source.save
|
165
|
+
@source.reload && @source.mongo_mapper_autosave_true_has_many_targets(true)
|
166
|
+
assert_equal 'xyz', @source.mongo_mapper_autosave_true_has_many_targets.first.prop
|
167
|
+
end
|
168
|
+
|
169
|
+
should "destroy the associated object stored in a local variable if autosave is true and object is marked for destruction" do
|
170
|
+
object = @source.mongo_mapper_autosave_true_has_many_targets.first
|
171
|
+
object.mark_for_destruction
|
172
|
+
assert object.marked_for_destruction?
|
173
|
+
@source.save
|
174
|
+
@source.reload && @source.mongo_mapper_autosave_true_has_many_targets(true)
|
175
|
+
assert_equal 1, @source.mongo_mapper_autosave_true_has_many_targets.size
|
176
|
+
assert_equal 'def', @source.mongo_mapper_autosave_true_has_many_targets.first.prop
|
177
|
+
end
|
178
|
+
|
179
|
+
should "destroy the associated object if autosave is true and object is marked for destruction" do
|
180
|
+
@source.mongo_mapper_autosave_true_has_many_targets.first.mark_for_destruction
|
181
|
+
assert @source.mongo_mapper_autosave_true_has_many_targets.first.marked_for_destruction?
|
182
|
+
@source.save
|
183
|
+
@source.reload && @source.mongo_mapper_autosave_true_has_many_targets(true)
|
184
|
+
assert_equal 1, @source.mongo_mapper_autosave_true_has_many_targets.size
|
185
|
+
assert_equal 'def', @source.mongo_mapper_autosave_true_has_many_targets.first.prop
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
82
189
|
context "with a set of associates that need to be deleted" do
|
83
190
|
setup do
|
84
191
|
@new_car = ActiveRecordCar.create
|
@@ -104,6 +211,84 @@ class HasManyTest < Test::Unit::TestCase
|
|
104
211
|
assert_equal old_count - 3, CouchRestDoor.count
|
105
212
|
assert_set_equal [], ActiveRecordCar.find(@new_car.id).couch_rest_doors
|
106
213
|
end
|
214
|
+
|
215
|
+
context "the delete method" do
|
216
|
+
should "not delete the object from the database if no dependent option is specified" do
|
217
|
+
dashboard = MongoMapperDashboard.create
|
218
|
+
vent_1 = MongoMapperVent.create
|
219
|
+
vent_2 = MongoMapperVent.create
|
220
|
+
vent_3 = MongoMapperVent.create
|
221
|
+
dashboard.vents = [vent_1, vent_2, vent_3]
|
222
|
+
dashboard.save
|
223
|
+
assert_set_equal [vent_1, vent_2, vent_3], MongoMapperDashboard.find(dashboard.id).vents
|
224
|
+
|
225
|
+
dashboard.vents.delete(vent_1)
|
226
|
+
dashboard.save
|
227
|
+
assert_set_equal [vent_2, vent_3], MongoMapperDashboard.find(dashboard.id).vents
|
228
|
+
assert_not_nil MongoMapperVent.find(vent_1.id)
|
229
|
+
end
|
230
|
+
|
231
|
+
should "delete the associated object and issue callbacks if association is configured to :destroy dependents" do
|
232
|
+
wheel_1 = MongoMapperWheel.create
|
233
|
+
wheel_2 = MongoMapperWheel.create
|
234
|
+
wheel_3 = MongoMapperWheel.create
|
235
|
+
@new_car.mongo_mapper_wheels = [wheel_1, wheel_2, wheel_3]
|
236
|
+
@new_car.save
|
237
|
+
assert_set_equal [wheel_1, wheel_2, wheel_3], ActiveRecordCar.find(@new_car.id).mongo_mapper_wheels
|
238
|
+
|
239
|
+
@new_car.mongo_mapper_wheels.delete(wheel_1)
|
240
|
+
@new_car.save
|
241
|
+
assert_set_equal [wheel_2, wheel_3], ActiveRecordCar.find(@new_car.id).mongo_mapper_wheels
|
242
|
+
assert_nil MongoMapperWheel._t_find(wheel_1.id)
|
243
|
+
end
|
244
|
+
|
245
|
+
should "delete the associated object without issuing callbacks if association is configured to :delete_all dependents" do
|
246
|
+
@new_car.couch_rest_doors.delete(@door_1)
|
247
|
+
@new_car.save
|
248
|
+
assert_set_equal [@door_2, @door_3], ActiveRecordCar.find(@new_car.id).couch_rest_doors
|
249
|
+
assert_nil CouchRestDoor._t_find(@door_1.id)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
context "the clear method" do
|
254
|
+
should "not delete the object from the database if no dependent option is specified" do
|
255
|
+
dashboard = MongoMapperDashboard.create
|
256
|
+
vent_1 = MongoMapperVent.create
|
257
|
+
vent_2 = MongoMapperVent.create
|
258
|
+
dashboard.vents = [vent_1, vent_2]
|
259
|
+
dashboard.save
|
260
|
+
assert_set_equal [vent_1, vent_2], MongoMapperDashboard.find(dashboard.id).vents
|
261
|
+
|
262
|
+
dashboard.vents.clear
|
263
|
+
dashboard.save
|
264
|
+
assert_set_equal [], MongoMapperDashboard.find(dashboard.id).vents
|
265
|
+
assert_not_nil MongoMapperVent.find(vent_1.id)
|
266
|
+
assert_not_nil MongoMapperVent.find(vent_2.id)
|
267
|
+
end
|
268
|
+
|
269
|
+
should "delete the associated object and issue callbacks if association is configured to :destroy dependents" do
|
270
|
+
wheel_1 = MongoMapperWheel.create
|
271
|
+
wheel_2 = MongoMapperWheel.create
|
272
|
+
@new_car.mongo_mapper_wheels = [wheel_1, wheel_2]
|
273
|
+
@new_car.save
|
274
|
+
assert_set_equal [wheel_1, wheel_2], ActiveRecordCar.find(@new_car.id).mongo_mapper_wheels
|
275
|
+
|
276
|
+
@new_car.mongo_mapper_wheels.clear
|
277
|
+
@new_car.save
|
278
|
+
assert_set_equal [], ActiveRecordCar.find(@new_car.id).mongo_mapper_wheels
|
279
|
+
assert_nil MongoMapperWheel._t_find(wheel_1.id)
|
280
|
+
assert_nil MongoMapperWheel._t_find(wheel_2.id)
|
281
|
+
end
|
282
|
+
|
283
|
+
should "delete the associated object without issuing callbacks if association is configured to :delete_all dependents" do
|
284
|
+
@new_car.couch_rest_doors.clear
|
285
|
+
@new_car.save
|
286
|
+
assert_set_equal [], ActiveRecordCar.find(@new_car.id).couch_rest_doors
|
287
|
+
assert_nil CouchRestDoor._t_find(@door_1.id)
|
288
|
+
assert_nil CouchRestDoor._t_find(@door_2.id)
|
289
|
+
assert_nil CouchRestDoor._t_find(@door_3.id)
|
290
|
+
end
|
291
|
+
end
|
107
292
|
end
|
108
293
|
end
|
109
294
|
|