datamapper-dm-core 0.9.11 → 0.10.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.
Files changed (192) hide show
  1. data/.autotest +17 -14
  2. data/.gitignore +3 -1
  3. data/FAQ +6 -5
  4. data/History.txt +5 -39
  5. data/Manifest.txt +67 -76
  6. data/QUICKLINKS +1 -1
  7. data/README.txt +21 -15
  8. data/Rakefile +16 -15
  9. data/SPECS +2 -29
  10. data/TODO +1 -1
  11. data/dm-core.gemspec +11 -15
  12. data/lib/dm-core/adapters/abstract_adapter.rb +182 -185
  13. data/lib/dm-core/adapters/data_objects_adapter.rb +482 -534
  14. data/lib/dm-core/adapters/in_memory_adapter.rb +90 -69
  15. data/lib/dm-core/adapters/mysql_adapter.rb +22 -115
  16. data/lib/dm-core/adapters/oracle_adapter.rb +249 -0
  17. data/lib/dm-core/adapters/postgres_adapter.rb +7 -173
  18. data/lib/dm-core/adapters/sqlite3_adapter.rb +4 -97
  19. data/lib/dm-core/adapters/yaml_adapter.rb +116 -0
  20. data/lib/dm-core/adapters.rb +135 -16
  21. data/lib/dm-core/associations/many_to_many.rb +372 -90
  22. data/lib/dm-core/associations/many_to_one.rb +220 -73
  23. data/lib/dm-core/associations/one_to_many.rb +319 -255
  24. data/lib/dm-core/associations/one_to_one.rb +66 -53
  25. data/lib/dm-core/associations/relationship.rb +560 -158
  26. data/lib/dm-core/collection.rb +1104 -381
  27. data/lib/dm-core/core_ext/kernel.rb +12 -0
  28. data/lib/dm-core/core_ext/symbol.rb +10 -0
  29. data/lib/dm-core/identity_map.rb +4 -34
  30. data/lib/dm-core/migrations.rb +1283 -0
  31. data/lib/dm-core/model/descendant_set.rb +81 -0
  32. data/lib/dm-core/model/hook.rb +45 -0
  33. data/lib/dm-core/model/is.rb +32 -0
  34. data/lib/dm-core/model/property.rb +248 -0
  35. data/lib/dm-core/model/relationship.rb +335 -0
  36. data/lib/dm-core/model/scope.rb +90 -0
  37. data/lib/dm-core/model.rb +570 -369
  38. data/lib/dm-core/property.rb +753 -280
  39. data/lib/dm-core/property_set.rb +141 -98
  40. data/lib/dm-core/query/conditions/comparison.rb +814 -0
  41. data/lib/dm-core/query/conditions/operation.rb +247 -0
  42. data/lib/dm-core/query/direction.rb +43 -0
  43. data/lib/dm-core/query/operator.rb +42 -0
  44. data/lib/dm-core/query/path.rb +102 -0
  45. data/lib/dm-core/query/sort.rb +45 -0
  46. data/lib/dm-core/query.rb +974 -492
  47. data/lib/dm-core/repository.rb +147 -107
  48. data/lib/dm-core/resource.rb +644 -429
  49. data/lib/dm-core/spec/adapter_shared_spec.rb +294 -0
  50. data/lib/dm-core/spec/data_objects_adapter_shared_spec.rb +106 -0
  51. data/lib/dm-core/support/chainable.rb +20 -0
  52. data/lib/dm-core/support/deprecate.rb +12 -0
  53. data/lib/dm-core/support/equalizer.rb +23 -0
  54. data/lib/dm-core/support/logger.rb +13 -0
  55. data/lib/dm-core/{naming_conventions.rb → support/naming_conventions.rb} +6 -6
  56. data/lib/dm-core/transaction.rb +333 -92
  57. data/lib/dm-core/type.rb +98 -60
  58. data/lib/dm-core/types/boolean.rb +1 -1
  59. data/lib/dm-core/types/discriminator.rb +34 -20
  60. data/lib/dm-core/types/object.rb +7 -4
  61. data/lib/dm-core/types/paranoid_boolean.rb +11 -9
  62. data/lib/dm-core/types/paranoid_datetime.rb +11 -9
  63. data/lib/dm-core/types/serial.rb +3 -3
  64. data/lib/dm-core/types/text.rb +3 -4
  65. data/lib/dm-core/version.rb +1 -1
  66. data/lib/dm-core.rb +106 -110
  67. data/script/performance.rb +102 -109
  68. data/script/profile.rb +169 -38
  69. data/spec/lib/adapter_helpers.rb +105 -0
  70. data/spec/lib/collection_helpers.rb +18 -0
  71. data/spec/lib/counter_adapter.rb +34 -0
  72. data/spec/lib/pending_helpers.rb +27 -0
  73. data/spec/lib/rspec_immediate_feedback_formatter.rb +53 -0
  74. data/spec/public/associations/many_to_many_spec.rb +193 -0
  75. data/spec/public/associations/many_to_one_spec.rb +73 -0
  76. data/spec/public/associations/one_to_many_spec.rb +77 -0
  77. data/spec/public/associations/one_to_one_spec.rb +156 -0
  78. data/spec/public/collection_spec.rb +65 -0
  79. data/spec/public/model/relationship_spec.rb +924 -0
  80. data/spec/public/model_spec.rb +159 -0
  81. data/spec/public/property_spec.rb +829 -0
  82. data/spec/public/resource_spec.rb +71 -0
  83. data/spec/public/sel_spec.rb +44 -0
  84. data/spec/public/setup_spec.rb +145 -0
  85. data/spec/public/shared/association_collection_shared_spec.rb +317 -0
  86. data/spec/public/shared/collection_shared_spec.rb +1723 -0
  87. data/spec/public/shared/finder_shared_spec.rb +1619 -0
  88. data/spec/public/shared/resource_shared_spec.rb +924 -0
  89. data/spec/public/shared/sel_shared_spec.rb +112 -0
  90. data/spec/public/transaction_spec.rb +129 -0
  91. data/spec/public/types/discriminator_spec.rb +130 -0
  92. data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
  93. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +12 -0
  94. data/spec/semipublic/adapters/mysql_adapter_spec.rb +17 -0
  95. data/spec/semipublic/adapters/oracle_adapter_spec.rb +194 -0
  96. data/spec/semipublic/adapters/postgres_adapter_spec.rb +17 -0
  97. data/spec/semipublic/adapters/sqlite3_adapter_spec.rb +17 -0
  98. data/spec/semipublic/adapters/yaml_adapter_spec.rb +12 -0
  99. data/spec/semipublic/associations/many_to_one_spec.rb +53 -0
  100. data/spec/semipublic/associations/relationship_spec.rb +194 -0
  101. data/spec/semipublic/associations_spec.rb +177 -0
  102. data/spec/semipublic/collection_spec.rb +142 -0
  103. data/spec/semipublic/property_spec.rb +61 -0
  104. data/spec/semipublic/query/conditions_spec.rb +528 -0
  105. data/spec/semipublic/query/path_spec.rb +443 -0
  106. data/spec/semipublic/query_spec.rb +2626 -0
  107. data/spec/semipublic/resource_spec.rb +47 -0
  108. data/spec/semipublic/shared/resource_shared_spec.rb +126 -0
  109. data/spec/spec.opts +3 -1
  110. data/spec/spec_helper.rb +80 -57
  111. data/tasks/ci.rb +19 -31
  112. data/tasks/dm.rb +43 -48
  113. data/tasks/doc.rb +8 -11
  114. data/tasks/gemspec.rb +5 -5
  115. data/tasks/hoe.rb +15 -16
  116. data/tasks/install.rb +8 -10
  117. metadata +72 -93
  118. data/lib/dm-core/associations/relationship_chain.rb +0 -81
  119. data/lib/dm-core/associations.rb +0 -207
  120. data/lib/dm-core/auto_migrations.rb +0 -105
  121. data/lib/dm-core/dependency_queue.rb +0 -32
  122. data/lib/dm-core/hook.rb +0 -11
  123. data/lib/dm-core/is.rb +0 -16
  124. data/lib/dm-core/logger.rb +0 -232
  125. data/lib/dm-core/migrations/destructive_migrations.rb +0 -17
  126. data/lib/dm-core/migrator.rb +0 -29
  127. data/lib/dm-core/scope.rb +0 -58
  128. data/lib/dm-core/support/array.rb +0 -13
  129. data/lib/dm-core/support/assertions.rb +0 -8
  130. data/lib/dm-core/support/errors.rb +0 -23
  131. data/lib/dm-core/support/kernel.rb +0 -11
  132. data/lib/dm-core/support/symbol.rb +0 -41
  133. data/lib/dm-core/support.rb +0 -7
  134. data/lib/dm-core/type_map.rb +0 -80
  135. data/lib/dm-core/types.rb +0 -19
  136. data/script/all +0 -4
  137. data/spec/integration/association_spec.rb +0 -1382
  138. data/spec/integration/association_through_spec.rb +0 -203
  139. data/spec/integration/associations/many_to_many_spec.rb +0 -449
  140. data/spec/integration/associations/many_to_one_spec.rb +0 -163
  141. data/spec/integration/associations/one_to_many_spec.rb +0 -188
  142. data/spec/integration/auto_migrations_spec.rb +0 -413
  143. data/spec/integration/collection_spec.rb +0 -1073
  144. data/spec/integration/data_objects_adapter_spec.rb +0 -32
  145. data/spec/integration/dependency_queue_spec.rb +0 -46
  146. data/spec/integration/model_spec.rb +0 -197
  147. data/spec/integration/mysql_adapter_spec.rb +0 -85
  148. data/spec/integration/postgres_adapter_spec.rb +0 -731
  149. data/spec/integration/property_spec.rb +0 -253
  150. data/spec/integration/query_spec.rb +0 -514
  151. data/spec/integration/repository_spec.rb +0 -61
  152. data/spec/integration/resource_spec.rb +0 -513
  153. data/spec/integration/sqlite3_adapter_spec.rb +0 -352
  154. data/spec/integration/sti_spec.rb +0 -273
  155. data/spec/integration/strategic_eager_loading_spec.rb +0 -156
  156. data/spec/integration/transaction_spec.rb +0 -75
  157. data/spec/integration/type_spec.rb +0 -275
  158. data/spec/lib/logging_helper.rb +0 -18
  159. data/spec/lib/mock_adapter.rb +0 -27
  160. data/spec/lib/model_loader.rb +0 -100
  161. data/spec/lib/publicize_methods.rb +0 -28
  162. data/spec/models/content.rb +0 -16
  163. data/spec/models/vehicles.rb +0 -34
  164. data/spec/models/zoo.rb +0 -48
  165. data/spec/unit/adapters/abstract_adapter_spec.rb +0 -133
  166. data/spec/unit/adapters/adapter_shared_spec.rb +0 -15
  167. data/spec/unit/adapters/data_objects_adapter_spec.rb +0 -632
  168. data/spec/unit/adapters/in_memory_adapter_spec.rb +0 -98
  169. data/spec/unit/adapters/postgres_adapter_spec.rb +0 -133
  170. data/spec/unit/associations/many_to_many_spec.rb +0 -32
  171. data/spec/unit/associations/many_to_one_spec.rb +0 -159
  172. data/spec/unit/associations/one_to_many_spec.rb +0 -393
  173. data/spec/unit/associations/one_to_one_spec.rb +0 -7
  174. data/spec/unit/associations/relationship_spec.rb +0 -71
  175. data/spec/unit/associations_spec.rb +0 -242
  176. data/spec/unit/auto_migrations_spec.rb +0 -111
  177. data/spec/unit/collection_spec.rb +0 -182
  178. data/spec/unit/data_mapper_spec.rb +0 -35
  179. data/spec/unit/identity_map_spec.rb +0 -126
  180. data/spec/unit/is_spec.rb +0 -80
  181. data/spec/unit/migrator_spec.rb +0 -33
  182. data/spec/unit/model_spec.rb +0 -321
  183. data/spec/unit/naming_conventions_spec.rb +0 -36
  184. data/spec/unit/property_set_spec.rb +0 -90
  185. data/spec/unit/property_spec.rb +0 -753
  186. data/spec/unit/query_spec.rb +0 -571
  187. data/spec/unit/repository_spec.rb +0 -93
  188. data/spec/unit/resource_spec.rb +0 -649
  189. data/spec/unit/scope_spec.rb +0 -142
  190. data/spec/unit/transaction_spec.rb +0 -493
  191. data/spec/unit/type_map_spec.rb +0 -114
  192. data/spec/unit/type_spec.rb +0 -119
