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
@@ -0,0 +1,36 @@
|
|
1
|
+
module Tenacity
|
2
|
+
module OrmExt
|
3
|
+
module Helpers #:nodoc:
|
4
|
+
|
5
|
+
def id_class_for(association)
|
6
|
+
if association.polymorphic?
|
7
|
+
String
|
8
|
+
elsif association.type == :belongs_to
|
9
|
+
association.source._t_id_type
|
10
|
+
else
|
11
|
+
association.associate_class._t_id_type
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def _t_serialize_ids(ids)
|
16
|
+
if ids.respond_to?(:map)
|
17
|
+
ids.map { |id| _t_serialize(id) }
|
18
|
+
else
|
19
|
+
_t_serialize(ids)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def _t_serialize_id_for_sql(id)
|
24
|
+
return id if id.nil?
|
25
|
+
|
26
|
+
serialized_id = _t_serialize(id)
|
27
|
+
if serialized_id.class == String
|
28
|
+
"'#{serialized_id}'"
|
29
|
+
else
|
30
|
+
serialized_id
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,105 +1,123 @@
|
|
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
|
-
def self.setup(model) #:nodoc:
|
35
|
-
require 'mongo_mapper'
|
36
|
-
if model.included_modules.include?(::MongoMapper::Document)
|
37
|
-
model.send :include, MongoMapper::InstanceMethods
|
38
|
-
model.extend MongoMapper::ClassMethods
|
39
|
-
end
|
40
|
-
rescue LoadError
|
41
|
-
# MongoMapper not available
|
42
|
-
end
|
2
|
+
module OrmExt
|
3
|
+
# Tenacity relationships on MongoMapper objects require no special keys
|
4
|
+
# defined on the object. Tenacity will define the keys that it needs
|
5
|
+
# to support the relationships. Take the following class for example:
|
6
|
+
#
|
7
|
+
# class Car < ActiveRecord::Base
|
8
|
+
# include MongoMapper::Document
|
9
|
+
# include Tenacity
|
10
|
+
#
|
11
|
+
# t_has_many :wheels
|
12
|
+
# t_has_one :dashboard
|
13
|
+
# t_belongs_to :driver
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# == t_belongs_to
|
17
|
+
#
|
18
|
+
# The +t_belongs_to+ association will define a key named after the association.
|
19
|
+
# The example above will create a key named <tt>:driver_id</tt>
|
20
|
+
#
|
21
|
+
#
|
22
|
+
# == t_has_one
|
23
|
+
#
|
24
|
+
# The +t_has_one+ association will not define any new keys on the object, since
|
25
|
+
# the associated object holds the foreign key.
|
26
|
+
#
|
27
|
+
#
|
28
|
+
# == t_has_many
|
29
|
+
#
|
30
|
+
# The +t_has_many+ association will define a key named after the association.
|
31
|
+
# The example above will create a key named <tt>:wheels_ids</tt>
|
32
|
+
#
|
33
|
+
module MongoMapper
|
43
34
|
|
44
|
-
|
45
|
-
|
46
|
-
|
35
|
+
def self.setup(model) #:nodoc:
|
36
|
+
require 'mongo_mapper'
|
37
|
+
if model.included_modules.include?(::MongoMapper::Document)
|
38
|
+
model.send :include, MongoMapper::InstanceMethods
|
39
|
+
model.extend MongoMapper::ClassMethods
|
40
|
+
end
|
41
|
+
rescue LoadError
|
42
|
+
# MongoMapper not available
|
47
43
|
end
|
48
44
|
|
49
|
-
|
50
|
-
|
51
|
-
end
|
45
|
+
module ClassMethods #:nodoc:
|
46
|
+
include Tenacity::OrmExt::Helpers
|
52
47
|
|
53
|
-
|
54
|
-
|
55
|
-
|
48
|
+
def _t_id_type
|
49
|
+
String
|
50
|
+
end
|
56
51
|
|
57
|
-
|
58
|
-
|
59
|
-
|
52
|
+
def _t_find(id)
|
53
|
+
find(_t_serialize(id))
|
54
|
+
end
|
60
55
|
|
61
|
-
|
62
|
-
|
63
|
-
key association.foreign_keys_property, Array
|
64
|
-
after_save { |record| _t_save_associates(record, association) }
|
56
|
+
def _t_find_bulk(ids=[])
|
57
|
+
find(_t_serialize_ids(ids))
|
65
58
|
end
|
66
|
-
end
|
67
59
|
|
68
|
-
|
69
|
-
|
70
|
-
key association.foreign_key, String
|
71
|
-
before_save { |record| _t_stringify_belongs_to_value(record, association) }
|
60
|
+
def _t_find_first_by_associate(property, id)
|
61
|
+
first(property => _t_serialize(id))
|
72
62
|
end
|
73
|
-
end
|
74
63
|
|
75
|
-
|
76
|
-
|
77
|
-
destroy(ids)
|
78
|
-
else
|
79
|
-
delete(ids)
|
64
|
+
def _t_find_all_by_associate(property, id)
|
65
|
+
all(property => _t_serialize(id))
|
80
66
|
end
|
81
|
-
end
|
82
|
-
end
|
83
67
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
rescue ::MongoMapper::DocumentNotFound
|
88
|
-
nil
|
89
|
-
end
|
68
|
+
def _t_initialize_tenacity
|
69
|
+
after_save { |record| record._t_save_autosave_associations }
|
70
|
+
end
|
90
71
|
|
91
|
-
|
92
|
-
|
93
|
-
|
72
|
+
def _t_initialize_has_one_association(association)
|
73
|
+
after_destroy { |record| record._t_cleanup_has_one_association(association) }
|
74
|
+
end
|
75
|
+
|
76
|
+
def _t_initialize_has_many_association(association)
|
77
|
+
unless self.respond_to?(association.foreign_keys_property)
|
78
|
+
key association.foreign_keys_property, Array
|
79
|
+
after_save { |record| _t_save_associates(record, association) }
|
80
|
+
after_destroy { |record| record._t_cleanup_has_many_association(association) }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def _t_initialize_belongs_to_association(association)
|
85
|
+
unless self.respond_to?(association.foreign_key)
|
86
|
+
key association.foreign_key, id_class_for(association)
|
87
|
+
key association.polymorphic_type, String if association.polymorphic?
|
88
|
+
after_destroy { |record| record._t_cleanup_belongs_to_association(association) }
|
89
|
+
end
|
90
|
+
end
|
94
91
|
|
95
|
-
|
96
|
-
|
92
|
+
def _t_delete(ids, run_callbacks=true)
|
93
|
+
if run_callbacks
|
94
|
+
destroy(_t_serialize_ids(ids))
|
95
|
+
else
|
96
|
+
delete(_t_serialize_ids(ids))
|
97
|
+
end
|
98
|
+
end
|
97
99
|
end
|
98
100
|
|
99
|
-
|
100
|
-
|
101
|
+
module InstanceMethods #:nodoc:
|
102
|
+
def _t_reload
|
103
|
+
reload
|
104
|
+
rescue ::MongoMapper::DocumentNotFound
|
105
|
+
nil
|
106
|
+
end
|
107
|
+
|
108
|
+
def _t_associate_many(association, associate_ids)
|
109
|
+
self.send(association.foreign_keys_property + '=', associate_ids)
|
110
|
+
end
|
111
|
+
|
112
|
+
def _t_get_associate_ids(association)
|
113
|
+
self.send(association.foreign_keys_property)
|
114
|
+
end
|
115
|
+
|
116
|
+
def _t_clear_associates(association)
|
117
|
+
self.send(association.foreign_keys_property + '=', [])
|
118
|
+
end
|
101
119
|
end
|
102
|
-
end
|
103
120
|
|
121
|
+
end
|
104
122
|
end
|
105
123
|
end
|
@@ -1,108 +1,127 @@
|
|
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
|
-
def self.setup(model) #:nodoc:
|
35
|
-
require 'mongoid'
|
36
|
-
if model.included_modules.include?(::Mongoid::Document)
|
37
|
-
model.send :include, Mongoid::InstanceMethods
|
38
|
-
model.extend Mongoid::ClassMethods
|
39
|
-
end
|
40
|
-
rescue LoadError
|
41
|
-
# Mongoid not available
|
42
|
-
end
|
2
|
+
module OrmExt
|
3
|
+
# Tenacity relationships on Mongoid objects require no special keys
|
4
|
+
# defined on the object. Tenacity will define the keys that it needs
|
5
|
+
# to support the relationships. Take the following class for example:
|
6
|
+
#
|
7
|
+
# class Car
|
8
|
+
# include Mongoid::Document
|
9
|
+
# include Tenacity
|
10
|
+
#
|
11
|
+
# t_has_many :wheels
|
12
|
+
# t_has_one :dashboard
|
13
|
+
# t_belongs_to :driver
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# == t_belongs_to
|
17
|
+
#
|
18
|
+
# The +t_belongs_to+ association will define a key named after the association.
|
19
|
+
# The example above will create a key named <tt>:driver_id</tt>
|
20
|
+
#
|
21
|
+
#
|
22
|
+
# == t_has_one
|
23
|
+
#
|
24
|
+
# The +t_has_one+ association will not define any new keys on the object, since
|
25
|
+
# the associated object holds the foreign key.
|
26
|
+
#
|
27
|
+
#
|
28
|
+
# == t_has_many
|
29
|
+
#
|
30
|
+
# The +t_has_many+ association will define a key named after the association.
|
31
|
+
# The example above will create a key named <tt>:wheels_ids</tt>
|
32
|
+
#
|
33
|
+
module Mongoid
|
43
34
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
35
|
+
def self.setup(model) #:nodoc:
|
36
|
+
require 'mongoid'
|
37
|
+
if model.included_modules.include?(::Mongoid::Document)
|
38
|
+
model.send :include, Mongoid::InstanceMethods
|
39
|
+
model.extend Mongoid::ClassMethods
|
40
|
+
end
|
41
|
+
rescue LoadError
|
42
|
+
# Mongoid not available
|
49
43
|
end
|
50
44
|
|
51
|
-
|
52
|
-
|
53
|
-
rescue ::Mongoid::Errors::DocumentNotFound
|
54
|
-
[]
|
55
|
-
end
|
45
|
+
module ClassMethods #:nodoc:
|
46
|
+
include Tenacity::OrmExt::Helpers
|
56
47
|
|
57
|
-
|
58
|
-
|
59
|
-
|
48
|
+
def _t_id_type
|
49
|
+
String
|
50
|
+
end
|
60
51
|
|
61
|
-
|
62
|
-
|
63
|
-
|
52
|
+
def _t_find(id)
|
53
|
+
(id.nil? || id.to_s.strip == "") ? nil : find(_t_serialize(id))
|
54
|
+
rescue ::Mongoid::Errors::DocumentNotFound
|
55
|
+
nil
|
56
|
+
end
|
64
57
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
58
|
+
def _t_find_bulk(ids)
|
59
|
+
docs = find(_t_serialize_ids(ids))
|
60
|
+
docs.respond_to?(:each) ? docs : [docs]
|
61
|
+
rescue ::Mongoid::Errors::DocumentNotFound
|
62
|
+
[]
|
69
63
|
end
|
70
|
-
end
|
71
64
|
|
72
|
-
|
73
|
-
|
74
|
-
field association.foreign_key, :type => String
|
75
|
-
before_save { |record| self.class._t_stringify_belongs_to_value(record, association) }
|
65
|
+
def _t_find_first_by_associate(property, id)
|
66
|
+
find(:first, :conditions => { property => _t_serialize(id) })
|
76
67
|
end
|
77
|
-
end
|
78
68
|
|
79
|
-
|
80
|
-
|
81
|
-
if run_callbacks
|
82
|
-
docs.each { |doc| doc.destroy }
|
83
|
-
else
|
84
|
-
docs.each { |doc| doc.delete }
|
69
|
+
def _t_find_all_by_associate(property, id)
|
70
|
+
find(:all, :conditions => { property => _t_serialize(id) })
|
85
71
|
end
|
86
|
-
end
|
87
|
-
end
|
88
72
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
end
|
73
|
+
def _t_initialize_tenacity
|
74
|
+
after_save { |record| record._t_save_autosave_associations }
|
75
|
+
end
|
93
76
|
|
94
|
-
|
95
|
-
|
96
|
-
|
77
|
+
def _t_initialize_has_one_association(association)
|
78
|
+
after_destroy { |record| record._t_cleanup_has_one_association(association) }
|
79
|
+
end
|
80
|
+
|
81
|
+
def _t_initialize_has_many_association(association)
|
82
|
+
unless self.respond_to?(association.foreign_keys_property)
|
83
|
+
field association.foreign_keys_property, :type => Array
|
84
|
+
after_save { |record| self.class._t_save_associates(record, association) }
|
85
|
+
after_destroy { |record| record._t_cleanup_has_many_association(association) }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def _t_initialize_belongs_to_association(association)
|
90
|
+
unless self.respond_to?(association.foreign_key)
|
91
|
+
field association.foreign_key, :type => id_class_for(association)
|
92
|
+
field association.polymorphic_type, :type => String if association.polymorphic?
|
93
|
+
after_destroy { |record| record._t_cleanup_belongs_to_association(association) }
|
94
|
+
end
|
95
|
+
end
|
97
96
|
|
98
|
-
|
99
|
-
|
97
|
+
def _t_delete(ids, run_callbacks=true)
|
98
|
+
docs = _t_find_bulk(ids)
|
99
|
+
if run_callbacks
|
100
|
+
docs.each { |doc| doc.destroy }
|
101
|
+
else
|
102
|
+
docs.each { |doc| doc.delete }
|
103
|
+
end
|
104
|
+
end
|
100
105
|
end
|
101
106
|
|
102
|
-
|
103
|
-
|
107
|
+
module InstanceMethods #:nodoc:
|
108
|
+
def _t_reload
|
109
|
+
reload
|
110
|
+
end
|
111
|
+
|
112
|
+
def _t_associate_many(association, associate_ids)
|
113
|
+
self.send(association.foreign_keys_property + '=', associate_ids)
|
114
|
+
end
|
115
|
+
|
116
|
+
def _t_get_associate_ids(association)
|
117
|
+
self.send(association.foreign_keys_property)
|
118
|
+
end
|
119
|
+
|
120
|
+
def _t_clear_associates(association)
|
121
|
+
self.send(association.foreign_keys_property + '=', [])
|
122
|
+
end
|
104
123
|
end
|
105
|
-
end
|
106
124
|
|
125
|
+
end
|
107
126
|
end
|
108
127
|
end
|