dm-core 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/CHANGELOG +144 -0
  2. data/FAQ +74 -0
  3. data/MIT-LICENSE +22 -0
  4. data/QUICKLINKS +12 -0
  5. data/README +143 -0
  6. data/lib/dm-core.rb +213 -0
  7. data/lib/dm-core/adapters.rb +4 -0
  8. data/lib/dm-core/adapters/abstract_adapter.rb +202 -0
  9. data/lib/dm-core/adapters/data_objects_adapter.rb +701 -0
  10. data/lib/dm-core/adapters/mysql_adapter.rb +132 -0
  11. data/lib/dm-core/adapters/postgres_adapter.rb +179 -0
  12. data/lib/dm-core/adapters/sqlite3_adapter.rb +105 -0
  13. data/lib/dm-core/associations.rb +172 -0
  14. data/lib/dm-core/associations/many_to_many.rb +138 -0
  15. data/lib/dm-core/associations/many_to_one.rb +101 -0
  16. data/lib/dm-core/associations/one_to_many.rb +275 -0
  17. data/lib/dm-core/associations/one_to_one.rb +61 -0
  18. data/lib/dm-core/associations/relationship.rb +116 -0
  19. data/lib/dm-core/associations/relationship_chain.rb +74 -0
  20. data/lib/dm-core/auto_migrations.rb +64 -0
  21. data/lib/dm-core/collection.rb +604 -0
  22. data/lib/dm-core/hook.rb +11 -0
  23. data/lib/dm-core/identity_map.rb +45 -0
  24. data/lib/dm-core/is.rb +16 -0
  25. data/lib/dm-core/logger.rb +233 -0
  26. data/lib/dm-core/migrations/destructive_migrations.rb +17 -0
  27. data/lib/dm-core/migrator.rb +29 -0
  28. data/lib/dm-core/model.rb +399 -0
  29. data/lib/dm-core/naming_conventions.rb +52 -0
  30. data/lib/dm-core/property.rb +611 -0
  31. data/lib/dm-core/property_set.rb +158 -0
  32. data/lib/dm-core/query.rb +590 -0
  33. data/lib/dm-core/repository.rb +159 -0
  34. data/lib/dm-core/resource.rb +618 -0
  35. data/lib/dm-core/scope.rb +35 -0
  36. data/lib/dm-core/support.rb +7 -0
  37. data/lib/dm-core/support/array.rb +13 -0
  38. data/lib/dm-core/support/assertions.rb +8 -0
  39. data/lib/dm-core/support/errors.rb +23 -0
  40. data/lib/dm-core/support/kernel.rb +7 -0
  41. data/lib/dm-core/support/symbol.rb +41 -0
  42. data/lib/dm-core/transaction.rb +267 -0
  43. data/lib/dm-core/type.rb +160 -0
  44. data/lib/dm-core/type_map.rb +80 -0
  45. data/lib/dm-core/types.rb +19 -0
  46. data/lib/dm-core/types/boolean.rb +7 -0
  47. data/lib/dm-core/types/discriminator.rb +32 -0
  48. data/lib/dm-core/types/object.rb +20 -0
  49. data/lib/dm-core/types/paranoid_boolean.rb +23 -0
  50. data/lib/dm-core/types/paranoid_datetime.rb +22 -0
  51. data/lib/dm-core/types/serial.rb +9 -0
  52. data/lib/dm-core/types/text.rb +10 -0
  53. data/spec/integration/association_spec.rb +1215 -0
  54. data/spec/integration/association_through_spec.rb +150 -0
  55. data/spec/integration/associations/many_to_many_spec.rb +171 -0
  56. data/spec/integration/associations/many_to_one_spec.rb +123 -0
  57. data/spec/integration/associations/one_to_many_spec.rb +66 -0
  58. data/spec/integration/auto_migrations_spec.rb +398 -0
  59. data/spec/integration/collection_spec.rb +1015 -0
  60. data/spec/integration/data_objects_adapter_spec.rb +32 -0
  61. data/spec/integration/model_spec.rb +68 -0
  62. data/spec/integration/mysql_adapter_spec.rb +85 -0
  63. data/spec/integration/postgres_adapter_spec.rb +732 -0
  64. data/spec/integration/property_spec.rb +224 -0
  65. data/spec/integration/query_spec.rb +376 -0
  66. data/spec/integration/repository_spec.rb +57 -0
  67. data/spec/integration/resource_spec.rb +324 -0
  68. data/spec/integration/sqlite3_adapter_spec.rb +352 -0
  69. data/spec/integration/sti_spec.rb +185 -0
  70. data/spec/integration/transaction_spec.rb +75 -0
  71. data/spec/integration/type_spec.rb +149 -0
  72. data/spec/lib/mock_adapter.rb +27 -0
  73. data/spec/spec_helper.rb +112 -0
  74. data/spec/unit/adapters/abstract_adapter_spec.rb +133 -0
  75. data/spec/unit/adapters/adapter_shared_spec.rb +15 -0
  76. data/spec/unit/adapters/data_objects_adapter_spec.rb +627 -0
  77. data/spec/unit/adapters/postgres_adapter_spec.rb +125 -0
  78. data/spec/unit/associations/many_to_many_spec.rb +14 -0
  79. data/spec/unit/associations/many_to_one_spec.rb +138 -0
  80. data/spec/unit/associations/one_to_many_spec.rb +385 -0
  81. data/spec/unit/associations/one_to_one_spec.rb +7 -0
  82. data/spec/unit/associations/relationship_spec.rb +67 -0
  83. data/spec/unit/associations_spec.rb +205 -0
  84. data/spec/unit/auto_migrations_spec.rb +110 -0
  85. data/spec/unit/collection_spec.rb +174 -0
  86. data/spec/unit/data_mapper_spec.rb +21 -0
  87. data/spec/unit/identity_map_spec.rb +126 -0
  88. data/spec/unit/is_spec.rb +80 -0
  89. data/spec/unit/migrator_spec.rb +33 -0
  90. data/spec/unit/model_spec.rb +339 -0
  91. data/spec/unit/naming_conventions_spec.rb +28 -0
  92. data/spec/unit/property_set_spec.rb +96 -0
  93. data/spec/unit/property_spec.rb +447 -0
  94. data/spec/unit/query_spec.rb +485 -0
  95. data/spec/unit/repository_spec.rb +93 -0
  96. data/spec/unit/resource_spec.rb +557 -0
  97. data/spec/unit/scope_spec.rb +131 -0
  98. data/spec/unit/transaction_spec.rb +493 -0
  99. data/spec/unit/type_map_spec.rb +114 -0
  100. data/spec/unit/type_spec.rb +119 -0
  101. metadata +187 -0