@@ -0,0 +1,81 @@
1
+ module DataMapper
2
+ module Model
3
+ class DescendantSet
4
+ include Enumerable
5
+
6
+ # Append a model as a descendant
7
+ #
8
+ # @param [Model] model
9
+ # the descendant model
10
+ #
11
+ # @return [DescendantSet]
12
+ # self
13
+ #
14
+ # @api private
15
+ def <<(model)
16
+ @descendants << model unless @descendants.include?(model)
17
+ @ancestors << model if @ancestors
18
+ self
19
+ end
20
+
21
+ # Iterate over each descendant
22
+ #
23
+ # @yield [model]
24
+ # iterate over each descendant
25
+ # @yieldparam [Model] model
26
+ # the descendant model
27
+ #
28
+ # @return [DescendantSet]
29
+ # self
30
+ #
31
+ # @api private
32
+ def each
33
+ @descendants.each { |model| yield model }
34
+ self
35
+ end
36
+
37
+ # Remove a descendant
38
+ #
39
+ # Also removed the descendant from the ancestors.
40
+ #
41
+ # @param [Model] model
42
+ # the model to remove
43
+ #
44
+ # @return [Model, NilClass]
45
+ # the model is return if it is a descendant
46
+ #
47
+ # @api private
48
+ def delete(model)
49
+ @ancestors.delete(model) if @ancestors
50
+ @descendants.delete(model)
51
+ end
52
+
53
+ # Return an Array representation of descendants
54
+ #
55
+ # @return [Array]
56
+ # the descendants
57
+ #
58
+ # @api private
59
+ def to_ary
60
+ @descendants.dup
61
+ end
62
+
63
+ private
64
+
65
+ # Initialize a DescendantSet instance
66
+ #
67
+ # @param [Model] model
68
+ # the base model
69
+ # @param [DescendantSet] ancestors
70
+ # the ancestors to notify when a descendant is added
71
+ #
72
+ # @api private
73
+ def initialize(model = nil, ancestors = nil)
74
+ @descendants = []
75
+ @ancestors = ancestors
76
+
77
+ @descendants << model if model
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,45 @@
1
+ module DataMapper
2
+ module Model
3
+ module Hook
4
+ Model.append_inclusions self
5
+
6
+ def self.included(model)
7
+ model.send(:include, Extlib::Hook)
8
+ model.extend Methods
9
+ model.register_instance_hooks :create_hook, :update_hook, :destroy
10
+ end
11
+
12
+ module Methods
13
+ # TODO: document
14
+ # @api public
15
+ def before(target_method, *args, &block)
16
+ remap_target_method(target_method).each do |target_method|
17
+ super(target_method, *args, &block)
18
+ end
19
+ end
20
+
21
+ # TODO: document
22
+ # @api public
23
+ def after(target_method, *args, &block)
24
+ remap_target_method(target_method).each do |target_method|
25
+ super(target_method, *args, &block)
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ # TODO: document
32
+ # @api private
33
+ def remap_target_method(target_method)
34
+ case target_method
35
+ when :create then [ :create_hook ]
36
+ when :update then [ :update_hook ]
37
+ when :save then [ :create_hook, :update_hook ]
38
+ else [ target_method ]
39
+ end
40
+ end
41
+ end
42
+
43
+ end # module Hook
44
+ end # module Model
45
+ end # module DataMapper
@@ -0,0 +1,32 @@
1
+ module DataMapper
2
+ module Model
3
+ # Module that provides a common way for plugin authors
4
+ # to implement "is ... " traits (object behaviors that can be shared)
5
+ module Is
6
+ # A common interface to activate plugins for a resource. For instance:
7
+ #
8
+ # class Widget
9
+ # include DataMapper::Resource
10
+ #
11
+ # is :list
12
+ # end
13
+ #
14
+ # adds list item behavior to the model. Plugin that wants to conform
15
+ # to "is API" of DataMapper must supply is_+behavior name+ method,
16
+ # for example above it would be is_list.
17
+ #
18
+ # @api public
19
+ def is(plugin, *args, &block)
20
+ generator_method = "is_#{plugin}".to_sym
21
+
22
+ if respond_to?(generator_method)
23
+ send(generator_method, *args, &block)
24
+ else
25
+ raise PluginNotFoundError, "could not find plugin named #{plugin}"
26
+ end
27
+ end
28
+ end # module Is
29
+
30
+ include Is
31
+ end # module Model
32
+ end # module DataMapper
@@ -0,0 +1,248 @@
1
+ # TODO: move paranoid property concerns to a ParanoidModel that is mixed
2
+ # into Model when a Paranoid property is used
3
+
4
+ # TODO: update Model#respond_to? to return true if method_method missing
5
+ # would handle the message
6
+
7
+ module DataMapper
8
+ module Model
9
+ module Property
10
+ Model.append_extensions self
11
+
12
+ extend Chainable
13
+
14
+ def self.extended(model)
15
+ model.instance_variable_set(:@properties, {})
16
+ model.instance_variable_set(:@field_naming_conventions, {})
17
+ model.instance_variable_set(:@paranoid_properties, {})
18
+ end
19
+
20
+ chainable do
21
+ def inherited(model)
22
+ model.instance_variable_set(:@properties, {})
23
+ model.instance_variable_set(:@field_naming_conventions, @field_naming_conventions.dup)
24
+ model.instance_variable_set(:@paranoid_properties, @paranoid_properties.dup)
25
+
26
+ @properties.each do |repository_name, properties|
27
+ model_properties = model.properties(repository_name)
28
+ properties.each { |property| model_properties << property }
29
+ end
30
+
31
+ super
32
+ end
33
+ end
34
+
35
+ # Defines a Property on the Resource
36
+ #
37
+ # @param [Symbol] name
38
+ # the name for which to call this property
39
+ # @param [Type] type
40
+ # the type to define this property ass
41
+ # @param [Hash(Symbol => String)] options
42
+ # a hash of available options
43
+ #
44
+ # @return [Property]
45
+ # the created Property
46
+ #
47
+ # @see Property
48
+ #
49
+ # @api public
50
+ def property(name, type, options = {})
51
+ property = DataMapper::Property.new(self, name, type, options)
52
+
53
+ properties(repository_name) << property
54
+
55
+ # Add property to the other mappings as well if this is for the default
56
+ # repository.
57
+ if repository_name == default_repository_name
58
+ @properties.except(repository_name).each do |repository_name, properties|
59
+ next if properties.named?(name)
60
+
61
+ # make sure the property is created within the correct repository scope
62
+ DataMapper.repository(repository_name) do
63
+ properties << DataMapper::Property.new(self, name, type, options)
64
+ end
65
+ end
66
+ end
67
+
68
+ # Add the property to the lazy_loads set for this resources repository
69
+ # only.
70
+ # TODO Is this right or should we add the lazy contexts to all
71
+ # repositories?
72
+ if property.lazy?
73
+ context = options.fetch(:lazy, :default)
74
+ context = :default if context == true
75
+
76
+ properties = properties(repository_name)
77
+
78
+ Array(context).each do |context|
79
+ properties.lazy_context(context) << self
80
+ end
81
+ end
82
+
83
+ # add the property to the child classes only if the property was
84
+ # added after the child classes' properties have been copied from
85
+ # the parent
86
+ descendants.each do |descendant|
87
+ next if descendant.properties(repository_name).named?(name)
88
+ descendant.properties(repository_name) << property
89
+ end
90
+
91
+ create_reader_for(property)
92
+ create_writer_for(property)
93
+
94
+ property
95
+ end
96
+
97
+ # Gets a list of all properties that have been defined on this Model in
98
+ # the requested repository
99
+ #
100
+ # @param [Symbol, String] repository_name
101
+ # The name of the repository to use. Uses the default Repository
102
+ # if none is specified.
103
+ #
104
+ # @return [Array]
105
+ # A list of Properties defined on this Model in the given Repository
106
+ #
107
+ # @api public
108
+ def properties(repository_name = default_repository_name)
109
+ # TODO: create PropertySet#copy that will copy the properties, but assign the
110
+ # new Relationship objects to a supplied repository and model. dup does not really
111
+ # do what is needed
112
+
113
+ @properties[repository_name] ||= if repository_name == default_repository_name
114
+ PropertySet.new
115
+ else
116
+ properties(default_repository_name).dup
117
+ end
118
+ end
119
+
120
+ # Gets the list of key fields for this Model in +repository_name+
121
+ #
122
+ # @param [String] repository_name
123
+ # The name of the Repository for which the key is to be reported
124
+ #
125
+ # @return [Array]
126
+ # The list of key fields for this Model in +repository_name+
127
+ #
128
+ # @api public
129
+ def key(repository_name = default_repository_name)
130
+ properties(repository_name).key
131
+ end
132
+
133
+ # TODO: document
134
+ # @api public
135
+ def serial(repository_name = default_repository_name)
136
+ key(repository_name).detect { |property| property.serial? }
137
+ end
138
+
139
+ # Gets the field naming conventions for this resource in the given Repository
140
+ #
141
+ # @param [String, Symbol] repository_name
142
+ # the name of the Repository for which the field naming convention
143
+ # will be retrieved
144
+ #
145
+ # @return [#call]
146
+ # The naming convention for the given Repository
147
+ #
148
+ # @api public
149
+ def field_naming_convention(repository_name = default_storage_name)
150
+ @field_naming_conventions[repository_name] ||= repository(repository_name).adapter.field_naming_convention
151
+ end
152
+
153
+ # TODO: document
154
+ # @api private
155
+ def properties_with_subclasses(repository_name = default_repository_name)
156
+ properties = PropertySet.new
157
+
158
+ descendants.each do |model|
159
+ model.properties(repository_name).each do |property|
160
+ properties << property unless properties.named?(property.name)
161
+ end
162
+ end
163
+
164
+ properties
165
+ end
166
+
167
+ # TODO: document
168
+ # @api private
169
+ def paranoid_properties
170
+ @paranoid_properties
171
+ end
172
+
173
+ # TODO: document
174
+ # @api private
175
+ def set_paranoid_property(name, &block)
176
+ paranoid_properties[name] = block
177
+ end
178
+
179
+ # TODO: document
180
+ # @api private
181
+ def key_conditions(repository, key)
182
+ self.key(repository.name).zip(key).to_hash
183
+ end
184
+
185
+ private
186
+
187
+ # defines the reader method for the property
188
+ #
189
+ # @api private
190
+ def create_reader_for(property)
191
+ name = property.name.to_s
192
+ reader_visibility = property.reader_visibility
193
+ instance_variable_name = property.instance_variable_name
194
+ primitive = property.primitive
195
+
196
+ unless resource_method_defined?(name)
197
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
198
+ #{reader_visibility}
199
+ def #{name}
200
+ return #{instance_variable_name} if defined?(#{instance_variable_name})
201
+ #{instance_variable_name} = properties[#{name.inspect}].get(self)
202
+ end
203
+ RUBY
204
+ end
205
+
206
+ boolean_reader_name = "#{name}?"
207
+
208
+ if primitive == TrueClass && !resource_method_defined?(boolean_reader_name)
209
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
210
+ #{reader_visibility}
211
+ alias #{boolean_reader_name} #{name}
212
+ RUBY
213
+ end
214
+ end
215
+
216
+ # defines the setter for the property
217
+ #
218
+ # @api private
219
+ def create_writer_for(property)
220
+ name = property.name
221
+ writer_visibility = property.writer_visibility
222
+
223
+ writer_name = "#{name}="
224
+
225
+ return if resource_method_defined?(writer_name)
226
+
227
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
228
+ #{writer_visibility}
229
+ def #{writer_name}(value)
230
+ properties[#{name.inspect}].set(self, value)
231
+ end
232
+ RUBY
233
+ end
234
+
235
+ chainable do
236
+ # TODO: document
237
+ # @api public
238
+ def method_missing(method, *args, &block)
239
+ if property = properties(repository_name)[method]
240
+ return property
241
+ end
242
+
243
+ super
244
+ end
245
+ end
246
+ end # module Property
247
+ end # module Model
248
+ end # module DataMapper