mack-data_mapper 0.8.1 → 0.8.2

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 (166) hide show
  1. data/lib/gems/addressable-2.0.0/lib/addressable/idna.rb +4867 -0
  2. data/lib/gems/addressable-2.0.0/lib/addressable/uri.rb +2469 -0
  3. data/lib/gems/addressable-2.0.0/lib/addressable/version.rb +35 -0
  4. data/lib/gems/dm-aggregates-0.9.7/lib/dm-aggregates/adapters/data_objects_adapter.rb +85 -0
  5. data/lib/gems/dm-aggregates-0.9.7/lib/dm-aggregates/aggregate_functions.rb +201 -0
  6. data/lib/gems/dm-aggregates-0.9.7/lib/dm-aggregates/collection.rb +11 -0
  7. data/lib/gems/dm-aggregates-0.9.7/lib/dm-aggregates/model.rb +11 -0
  8. data/lib/gems/dm-aggregates-0.9.7/lib/dm-aggregates/repository.rb +7 -0
  9. data/lib/gems/dm-aggregates-0.9.7/lib/dm-aggregates/support/symbol.rb +21 -0
  10. data/lib/gems/dm-aggregates-0.9.7/lib/dm-aggregates/version.rb +7 -0
  11. data/lib/gems/dm-aggregates-0.9.7/lib/dm-aggregates.rb +15 -0
  12. data/lib/gems/dm-core-0.9.7/lib/dm-core/adapters/abstract_adapter.rb +209 -0
  13. data/lib/gems/dm-core-0.9.7/lib/dm-core/adapters/data_objects_adapter.rb +709 -0
  14. data/lib/gems/dm-core-0.9.7/lib/dm-core/adapters/in_memory_adapter.rb +87 -0
  15. data/lib/gems/dm-core-0.9.7/lib/dm-core/adapters/mysql_adapter.rb +136 -0
  16. data/lib/gems/dm-core-0.9.7/lib/dm-core/adapters/postgres_adapter.rb +188 -0
  17. data/lib/gems/dm-core-0.9.7/lib/dm-core/adapters/sqlite3_adapter.rb +105 -0
  18. data/lib/gems/dm-core-0.9.7/lib/dm-core/adapters.rb +22 -0
  19. data/lib/gems/dm-core-0.9.7/lib/dm-core/associations/many_to_many.rb +147 -0
  20. data/lib/gems/dm-core-0.9.7/lib/dm-core/associations/many_to_one.rb +107 -0
  21. data/lib/gems/dm-core-0.9.7/lib/dm-core/associations/one_to_many.rb +318 -0
  22. data/lib/gems/dm-core-0.9.7/lib/dm-core/associations/one_to_one.rb +61 -0
  23. data/lib/gems/dm-core-0.9.7/lib/dm-core/associations/relationship.rb +223 -0
  24. data/lib/gems/dm-core-0.9.7/lib/dm-core/associations/relationship_chain.rb +81 -0
  25. data/lib/gems/dm-core-0.9.7/lib/dm-core/associations.rb +200 -0
  26. data/lib/gems/dm-core-0.9.7/lib/dm-core/auto_migrations.rb +105 -0
  27. data/lib/gems/dm-core-0.9.7/lib/dm-core/collection.rb +642 -0
  28. data/lib/gems/dm-core-0.9.7/lib/dm-core/dependency_queue.rb +32 -0
  29. data/lib/gems/dm-core-0.9.7/lib/dm-core/hook.rb +11 -0
  30. data/lib/gems/dm-core-0.9.7/lib/dm-core/identity_map.rb +42 -0
  31. data/lib/gems/dm-core-0.9.7/lib/dm-core/is.rb +16 -0
  32. data/lib/gems/dm-core-0.9.7/lib/dm-core/logger.rb +232 -0
  33. data/lib/gems/dm-core-0.9.7/lib/dm-core/migrations/destructive_migrations.rb +17 -0
  34. data/lib/gems/dm-core-0.9.7/lib/dm-core/migrator.rb +29 -0
  35. data/lib/gems/dm-core-0.9.7/lib/dm-core/model.rb +488 -0
  36. data/lib/gems/dm-core-0.9.7/lib/dm-core/naming_conventions.rb +84 -0
  37. data/lib/gems/dm-core-0.9.7/lib/dm-core/property.rb +663 -0
  38. data/lib/gems/dm-core-0.9.7/lib/dm-core/property_set.rb +169 -0
  39. data/lib/gems/dm-core-0.9.7/lib/dm-core/query.rb +628 -0
  40. data/lib/gems/dm-core-0.9.7/lib/dm-core/repository.rb +159 -0
  41. data/lib/gems/dm-core-0.9.7/lib/dm-core/resource.rb +637 -0
  42. data/lib/gems/dm-core-0.9.7/lib/dm-core/scope.rb +58 -0
  43. data/lib/gems/dm-core-0.9.7/lib/dm-core/support/array.rb +13 -0
  44. data/lib/gems/dm-core-0.9.7/lib/dm-core/support/assertions.rb +8 -0
  45. data/lib/gems/dm-core-0.9.7/lib/dm-core/support/errors.rb +23 -0
  46. data/lib/gems/dm-core-0.9.7/lib/dm-core/support/kernel.rb +11 -0
  47. data/lib/gems/dm-core-0.9.7/lib/dm-core/support/symbol.rb +41 -0
  48. data/lib/gems/dm-core-0.9.7/lib/dm-core/support.rb +7 -0
  49. data/lib/gems/dm-core-0.9.7/lib/dm-core/transaction.rb +267 -0
  50. data/lib/gems/dm-core-0.9.7/lib/dm-core/type.rb +160 -0
  51. data/lib/gems/dm-core-0.9.7/lib/dm-core/type_map.rb +80 -0
  52. data/lib/gems/dm-core-0.9.7/lib/dm-core/types/boolean.rb +7 -0
  53. data/lib/gems/dm-core-0.9.7/lib/dm-core/types/discriminator.rb +34 -0
  54. data/lib/gems/dm-core-0.9.7/lib/dm-core/types/object.rb +24 -0
  55. data/lib/gems/dm-core-0.9.7/lib/dm-core/types/paranoid_boolean.rb +34 -0
  56. data/lib/gems/dm-core-0.9.7/lib/dm-core/types/paranoid_datetime.rb +33 -0
  57. data/lib/gems/dm-core-0.9.7/lib/dm-core/types/serial.rb +9 -0
  58. data/lib/gems/dm-core-0.9.7/lib/dm-core/types/text.rb +10 -0
  59. data/lib/gems/dm-core-0.9.7/lib/dm-core/types.rb +19 -0
  60. data/lib/gems/dm-core-0.9.7/lib/dm-core/version.rb +3 -0
  61. data/lib/gems/dm-core-0.9.7/lib/dm-core.rb +217 -0
  62. data/lib/gems/dm-core-0.9.7/script/all +5 -0
  63. data/lib/gems/dm-core-0.9.7/script/performance.rb +284 -0
  64. data/lib/gems/dm-core-0.9.7/script/profile.rb +87 -0
  65. data/lib/gems/dm-migrations-0.9.7/lib/dm-migrations/version.rb +5 -0
  66. data/lib/gems/dm-migrations-0.9.7/lib/dm-migrations.rb +1 -0
  67. data/lib/gems/dm-migrations-0.9.7/lib/migration.rb +215 -0
  68. data/lib/gems/dm-migrations-0.9.7/lib/migration_runner.rb +88 -0
  69. data/lib/gems/dm-migrations-0.9.7/lib/spec/example/migration_example_group.rb +73 -0
  70. data/lib/gems/dm-migrations-0.9.7/lib/spec/matchers/migration_matchers.rb +107 -0
  71. data/lib/gems/dm-migrations-0.9.7/lib/sql/column.rb +9 -0
  72. data/lib/gems/dm-migrations-0.9.7/lib/sql/mysql.rb +52 -0
  73. data/lib/gems/dm-migrations-0.9.7/lib/sql/postgresql.rb +78 -0
  74. data/lib/gems/dm-migrations-0.9.7/lib/sql/sqlite3.rb +43 -0
  75. data/lib/gems/dm-migrations-0.9.7/lib/sql/table.rb +19 -0
  76. data/lib/gems/dm-migrations-0.9.7/lib/sql/table_creator.rb +81 -0
  77. data/lib/gems/dm-migrations-0.9.7/lib/sql/table_modifier.rb +53 -0
  78. data/lib/gems/dm-migrations-0.9.7/lib/sql.rb +10 -0
  79. data/lib/gems/dm-observer-0.9.7/lib/dm-observer/version.rb +5 -0
  80. data/lib/gems/dm-observer-0.9.7/lib/dm-observer.rb +91 -0
  81. data/lib/gems/dm-serializer-0.9.7/lib/dm-serializer/version.rb +5 -0
  82. data/lib/gems/dm-serializer-0.9.7/lib/dm-serializer.rb +183 -0
  83. data/lib/gems/dm-timestamps-0.9.7/lib/dm-timestamps/version.rb +5 -0
  84. data/lib/gems/dm-timestamps-0.9.7/lib/dm-timestamps.rb +57 -0
  85. data/lib/gems/dm-types-0.9.7/lib/dm-types/bcrypt_hash.rb +31 -0
  86. data/lib/gems/dm-types-0.9.7/lib/dm-types/csv.rb +28 -0
  87. data/lib/gems/dm-types-0.9.7/lib/dm-types/enum.rb +70 -0
  88. data/lib/gems/dm-types-0.9.7/lib/dm-types/epoch_time.rb +27 -0
  89. data/lib/gems/dm-types-0.9.7/lib/dm-types/file_path.rb +27 -0
  90. data/lib/gems/dm-types-0.9.7/lib/dm-types/flag.rb +61 -0
  91. data/lib/gems/dm-types-0.9.7/lib/dm-types/ip_address.rb +30 -0
  92. data/lib/gems/dm-types-0.9.7/lib/dm-types/json.rb +40 -0
  93. data/lib/gems/dm-types-0.9.7/lib/dm-types/regexp.rb +20 -0
  94. data/lib/gems/dm-types-0.9.7/lib/dm-types/serial.rb +8 -0
  95. data/lib/gems/dm-types-0.9.7/lib/dm-types/slug.rb +37 -0
  96. data/lib/gems/dm-types-0.9.7/lib/dm-types/uri.rb +29 -0
  97. data/lib/gems/dm-types-0.9.7/lib/dm-types/uuid.rb +64 -0
  98. data/lib/gems/dm-types-0.9.7/lib/dm-types/version.rb +5 -0
  99. data/lib/gems/dm-types-0.9.7/lib/dm-types/yaml.rb +36 -0
  100. data/lib/gems/dm-types-0.9.7/lib/dm-types.rb +28 -0
  101. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/absent_field_validator.rb +60 -0
  102. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/acceptance_validator.rb +76 -0
  103. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/auto_validate.rb +153 -0
  104. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/block_validator.rb +60 -0
  105. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/confirmation_validator.rb +80 -0
  106. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/contextual_validators.rb +56 -0
  107. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/custom_validator.rb +72 -0
  108. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/format_validator.rb +97 -0
  109. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/formats/email.rb +40 -0
  110. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/formats/url.rb +20 -0
  111. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/generic_validator.rb +100 -0
  112. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/length_validator.rb +113 -0
  113. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/method_validator.rb +68 -0
  114. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/numeric_validator.rb +83 -0
  115. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/primitive_validator.rb +60 -0
  116. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/required_field_validator.rb +88 -0
  117. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/support/object.rb +5 -0
  118. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/uniqueness_validator.rb +64 -0
  119. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/validation_errors.rb +63 -0
  120. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/version.rb +5 -0
  121. data/lib/gems/dm-validations-0.9.7/lib/dm-validations/within_validator.rb +53 -0
  122. data/lib/gems/dm-validations-0.9.7/lib/dm-validations.rb +234 -0
  123. data/lib/gems/json_pure-1.1.3/GPL +340 -0
  124. data/lib/gems/json_pure-1.1.3/VERSION +1 -0
  125. data/lib/gems/json_pure-1.1.3/bin/edit_json.rb +10 -0
  126. data/lib/gems/json_pure-1.1.3/bin/prettify_json.rb +76 -0
  127. data/lib/gems/json_pure-1.1.3/lib/json/Array.xpm +21 -0
  128. data/lib/gems/json_pure-1.1.3/lib/json/FalseClass.xpm +21 -0
  129. data/lib/gems/json_pure-1.1.3/lib/json/Hash.xpm +21 -0
  130. data/lib/gems/json_pure-1.1.3/lib/json/Key.xpm +73 -0
  131. data/lib/gems/json_pure-1.1.3/lib/json/NilClass.xpm +21 -0
  132. data/lib/gems/json_pure-1.1.3/lib/json/Numeric.xpm +28 -0
  133. data/lib/gems/json_pure-1.1.3/lib/json/String.xpm +96 -0
  134. data/lib/gems/json_pure-1.1.3/lib/json/TrueClass.xpm +21 -0
  135. data/lib/gems/json_pure-1.1.3/lib/json/add/core.rb +135 -0
  136. data/lib/gems/json_pure-1.1.3/lib/json/add/rails.rb +58 -0
  137. data/lib/gems/json_pure-1.1.3/lib/json/common.rb +354 -0
  138. data/lib/gems/json_pure-1.1.3/lib/json/editor.rb +1362 -0
  139. data/lib/gems/json_pure-1.1.3/lib/json/ext.rb +13 -0
  140. data/lib/gems/json_pure-1.1.3/lib/json/json.xpm +1499 -0
  141. data/lib/gems/json_pure-1.1.3/lib/json/pure/generator.rb +394 -0
  142. data/lib/gems/json_pure-1.1.3/lib/json/pure/parser.rb +259 -0
  143. data/lib/gems/json_pure-1.1.3/lib/json/pure.rb +75 -0
  144. data/lib/gems/json_pure-1.1.3/lib/json/version.rb +9 -0
  145. data/lib/gems/json_pure-1.1.3/lib/json.rb +235 -0
  146. data/lib/gems/launchy-0.3.2/bin/launchy +12 -0
  147. data/lib/gems/launchy-0.3.2/lib/launchy/application.rb +163 -0
  148. data/lib/gems/launchy-0.3.2/lib/launchy/browser.rb +85 -0
  149. data/lib/gems/launchy-0.3.2/lib/launchy/command_line.rb +48 -0
  150. data/lib/gems/launchy-0.3.2/lib/launchy/gemspec.rb +53 -0
  151. data/lib/gems/launchy-0.3.2/lib/launchy/specification.rb +133 -0
  152. data/lib/gems/launchy-0.3.2/lib/launchy/version.rb +18 -0
  153. data/lib/gems/launchy-0.3.2/lib/launchy.rb +58 -0
  154. data/lib/gems/uuidtools-1.0.3/lib/uuidtools/version.rb +32 -0
  155. data/lib/gems/uuidtools-1.0.3/lib/uuidtools.rb +648 -0
  156. data/lib/gems.rb +13 -0
  157. data/lib/mack-data_mapper/migration_generator/migration_generator.rb +5 -0
  158. data/lib/mack-data_mapper/migration_generator/templates/db/migrations/%=@migration_name%.rb.template +1 -1
  159. data/lib/mack-data_mapper/model_generator/manifest.yml +3 -3
  160. data/lib/mack-data_mapper/model_generator/model_generator.rb +8 -1
  161. data/lib/mack-data_mapper/model_generator/templates/model.rb.template +1 -1
  162. data/lib/mack-data_mapper/model_generator/templates/rspec.rb.template +1 -1
  163. data/lib/mack-data_mapper/model_generator/templates/test_case.rb.template +1 -1
  164. data/lib/mack-data_mapper.rb +3 -2
  165. data/lib/mack-data_mapper_tasks.rb +7 -0
  166. metadata +235 -86