@@ -0,0 +1,35 @@
1
+ module DataMapper
2
+ module Scope
3
+ def query
4
+ scope_stack.last
5
+ end
6
+
7
+ protected
8
+
9
+ def with_scope(query, &block)
10
+ # merge the current scope with the passed in query
11
+ with_exclusive_scope(self.query ? self.query.merge(query) : query, &block)
12
+ end
13
+
14
+ def with_exclusive_scope(query, &block)
15
+ query = DataMapper::Query.new(repository, self, query) if query.kind_of?(Hash)
16
+
17
+ scope_stack << query
18
+
19
+ begin
20
+ return yield(query)
21
+ ensure
22
+ scope_stack.pop
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def scope_stack
29
+ scope_stack_for = Thread.current[:dm_scope_stack] ||= Hash.new { |h,k| h[k] = [] }
30
+ scope_stack_for[self]
31
+ end
32
+
33
+ Model.send(:include, self)
34
+ end # module Scope
35
+ end # module DataMapper
@@ -0,0 +1,7 @@
1
+ dir = Pathname(__FILE__).dirname.expand_path / 'support'
2
+
3
+ require dir / 'array'
4
+ require dir / 'assertions'
5
+ require dir / 'errors'
6
+ require dir / 'kernel'
7
+ require dir / 'symbol'
@@ -0,0 +1,13 @@
1
+ class Array
2
+
3
+ ##
4
+ # atm it assumes self is an array of [key,value]-arrays
5
+ # this is just a better way to make hashes than Hash[*array.flatten]
6
+ # since you cannot flatten only one level in ruby 1.8.6
7
+ #
8
+ def to_hash
9
+ h = {}
10
+ self.each{ |k,v| h[k] = v }
11
+ h
12
+ end
13
+ end # class Symbol
@@ -0,0 +1,8 @@
1
+ module DataMapper
2
+ module Assertions
3
+ def assert_kind_of(name, value, *klasses)
4
+ klasses.each { |k| return if value.kind_of?(k) }
5
+ raise ArgumentError, "+#{name}+ should be #{klasses.map { |k| k.name } * ' or '}, but was #{value.class.name}", caller(2)
6
+ end
7
+ end
8
+ end # module DataMapper
@@ -0,0 +1,23 @@
1
+ #Some useful errors types
2
+ module DataMapper
3
+ class ValidationError < StandardError; end
4
+
5
+ class ObjectNotFoundError < StandardError; end
6
+
7
+ class MaterializationError < StandardError; end
8
+
9
+ class RepositoryNotSetupError < StandardError; end
10
+
11
+ class IncompleteResourceError < StandardError; end
12
+
13
+ class PersistenceError < StandardError; end
14
+
15
+ class PluginNotFoundError < StandardError; end
16
+ end # module DataMapper
17
+
18
+ class StandardError
19
+ # Displays the specific error message and the backtrace associated with it.
20
+ def display
21
+ "#{message}\n\t#{backtrace.join("\n\t")}"
22
+ end
23
+ end # class StandardError
@@ -0,0 +1,7 @@
1
+ module Kernel
2
+ # Delegates to DataMapper::repository.
3
+ # Will not overwrite if a method of the same name is pre-defined.
4
+ def repository(*args, &block)
5
+ DataMapper.repository(*args, &block)
6
+ end
7
+ end # module Kernel
@@ -0,0 +1,41 @@
1
+ class Symbol
2
+ def gt
3
+ DataMapper::Query::Operator.new(self, :gt)
4
+ end
5
+
6
+ def gte
7
+ DataMapper::Query::Operator.new(self, :gte)
8
+ end
9
+
10
+ def lt
11
+ DataMapper::Query::Operator.new(self, :lt)
12
+ end
13
+
14
+ def lte
15
+ DataMapper::Query::Operator.new(self, :lte)
16
+ end
17
+
18
+ def not
19
+ DataMapper::Query::Operator.new(self, :not)
20
+ end
21
+
22
+ def eql
23
+ DataMapper::Query::Operator.new(self, :eql)
24
+ end
25
+
26
+ def like
27
+ DataMapper::Query::Operator.new(self, :like)
28
+ end
29
+
30
+ def in
31
+ DataMapper::Query::Operator.new(self, :in)
32
+ end
33
+
34
+ def asc
35
+ DataMapper::Query::Operator.new(self, :asc)
36
+ end
37
+
38
+ def desc
39
+ DataMapper::Query::Operator.new(self, :desc)
40
+ end
41
+ end # class Symbol
@@ -0,0 +1,267 @@
1
+ # TODO: move to dm-more/dm-transactions
2
+
3
+ module DataMapper
4
+ class Transaction
5
+
6
+ attr_reader :transaction_primitives, :adapters, :state
7
+
8
+ #
9
+ # Create a new DataMapper::Transaction
10
+ #
11
+ # @see DataMapper::Transaction#link
12
+ #
13
+ # In fact, it just calls #link with the given arguments at the end of the
14
+ # constructor.
15
+ #
16
+ def initialize(*things, &block)
17
+ @transaction_primitives = {}
18
+ @state = :none
19
+ @adapters = {}
20
+ link(*things)
21
+ commit(&block) if block_given?
22
+ end
23
+
24
+ #
25
+ # Associate this Transaction with some things.
26
+ #
27
+ # @param things<any number of Object> the things you want this Transaction
28
+ # associated with
29
+ # @details [things a Transaction may be associatied with]
30
+ # DataMapper::Adapters::AbstractAdapter subclasses will be added as
31
+ # adapters as is.
32
+ # Arrays will have their elements added.
33
+ # DataMapper::Repositories will have their @adapters added.
34
+ # DataMapper::Resource subclasses will have all the repositories of all
35
+ # their properties added.
36
+ # DataMapper::Resource instances will have all repositories of all their
37
+ # properties added.
38
+ # @param block<Block> a block (taking one argument, the Transaction) to execute
39
+ # within this transaction. The transaction will begin and commit around
40
+ # the block, and rollback if an exception is raised.
41
+ #
42
+ def link(*things, &block)
43
+ raise "Illegal state for link: #{@state}" unless @state == :none
44
+ things.each do |thing|
45
+ if thing.is_a?(Array)
46
+ link(*thing)
47
+ elsif thing.is_a?(DataMapper::Adapters::AbstractAdapter)
48
+ @adapters[thing] = :none
49
+ elsif thing.is_a?(DataMapper::Repository)
50
+ link(thing.adapter)
51
+ elsif thing.is_a?(Class) && thing.ancestors.include?(DataMapper::Resource)
52
+ link(*thing.repositories)
53
+ elsif thing.is_a?(DataMapper::Resource)
54
+ link(thing.model)
55
+ else
56
+ raise "Unknown argument to #{self}#link: #{thing.inspect}"
57
+ end
58
+ end
59
+ return commit(&block) if block_given?
60
+ return self
61
+ end
62
+
63
+ #
64
+ # Begin the transaction
65
+ #
66
+ # Before #begin is called, the transaction is not valid and can not be used.
67
+ #
68
+ def begin
69
+ raise "Illegal state for begin: #{@state}" unless @state == :none
70
+ each_adapter(:connect_adapter, [:log_fatal_transaction_breakage])
71
+ each_adapter(:begin_adapter, [:rollback_and_close_adapter_if_begin, :close_adapter_if_none])
72
+ @state = :begin
73
+ end
74
+
75
+ #
76
+ # Commit the transaction
77
+ #
78
+ # @param block<Block> a block (taking the one argument, the Transaction) to
79
+ # execute within this transaction. The transaction will begin and commit
80
+ # around the block, and roll back if an exception is raised.
81
+ #
82
+ # @note
83
+ # If no block is given, it will simply commit any changes made since the
84
+ # Transaction did #begin.
85
+ #
86
+ def commit(&block)
87
+ if block_given?
88
+ raise "Illegal state for commit with block: #{@state}" unless @state == :none
89
+ begin
90
+ self.begin
91
+ rval = within(&block)
92
+ self.commit if @state == :begin
93
+ return rval
94
+ rescue Exception => e
95
+ self.rollback if @state == :begin
96
+ raise e
97
+ end
98
+ else
99
+ raise "Illegal state for commit without block: #{@state}" unless @state == :begin
100
+ each_adapter(:prepare_adapter, [:rollback_and_close_adapter_if_begin, :rollback_prepared_and_close_adapter_if_prepare])
101
+ each_adapter(:commit_adapter, [:log_fatal_transaction_breakage])
102
+ each_adapter(:close_adapter, [:log_fatal_transaction_breakage])
103
+ @state = :commit
104
+ end
105
+ end
106
+
107
+ #
108
+ # Rollback the transaction
109
+ #
110
+ # Will undo all changes made during the transaction.
111
+ #
112
+ def rollback
113
+ raise "Illegal state for rollback: #{@state}" unless @state == :begin
114
+ each_adapter(:rollback_adapter_if_begin, [:rollback_and_close_adapter_if_begin, :close_adapter_if_none])
115
+ each_adapter(:rollback_prepared_adapter_if_prepare, [:rollback_prepared_and_close_adapter_if_begin, :close_adapter_if_none])
116
+ each_adapter(:close_adapter_if_open, [:log_fatal_transaction_breakage])
117
+ @state = :rollback
118
+ end
119
+
120
+ #
121
+ # Execute a block within this Transaction.
122
+ #
123
+ # @param block<Block> the block of code to execute.
124
+ #
125
+ # @note
126
+ # No #begin, #commit or #rollback is performed in #within, but this
127
+ # Transaction will pushed on the per thread stack of transactions for each
128
+ # adapter it is associated with, and it will ensures that it will pop the
129
+ # Transaction away again after the block is finished.
130
+ #
131
+ def within(&block)
132
+ raise "No block provided" unless block_given?
133
+ raise "Illegal state for within: #{@state}" unless @state == :begin
134
+ @adapters.each do |adapter, state|
135
+ adapter.push_transaction(self)
136
+ end
137
+ begin
138
+ return yield(self)
139
+ ensure
140
+ @adapters.each do |adapter, state|
141
+ adapter.pop_transaction
142
+ end
143
+ end
144
+ end
145
+
146
+ def method_missing(meth, *args, &block)
147
+ if args.size == 1 && args.first.is_a?(DataMapper::Adapters::AbstractAdapter)
148
+ if (match = meth.to_s.match(/^(.*)_if_(none|begin|prepare|rollback|commit)$/))
149
+ if self.respond_to?(match[1], true)
150
+ self.send(match[1], args.first) if state_for(args.first).to_s == match[2]
151
+ else
152
+ super
153
+ end
154
+ elsif (match = meth.to_s.match(/^(.*)_unless_(none|begin|prepare|rollback|commit)$/))
155
+ if self.respond_to?(match[1], true)
156
+ self.send(match[1], args.first) unless state_for(args.first).to_s == match[2]
157
+ else
158
+ super
159
+ end
160
+ else
161
+ super
162
+ end
163
+ else
164
+ super
165
+ end
166
+ end
167
+
168
+ def primitive_for(adapter)
169
+ raise "Unknown adapter #{adapter}" unless @adapters.include?(adapter)
170
+ raise "No primitive for #{adapter}" unless @transaction_primitives.include?(adapter)
171
+ @transaction_primitives[adapter]
172
+ end
173
+
174
+ private
175
+
176
+ def validate_primitive(primitive)
177
+ [:close, :begin, :prepare, :rollback, :rollback_prepared, :commit].each do |meth|
178
+ raise "Invalid primitive #{primitive}: doesnt respond_to?(#{meth.inspect})" unless primitive.respond_to?(meth)
179
+ end
180
+ return primitive
181
+ end
182
+
183
+ def each_adapter(method, on_fail)
184
+ begin
185
+ @adapters.each do |adapter, state|
186
+ self.send(method, adapter)
187
+ end
188
+ rescue Exception => e
189
+ @adapters.each do |adapter, state|
190
+ on_fail.each do |fail_handler|
191
+ begin
192
+ self.send(fail_handler, adapter)
193
+ rescue Exception => e2
194
+ DataMapper.logger.fatal("#{self}#each_adapter(#{method.inspect}, #{on_fail.inspect}) failed with #{e.inspect}: #{e.backtrace.join("\n")} - and when sending #{fail_handler} to #{adapter} we failed again with #{e2.inspect}: #{e2.backtrace.join("\n")}")
195
+ end
196
+ end
197
+ end
198
+ raise e
199
+ end
200
+ end
201
+
202
+ def state_for(adapter)
203
+ raise "Unknown adapter #{adapter}" unless @adapters.include?(adapter)
204
+ @adapters[adapter]
205
+ end
206
+
207
+ def do_adapter(adapter, what, prerequisite)
208
+ raise "No primitive for #{adapter}" unless @transaction_primitives.include?(adapter)
209
+ raise "Illegal state for #{what}: #{state_for(adapter)}" unless state_for(adapter) == prerequisite
210
+ DataMapper.logger.debug("#{adapter.name}: #{what}")
211
+ @transaction_primitives[adapter].send(what)
212
+ @adapters[adapter] = what
213
+ end
214
+
215
+ def log_fatal_transaction_breakage(adapter)
216
+ DataMapper.logger.fatal("#{self} experienced a totally broken transaction execution. Presenting member #{adapter.inspect}.")
217
+ end
218
+
219
+ def connect_adapter(adapter)
220
+ raise "Already a primitive for adapter #{adapter}" unless @transaction_primitives[adapter].nil?
221
+ @transaction_primitives[adapter] = validate_primitive(adapter.transaction_primitive)
222
+ end
223
+
224
+ def close_adapter_if_open(adapter)
225
+ if @transaction_primitives.include?(adapter)
226
+ close_adapter(adapter)
227
+ end
228
+ end
229
+
230
+ def close_adapter(adapter)
231
+ raise "No primitive for adapter" unless @transaction_primitives.include?(adapter)
232
+ @transaction_primitives[adapter].close
233
+ @transaction_primitives.delete(adapter)
234
+ end
235
+
236
+ def begin_adapter(adapter)
237
+ do_adapter(adapter, :begin, :none)
238
+ end
239
+
240
+ def prepare_adapter(adapter)
241
+ do_adapter(adapter, :prepare, :begin);
242
+ end
243
+
244
+ def commit_adapter(adapter)
245
+ do_adapter(adapter, :commit, :prepare)
246
+ end
247
+
248
+ def rollback_adapter(adapter)
249
+ do_adapter(adapter, :rollback, :begin)
250
+ end
251
+
252
+ def rollback_prepared_adapter(adapter)
253
+ do_adapter(adapter, :rollback_prepared, :prepare)
254
+ end
255
+
256
+ def rollback_prepared_and_close_adapter(adapter)
257
+ rollback_prepared_adapter(adapter)
258
+ close_adapter(adapter)
259
+ end
260
+
261
+ def rollback_and_close_adapter(adapter)
262
+ rollback_adapter(adapter)
263
+ close_adapter(adapter)
264
+ end
265
+
266
+ end # class Transaction
267
+ end # module DataMapper
@@ -0,0 +1,160 @@
1
+ module DataMapper
2
+
3
+ # = Types
4
+ # Provides means of writing custom types for properties. Each type is based
5
+ # on a ruby primitive and handles its own serialization and materialization,
6
+ # and therefore is responsible for providing those methods.
7
+ #
8
+ # To see complete list of supported types, see documentation for
9
+ # DataMapper::Property::TYPES
10
+ #
11
+ # == Defining new Types
12
+ # To define a new type, subclass DataMapper::Type, pick ruby primitive, and
13
+ # set the options for this type.
14
+ #
15
+ # class MyType < DataMapper::Type
16
+ # primitive String
17
+ # size 10
18
+ # end
19
+ #
20
+ # Following this, you will be able to use MyType as a type for any given
21
+ # property. If special materialization and serialization is required,
22
+ # override the class methods
23
+ #
24
+ # class MyType < DataMapper::Type
25
+ # primitive String
26
+ # size 10
27
+ #
28
+ # def self.dump(value, property)
29
+ # <work some magic>
30
+ # end
31
+ #
32
+ # def self.load(value)
33
+ # <work some magic>
34
+ # end
35
+ # end
36
+ class Type
37
+ PROPERTY_OPTIONS = [
38
+ :public, :protected, :private, :accessor, :reader, :writer,
39
+ :lazy, :default, :nullable, :key, :serial, :field, :size, :length,
40
+ :format, :index, :unique_index, :check, :ordinal, :auto_validation,
41
+ :validates, :unique, :track, :precision, :scale
42
+ ]
43
+
44
+ PROPERTY_OPTION_ALIASES = {
45
+ :size => [ :length ]
46
+ }
47
+
48
+ class << self
49
+
50
+ def configure(primitive_type, options)
51
+ @_primitive_type = primitive_type
52
+ @_options = options
53
+
54
+ def self.inherited(base)
55
+ base.primitive @_primitive_type
56
+
57
+ @_options.each do |k, v|
58
+ base.send(k, v)
59
+ end
60
+ end
61
+
62
+ self
63
+ end
64
+
65
+ # The Ruby primitive type to use as basis for this type. See
66
+ # DataMapper::Property::TYPES for list of types.
67
+ #
68
+ # @param primitive<Class, nil>
69
+ # The class for the primitive. If nil is passed in, it returns the
70
+ # current primitive
71
+ #
72
+ # @return <Class> if the <primitive> param is nil, return the current primitive.
73
+ #
74
+ # @api public
75
+ def primitive(primitive = nil)
76
+ return @primitive if primitive.nil?
77
+
78
+ # TODO: change Integer to be used internally once most in-the-wild code
79
+ # is updated to use Integer for properties instead of Fixnum, or before
80
+ # DM 1.0, whichever comes first
81
+ if Fixnum == primitive
82
+ warn "#{primitive} properties are deprecated. Please use Integer instead"
83
+ primitive = Integer
84
+ end
85
+
86
+ @primitive = primitive
87
+ end
88
+
89
+ #load DataMapper::Property options
90
+ PROPERTY_OPTIONS.each do |property_option|
91
+ self.class_eval <<-EOS, __FILE__, __LINE__
92
+ def #{property_option}(arg = nil)
93
+ return @#{property_option} if arg.nil?
94
+
95
+ @#{property_option} = arg
96
+ end
97
+ EOS
98
+ end
99
+
100
+ #create property aliases
101
+ PROPERTY_OPTION_ALIASES.each do |property_option, aliases|
102
+ aliases.each do |ali|
103
+ self.class_eval <<-EOS, __FILE__, __LINE__
104
+ alias #{ali} #{property_option}
105
+ EOS
106
+ end
107
+ end
108
+
109
+ # Gives all the options set on this type
110
+ #
111
+ # @return <Hash> with all options and their values set on this type
112
+ #
113
+ # @api public
114
+ def options
115
+ options = {}
116
+ PROPERTY_OPTIONS.each do |method|
117
+ next if (value = send(method)).nil?
118
+ options[method] = value
119
+ end
120
+ options
121
+ end
122
+ end
123
+
124
+ # Stub instance method for dumping
125
+ #
126
+ # @param value<Object, nil> the value to dump
127
+ # @param property<Property, nil> the property the type is being used by
128
+ #
129
+ # @return <Object> Dumped object
130
+ #
131
+ # @api public
132
+ def self.dump(value, property)
133
+ value
134
+ end
135
+
136
+ # Stub instance method for loading
137
+ #
138
+ # @param value<Object, nil> the value to serialize
139
+ # @param property<Property, nil> the property the type is being used by
140
+ #
141
+ # @return <Object> Serialized object. Must be the same type as the Ruby primitive
142
+ #
143
+ # @api public
144
+ def self.load(value, property)
145
+ value
146
+ end
147
+
148
+ def self.bind(property)
149
+ # This method should not modify the state of this type class, and
150
+ # should produce no side-effects on the type class. It's just a
151
+ # hook to allow your custom-type to modify the property it's bound to.
152
+ end
153
+
154
+ end # class Type
155
+
156
+ def self.Type(primitive_type, options = {})
157
+ Class.new(Type).configure(primitive_type, options)
158
+ end
159
+
160
+ end # module DataMapper