@@ -0,0 +1,488 @@
1
+ require 'set'
2
+
3
+ module DataMapper
4
+ module Model
5
+ ##
6
+ #
7
+ # Extends the model with this module after DataMapper::Resource has been
8
+ # included.
9
+ #
10
+ # This is a useful way to extend DataMapper::Model while
11
+ # still retaining a self.extended method.
12
+ #
13
+ # @param [Module] extensions the module that is to be extend the model after
14
+ # after DataMapper::Model
15
+ #
16
+ # @return [TrueClass, FalseClass] whether or not the inclusions have been
17
+ # successfully appended to the list
18
+ #-
19
+ # @api public
20
+ #
21
+ # TODO: Move this do DataMapper::Model when DataMapper::Model is created
22
+ def self.append_extensions(*extensions)
23
+ extra_extensions.concat extensions
24
+ true
25
+ end
26
+
27
+ def self.extra_extensions
28
+ @extra_extensions ||= []
29
+ end
30
+
31
+ def self.extended(model)
32
+ model.instance_variable_set(:@storage_names, {})
33
+ model.instance_variable_set(:@properties, {})
34
+ model.instance_variable_set(:@field_naming_conventions, {})
35
+ extra_extensions.each { |extension| model.extend(extension) }
36
+ end
37
+
38
+ def inherited(target)
39
+ target.instance_variable_set(:@storage_names, @storage_names.dup)
40
+ target.instance_variable_set(:@properties, {})
41
+ target.instance_variable_set(:@base_model, self.base_model)
42
+ target.instance_variable_set(:@paranoid_properties, @paranoid_properties)
43
+ target.instance_variable_set(:@field_naming_conventions, @field_naming_conventions.dup)
44
+
45
+ if self.respond_to?(:validators)
46
+ @validations.contexts.each do |context, validators|
47
+ validators.each { |validator| target.validators.context(context) << validator }
48
+ end
49
+ end
50
+
51
+ @properties.each do |repository_name,properties|
52
+ repository(repository_name) do
53
+ properties.each do |property|
54
+ next if target.properties(repository_name).has_property?(property.name)
55
+ target.property(property.name, property.type, property.options.dup)
56
+ end
57
+ end
58
+ end
59
+
60
+ if @relationships
61
+ duped_relationships = {}
62
+ @relationships.each do |repository_name,relationships|
63
+ relationships.each do |name, relationship|
64
+ dup = relationship.dup
65
+ dup.instance_variable_set(:@child_model, target) if dup.instance_variable_get(:@child_model) == self
66
+ dup.instance_variable_set(:@parent_model, target) if dup.instance_variable_get(:@parent_model) == self
67
+ duped_relationships[repository_name] ||= {}
68
+ duped_relationships[repository_name][name] = dup
69
+ end
70
+ end
71
+ target.instance_variable_set(:@relationships, duped_relationships)
72
+ end
73
+ end
74
+
75
+ def self.new(storage_name, &block)
76
+ model = Class.new
77
+ model.send(:include, Resource)
78
+ model.class_eval <<-EOS, __FILE__, __LINE__
79
+ def self.default_storage_name
80
+ #{Extlib::Inflection.classify(storage_name).inspect}
81
+ end
82
+ EOS
83
+ model.instance_eval(&block) if block_given?
84
+ model
85
+ end
86
+
87
+ def base_model
88
+ @base_model ||= self
89
+ end
90
+
91
+ def repository_name
92
+ Repository.context.any? ? Repository.context.last.name : default_repository_name
93
+ end
94
+
95
+ ##
96
+ # Get the repository with a given name, or the default one for the current
97
+ # context, or the default one for this class.
98
+ #
99
+ # @param name<Symbol> the name of the repository wanted
100
+ # @param block<Block> block to execute with the fetched repository as parameter
101
+ #
102
+ # @return <Object, DataMapper::Respository> whatever the block returns,
103
+ # if given a block, otherwise the requested repository.
104
+ #-
105
+ # @api public
106
+ def repository(name = nil)
107
+ #
108
+ # There has been a couple of different strategies here, but me (zond) and dkubb are at least
109
+ # united in the concept of explicitness over implicitness. That is - the explicit wish of the
110
+ # caller (+name+) should be given more priority than the implicit wish of the caller (Repository.context.last).
111
+ #
112
+ if block_given?
113
+ DataMapper.repository(name || repository_name) { |*block_args| yield(*block_args) }
114
+ else
115
+ DataMapper.repository(name || repository_name)
116
+ end
117
+ end
118
+
119
+ ##
120
+ # the name of the storage recepticle for this resource. IE. table name, for database stores
121
+ #
122
+ # @return <String> the storage name (IE table name, for database stores) associated with this resource in the given repository
123
+ def storage_name(repository_name = default_repository_name)
124
+ @storage_names[repository_name] ||= repository(repository_name).adapter.resource_naming_convention.call(base_model.send(:default_storage_name))
125
+ end
126
+
127
+ ##
128
+ # the names of the storage recepticles for this resource across all repositories
129
+ #
130
+ # @return <Hash(Symbol => String)> All available names of storage recepticles
131
+ def storage_names
132
+ @storage_names
133
+ end
134
+
135
+ ##
136
+ # The field naming conventions for this resource across all repositories.
137
+ #
138
+ # @return <String> The naming convention for the given repository
139
+ def field_naming_convention(repository_name = default_storage_name)
140
+ @field_naming_conventions[repository_name] ||= repository(repository_name).adapter.field_naming_convention
141
+ end
142
+
143
+ ##
144
+ # defines a property on the resource
145
+ #
146
+ # @param <Symbol> name the name for which to call this property
147
+ # @param <Type> type the type to define this property ass
148
+ # @param <Hash(Symbol => String)> options a hash of available options
149
+ # @see DataMapper::Property
150
+ def property(name, type, options = {})
151
+ property = Property.new(self, name, type, options)
152
+
153
+ create_property_getter(property)
154
+ create_property_setter(property)
155
+
156
+ properties(repository_name)[property.name] = property
157
+ @_valid_relations = false
158
+
159
+ # Add property to the other mappings as well if this is for the default
160
+ # repository.
161
+ if repository_name == default_repository_name
162
+ @properties.each_pair do |repository_name, properties|
163
+ next if repository_name == default_repository_name
164
+ properties << property unless properties.has_property?(property.name)
165
+ end
166
+ end
167
+
168
+ # Add the property to the lazy_loads set for this resources repository
169
+ # only.
170
+ # TODO Is this right or should we add the lazy contexts to all
171
+ # repositories?
172
+ if property.lazy?
173
+ context = options.fetch(:lazy, :default)
174
+ context = :default if context == true
175
+
176
+ Array(context).each do |item|
177
+ properties(repository_name).lazy_context(item) << name
178
+ end
179
+ end
180
+
181
+ # add the property to the child classes only if the property was
182
+ # added after the child classes' properties have been copied from
183
+ # the parent
184
+ if respond_to?(:descendants)
185
+ descendants.each do |model|
186
+ next if model.properties(repository_name).has_property?(name)
187
+ model.property(name, type, options)
188
+ end
189
+ end
190
+
191
+ property
192
+ end
193
+
194
+ def repositories
195
+ [ repository ].to_set + @properties.keys.collect { |repository_name| DataMapper.repository(repository_name) }
196
+ end
197
+
198
+ def properties(repository_name = default_repository_name)
199
+ # We need to check whether all relations are already set up.
200
+ # If this isn't the case, we try to reload them here
201
+ if !@_valid_relations && respond_to?(:many_to_one_relationships)
202
+ @_valid_relations = true
203
+ begin
204
+ many_to_one_relationships.each do |r|
205
+ r.child_key
206
+ end
207
+ rescue NameError
208
+ # Apparently not all relations are loaded,
209
+ # so we will try again later on
210
+ @_valid_relations = false
211
+ end
212
+ end
213
+ @properties[repository_name] ||= repository_name == Repository.default_name ? PropertySet.new : properties(Repository.default_name).dup
214
+ end
215
+
216
+ def eager_properties(repository_name = default_repository_name)
217
+ properties(repository_name).defaults
218
+ end
219
+
220
+ # @api private
221
+ def properties_with_subclasses(repository_name = default_repository_name)
222
+ properties = PropertySet.new
223
+ ([ self ].to_set + (respond_to?(:descendants) ? descendants : [])).each do |model|
224
+ model.relationships(repository_name).each_value { |relationship| relationship.child_key }
225
+ model.many_to_one_relationships.each do |relationship| relationship.child_key end
226
+ model.properties(repository_name).each do |property|
227
+ properties << property unless properties.has_property?(property.name)
228
+ end
229
+ end
230
+ properties
231
+ end
232
+
233
+ def key(repository_name = default_repository_name)
234
+ properties(repository_name).key
235
+ end
236
+
237
+ def default_order(repository_name = default_repository_name)
238
+ @default_order ||= {}
239
+ @default_order[repository_name] ||= key(repository_name).map { |property| Query::Direction.new(property) }
240
+ end
241
+
242
+ def get(*key)
243
+ key = typecast_key(key)
244
+ repository.identity_map(self).get(key) || first(to_query(repository, key))
245
+ end
246
+
247
+ def get!(*key)
248
+ get(*key) || raise(ObjectNotFoundError, "Could not find #{self.name} with key #{key.inspect}")
249
+ end
250
+
251
+ def all(query = {})
252
+ query = scoped_query(query)
253
+ query.repository.read_many(query)
254
+ end
255
+
256
+ def first(*args)
257
+ query = args.last.respond_to?(:merge) ? args.pop : {}
258
+ query = scoped_query(query.merge(:limit => args.first || 1))
259
+
260
+ if args.any?
261
+ query.repository.read_many(query)
262
+ else
263
+ query.repository.read_one(query)
264
+ end
265
+ end
266
+
267
+ def [](*key)
268
+ warn("#{name}[] is deprecated. Use #{name}.get! instead.")
269
+ get!(*key)
270
+ end
271
+
272
+ def first_or_create(query, attributes = {})
273
+ first(query) || begin
274
+ resource = allocate
275
+ query = query.dup
276
+
277
+ properties(repository_name).key.each do |property|
278
+ if value = query.delete(property.name)
279
+ resource.send("#{property.name}=", value)
280
+ end
281
+ end
282
+
283
+ resource.attributes = query.merge(attributes)
284
+ resource.save
285
+ resource
286
+ end
287
+ end
288
+
289
+ ##
290
+ # Create an instance of Resource with the given attributes
291
+ #
292
+ # @param <Hash(Symbol => Object)> attributes hash of attributes to set
293
+ def create(attributes = {})
294
+ resource = new(attributes)
295
+ resource.save
296
+ resource
297
+ end
298
+
299
+ ##
300
+ # This method is deprecated, and will be removed from dm-core.
301
+ #
302
+ def create!(attributes = {})
303
+ warn("Model#create! is deprecated. It is moving to dm-validations, and will be used to create a record without validations")
304
+ resource = create(attributes)
305
+ raise PersistenceError, "Resource not saved: :new_record => #{resource.new_record?}, :dirty_attributes => #{resource.dirty_attributes.inspect}" if resource.new_record?
306
+ resource
307
+ end
308
+
309
+ # TODO SPEC
310
+ def copy(source, destination, query = {})
311
+ repository(destination) do
312
+ repository(source).read_many(scoped_query(query)).each do |resource|
313
+ self.create(resource.attributes)
314
+ end
315
+ end
316
+ end
317
+
318
+ # @api private
319
+ # TODO: spec this
320
+ def load(values, query)
321
+ repository = query.repository
322
+ model = self
323
+
324
+ if inheritance_property_index = query.inheritance_property_index
325
+ model = values.at(inheritance_property_index) || model
326
+ end
327
+
328
+ if key_property_indexes = query.key_property_indexes(repository)
329
+ key_values = values.values_at(*key_property_indexes)
330
+ identity_map = repository.identity_map(model)
331
+
332
+ if resource = identity_map.get(key_values)
333
+ return resource unless query.reload?
334
+ else
335
+ resource = model.allocate
336
+ resource.instance_variable_set(:@repository, repository)
337
+ identity_map.set(key_values, resource)
338
+ end
339
+ else
340
+ resource = model.allocate
341
+ resource.readonly!
342
+ end
343
+
344
+ resource.instance_variable_set(:@new_record, false)
345
+
346
+ query.fields.zip(values) do |property,value|
347
+ value = property.custom? ? property.type.load(value, property) : property.typecast(value)
348
+ property.set!(resource, value)
349
+
350
+ if track = property.track
351
+ case track
352
+ when :hash
353
+ resource.original_values[property.name] = value.dup.hash unless resource.original_values.has_key?(property.name) rescue value.hash
354
+ when :load
355
+ resource.original_values[property.name] = value unless resource.original_values.has_key?(property.name)
356
+ end
357
+ end
358
+ end
359
+
360
+ resource
361
+ end
362
+
363
+ # TODO: spec this
364
+ def to_query(repository, key, query = {})
365
+ conditions = Hash[ *self.key(repository.name).zip(key).flatten ]
366
+ Query.new(repository, self, query.merge(conditions))
367
+ end
368
+
369
+ def typecast_key(key)
370
+ self.key(repository_name).zip(key).map { |k, v| k.typecast(v) }
371
+ end
372
+
373
+ def default_repository_name
374
+ Repository.default_name
375
+ end
376
+
377
+ def paranoid_properties
378
+ @paranoid_properties ||= {}
379
+ @paranoid_properties
380
+ end
381
+
382
+ private
383
+
384
+ def default_storage_name
385
+ self.name
386
+ end
387
+
388
+ def scoped_query(query = self.query)
389
+ assert_kind_of 'query', query, Query, Hash
390
+
391
+ return self.query if query == self.query
392
+
393
+ query = if query.kind_of?(Hash)
394
+ Query.new(query.has_key?(:repository) ? query.delete(:repository) : self.repository, self, query)
395
+ else
396
+ query
397
+ end
398
+
399
+ if self.query
400
+ self.query.merge(query)
401
+ else
402
+ merge_with_default_scope(query)
403
+ end
404
+ end
405
+
406
+ def set_paranoid_property(name, &block)
407
+ self.paranoid_properties[name] = block
408
+ end
409
+
410
+ # defines the getter for the property
411
+ def create_property_getter(property)
412
+ class_eval <<-EOS, __FILE__, __LINE__
413
+ #{property.reader_visibility}
414
+ def #{property.getter}
415
+ attribute_get(#{property.name.inspect})
416
+ end
417
+ EOS
418
+
419
+ if property.primitive == TrueClass && !instance_methods.include?(property.name.to_s)
420
+ class_eval <<-EOS, __FILE__, __LINE__
421
+ #{property.reader_visibility}
422
+ alias #{property.name} #{property.getter}
423
+ EOS
424
+ end
425
+ end
426
+
427
+ # defines the setter for the property
428
+ def create_property_setter(property)
429
+ unless instance_methods.include?("#{property.name}=")
430
+ class_eval <<-EOS, __FILE__, __LINE__
431
+ #{property.writer_visibility}
432
+ def #{property.name}=(value)
433
+ attribute_set(#{property.name.inspect}, value)
434
+ end
435
+ EOS
436
+ end
437
+ end
438
+
439
+ def relationships(*args)
440
+ # DO NOT REMOVE!
441
+ # method_missing depends on these existing. Without this stub,
442
+ # a missing module can cause misleading recursive errors.
443
+ raise NotImplementedError.new
444
+ end
445
+
446
+ def method_missing(method, *args, &block)
447
+ if relationship = self.relationships(repository_name)[method]
448
+ klass = self == relationship.child_model ? relationship.parent_model : relationship.child_model
449
+ return DataMapper::Query::Path.new(repository, [ relationship ], klass)
450
+ end
451
+
452
+ if property = properties(repository_name)[method]
453
+ return property
454
+ end
455
+
456
+ super
457
+ end
458
+
459
+ # TODO: move to dm-more/dm-transactions
460
+ module Transaction
461
+ #
462
+ # Produce a new Transaction for this Resource class
463
+ #
464
+ # @return <DataMapper::Adapters::Transaction
465
+ # a new DataMapper::Adapters::Transaction with all DataMapper::Repositories
466
+ # of the class of this DataMapper::Resource added.
467
+ #-
468
+ # @api public
469
+ #
470
+ # TODO: move to dm-more/dm-transactions
471
+ def transaction
472
+ DataMapper::Transaction.new(self) { |block_args| yield(*block_args) }
473
+ end
474
+ end # module Transaction
475
+
476
+ include Transaction
477
+
478
+ # TODO: move to dm-more/dm-migrations
479
+ module Migration
480
+ # TODO: move to dm-more/dm-migrations
481
+ def storage_exists?(repository_name = default_repository_name)
482
+ repository(repository_name).storage_exists?(storage_name(repository_name))
483
+ end
484
+ end # module Migration
485
+
486
+ include Migration
487
+ end # module Model
488
+ end # module DataMapper
@@ -0,0 +1,84 @@
1
+ module DataMapper
2
+
3
+ # Use these modules to establish naming conventions.
4
+ # The default is UnderscoredAndPluralized.
5
+ # You assign a naming convention like so:
6
+ #
7
+ # repository(:default).adapter.resource_naming_convention = NamingConventions::Resource::Underscored
8
+ #
9
+ # You can also easily assign a custom convention with a Proc:
10
+ #
11
+ # repository(:default).adapter.resource_naming_convention = lambda do |value|
12
+ # 'tbl' + value.camelize(true)
13
+ # end
14
+ #
15
+ # Or by simply defining your own module in NamingConventions that responds to
16
+ # ::call.
17
+ #
18
+ # NOTE: It's important to set the convention before accessing your models
19
+ # since the resource_names are cached after first accessed.
20
+ # DataMapper.setup(name, uri) returns the Adapter for convenience, so you can
21
+ # use code like this:
22
+ #
23
+ # adapter = DataMapper.setup(:default, "mock://localhost/mock")
24
+ # adapter.resource_naming_convention = DataMapper::NamingConventions::Resource::Underscored
25
+ module NamingConventions
26
+
27
+ module Resource
28
+
29
+ module UnderscoredAndPluralized
30
+ def self.call(name)
31
+ Extlib::Inflection.pluralize(Extlib::Inflection.underscore(name)).gsub('/','_')
32
+ end
33
+ end # module UnderscoredAndPluralized
34
+
35
+ module UnderscoredAndPluralizedWithoutModule
36
+ def self.call(name)
37
+ Extlib::Inflection.pluralize(Extlib::Inflection.underscore(Extlib::Inflection.demodulize(name)))
38
+ end
39
+ end # module UnderscoredAndPluralizedWithoutModule
40
+
41
+ module Underscored
42
+ def self.call(name)
43
+ Extlib::Inflection.underscore(name)
44
+ end
45
+ end # module Underscored
46
+
47
+ module Yaml
48
+ def self.call(name)
49
+ Extlib::Inflection.pluralize(Extlib::Inflection.underscore(name)) + ".yaml"
50
+ end
51
+ end # module Yaml
52
+
53
+ end # module Resource
54
+
55
+ module Field
56
+
57
+ module UnderscoredAndPluralized
58
+ def self.call(property)
59
+ Extlib::Inflection.pluralize(Extlib::Inflection.underscore(property.name.to_s)).gsub('/','_')
60
+ end
61
+ end # module UnderscoredAndPluralized
62
+
63
+ module UnderscoredAndPluralizedWithoutModule
64
+ def self.call(property)
65
+ Extlib::Inflection.pluralize(Extlib::Inflection.underscore(Extlib::Inflection.demodulize(property.name.to_s)))
66
+ end
67
+ end # module UnderscoredAndPluralizedWithoutModule
68
+
69
+ module Underscored
70
+ def self.call(property)
71
+ Extlib::Inflection.underscore(property.name.to_s)
72
+ end
73
+ end # module Underscored
74
+
75
+ module Yaml
76
+ def self.call(property)
77
+ Extlib::Inflection.pluralize(Extlib::Inflection.underscore(property.name.to_s)) + ".yaml"
78
+ end
79
+ end # module Yaml
80
+
81
+ end # module Field
82
+
83
+ end # module NamingConventions
84
+ end # module DataMapper