lotus-model 0.4.1 → 0.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -1
- data/README.md +3 -1
- data/lib/lotus/model.rb +10 -2
- data/lib/lotus/model/adapters/abstract.rb +63 -2
- data/lib/lotus/model/adapters/file_system_adapter.rb +11 -0
- data/lib/lotus/model/adapters/memory/query.rb +13 -0
- data/lib/lotus/model/adapters/memory_adapter.rb +9 -0
- data/lib/lotus/model/adapters/sql/collection.rb +63 -11
- data/lib/lotus/model/adapters/sql/query.rb +93 -1
- data/lib/lotus/model/adapters/sql_adapter.rb +35 -5
- data/lib/lotus/model/coercer.rb +74 -0
- data/lib/lotus/model/configuration.rb +1 -1
- data/lib/lotus/model/mapper.rb +2 -2
- data/lib/lotus/model/mapping.rb +2 -2
- data/lib/lotus/model/mapping/attribute.rb +85 -0
- data/lib/lotus/model/mapping/coercers.rb +314 -0
- data/lib/lotus/model/mapping/collection.rb +61 -7
- data/lib/lotus/model/mapping/{coercer.rb → collection_coercer.rb} +7 -9
- data/lib/lotus/model/migrator.rb +2 -1
- data/lib/lotus/model/migrator/adapter.rb +28 -27
- data/lib/lotus/model/migrator/connection.rb +133 -0
- data/lib/lotus/model/migrator/mysql_adapter.rb +2 -2
- data/lib/lotus/model/migrator/postgres_adapter.rb +20 -17
- data/lib/lotus/model/migrator/sqlite_adapter.rb +2 -2
- data/lib/lotus/model/version.rb +1 -1
- data/lib/lotus/repository.rb +134 -18
- data/lotus-model.gemspec +1 -1
- metadata +9 -6
- data/lib/lotus/model/mapping/coercions.rb +0 -192
@@ -0,0 +1,74 @@
|
|
1
|
+
module Lotus
|
2
|
+
module Model
|
3
|
+
# Abstract coercer
|
4
|
+
#
|
5
|
+
# It can be used as super class for custom mapping coercers.
|
6
|
+
#
|
7
|
+
# @since 0.5.0
|
8
|
+
#
|
9
|
+
# @see Lotus::Model::Mapper
|
10
|
+
#
|
11
|
+
# @example Postgres Array
|
12
|
+
# require 'lotus/model/coercer'
|
13
|
+
# require 'sequel/extensions/pg_array'
|
14
|
+
#
|
15
|
+
# class PGArray < Lotus::Model::Coercer
|
16
|
+
# def self.dump(value)
|
17
|
+
# ::Sequel.pg_array(value) rescue nil
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# def self.load(value)
|
21
|
+
# ::Kernel.Array(value) unless value.nil?
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# Lotus::Model.configure do
|
26
|
+
# mapping do
|
27
|
+
# collection :articles do
|
28
|
+
# entity Article
|
29
|
+
# repository ArticleRepository
|
30
|
+
#
|
31
|
+
# attribute :id, Integer
|
32
|
+
# attribute :title, String
|
33
|
+
# attribute :tags, PGArray
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
# end.load!
|
37
|
+
#
|
38
|
+
# # When the entity is serialized, it calls `PGArray.dump` to store `tags`
|
39
|
+
# # as a Postgres Array.
|
40
|
+
# #
|
41
|
+
# # When the record is loaded (unserialized) from the database, it calls
|
42
|
+
# # `PGArray.load` and returns a Ruby Array.
|
43
|
+
class Coercer
|
44
|
+
# Deserialize (load) a value coming from the database into a Ruby object.
|
45
|
+
#
|
46
|
+
# When inheriting from this class, it's a good practice to return <tt>nil</tt>
|
47
|
+
# if the given value it's <tt>nil</tt>.
|
48
|
+
#
|
49
|
+
# @abstract
|
50
|
+
#
|
51
|
+
# @raise [TypeError] if the value can't be coerced
|
52
|
+
#
|
53
|
+
# @since 0.5.0
|
54
|
+
#
|
55
|
+
# @see Lotus::Model::Mapping::Coercers
|
56
|
+
def self.load(value)
|
57
|
+
raise NotImplementedError
|
58
|
+
end
|
59
|
+
|
60
|
+
# Serialize (dump) a Ruby object into a value that can be store by the database.
|
61
|
+
#
|
62
|
+
# @abstract
|
63
|
+
#
|
64
|
+
# @raise [TypeError] if the value can't be coerced
|
65
|
+
#
|
66
|
+
# @since 0.5.0
|
67
|
+
#
|
68
|
+
# @see Lotus::Model::Mapping::Coercers
|
69
|
+
def self.dump(value)
|
70
|
+
self.load(value)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -247,7 +247,7 @@ module Lotus
|
|
247
247
|
# @api private
|
248
248
|
# @since 0.2.0
|
249
249
|
def _build_mapper
|
250
|
-
@mapper = Lotus::Model::Mapper.new(&@mapper_config
|
250
|
+
@mapper = Lotus::Model::Mapper.new(&@mapper_config) if @mapper_config
|
251
251
|
end
|
252
252
|
|
253
253
|
# @api private
|
data/lib/lotus/model/mapper.rb
CHANGED
@@ -65,7 +65,7 @@ module Lotus
|
|
65
65
|
# * #from_record(record) # translates a record into an entity
|
66
66
|
# * #deserialize_*(value) # a set of methods, one for each database column.
|
67
67
|
#
|
68
|
-
# If not given, it uses `Lotus::Model::Mapping::
|
68
|
+
# If not given, it uses `Lotus::Model::Mapping::CollectionCoercer`, by default.
|
69
69
|
#
|
70
70
|
#
|
71
71
|
#
|
@@ -79,7 +79,7 @@ module Lotus
|
|
79
79
|
#
|
80
80
|
# @since 0.1.0
|
81
81
|
def initialize(coercer = nil, &blk)
|
82
|
-
@coercer = coercer || Mapping::
|
82
|
+
@coercer = coercer || Mapping::CollectionCoercer
|
83
83
|
@collections = {}
|
84
84
|
|
85
85
|
instance_eval(&blk) if block_given?
|
data/lib/lotus/model/mapping.rb
CHANGED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'lotus/utils/class'
|
2
|
+
|
3
|
+
module Lotus
|
4
|
+
module Model
|
5
|
+
module Mapping
|
6
|
+
# Mapping attribute
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
# @since 0.5.0
|
10
|
+
class Attribute
|
11
|
+
# @api private
|
12
|
+
# @since 0.5.0
|
13
|
+
COERCERS_NAMESPACE = "Lotus::Model::Mapping::Coercers".freeze
|
14
|
+
|
15
|
+
# Initialize a new attribute
|
16
|
+
#
|
17
|
+
# @param name [#to_sym] attribute name
|
18
|
+
# @param coercer [.load, .dump] a coercer
|
19
|
+
# @param options [Hash] a set of options
|
20
|
+
#
|
21
|
+
# @option options [#to_sym] :as Resolve mismatch between database column
|
22
|
+
# name and entity attribute name
|
23
|
+
#
|
24
|
+
# @return [Lotus::Model::Mapping::Attribute]
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
# @since 0.5.0
|
28
|
+
#
|
29
|
+
# @see Lotus::Model::Coercer
|
30
|
+
# @see Lotus::Model::Mapping::Coercers
|
31
|
+
# @see Lotus::Model::Mapping::Collection#attribute
|
32
|
+
def initialize(name, coercer, options)
|
33
|
+
@name = name.to_sym
|
34
|
+
@coercer = coercer
|
35
|
+
@options = options
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns the mapped name
|
39
|
+
#
|
40
|
+
# @return [Symbol] the mapped name
|
41
|
+
#
|
42
|
+
# @api private
|
43
|
+
# @since 0.5.0
|
44
|
+
#
|
45
|
+
# @see Lotus::Model::Mapping::Collection#attribute
|
46
|
+
def mapped
|
47
|
+
(@options.fetch(:as) { name }).to_sym
|
48
|
+
end
|
49
|
+
|
50
|
+
# @api private
|
51
|
+
# @since 0.5.0
|
52
|
+
def load_coercer
|
53
|
+
"#{ coercer }.load"
|
54
|
+
end
|
55
|
+
|
56
|
+
# @api private
|
57
|
+
# @since 0.5.0
|
58
|
+
def dump_coercer
|
59
|
+
"#{ coercer }.dump"
|
60
|
+
end
|
61
|
+
|
62
|
+
# @api private
|
63
|
+
# @since 0.5.0
|
64
|
+
def ==(other)
|
65
|
+
self.class == other.class &&
|
66
|
+
self.name == other.name &&
|
67
|
+
self.mapped == other.mapped &&
|
68
|
+
self.coercer == other.coercer
|
69
|
+
end
|
70
|
+
|
71
|
+
protected
|
72
|
+
|
73
|
+
# @api private
|
74
|
+
# @since 0.5.0
|
75
|
+
attr_reader :name
|
76
|
+
|
77
|
+
# @api private
|
78
|
+
# @since 0.5.0
|
79
|
+
def coercer
|
80
|
+
Utils::Class.load_from_pattern!("(#{ COERCERS_NAMESPACE }::#{ @coercer }|#{ @coercer })")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,314 @@
|
|
1
|
+
require 'lotus/model/coercer'
|
2
|
+
require 'lotus/utils/kernel'
|
3
|
+
|
4
|
+
module Lotus
|
5
|
+
module Model
|
6
|
+
module Mapping
|
7
|
+
# Default coercers
|
8
|
+
#
|
9
|
+
# @since 0.5.0
|
10
|
+
# @api private
|
11
|
+
module Coercers
|
12
|
+
# Array coercer
|
13
|
+
#
|
14
|
+
# @since 0.5.0
|
15
|
+
# @api private
|
16
|
+
#
|
17
|
+
# @see Lotus::Model::Coercer
|
18
|
+
class Array < Coercer
|
19
|
+
# Transform a value from the database into a Ruby Array, unless nil
|
20
|
+
#
|
21
|
+
# @param value [Object] the object to coerce
|
22
|
+
#
|
23
|
+
# @return [Array] the result of the coercion
|
24
|
+
#
|
25
|
+
# @raise [TypeError] if the value can't be coerced
|
26
|
+
#
|
27
|
+
# @since 0.5.0
|
28
|
+
# @api private
|
29
|
+
#
|
30
|
+
# @see Lotus::Model::Coercer.load
|
31
|
+
# @see http://ruby-doc.org/core/Kernel.html#method-i-Array
|
32
|
+
def self.load(value)
|
33
|
+
::Kernel.Array(value) unless value.nil?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Boolean coercer
|
38
|
+
#
|
39
|
+
# @since 0.5.0
|
40
|
+
# @api private
|
41
|
+
#
|
42
|
+
# @see Lotus::Model::Coercer
|
43
|
+
class Boolean < Coercer
|
44
|
+
# Transform a value from the database into a Boolean, unless nil
|
45
|
+
#
|
46
|
+
# @param value [Object] the object to coerce
|
47
|
+
#
|
48
|
+
# @return [Boolean] the result of the coercion
|
49
|
+
#
|
50
|
+
# @raise [TypeError] if the value can't be coerced
|
51
|
+
#
|
52
|
+
# @since 0.5.0
|
53
|
+
# @api private
|
54
|
+
#
|
55
|
+
# @see Lotus::Model::Coercer.load
|
56
|
+
# @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#Boolean-class_method
|
57
|
+
def self.load(value)
|
58
|
+
Utils::Kernel.Boolean(value) unless value.nil?
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Date coercer
|
63
|
+
#
|
64
|
+
# @since 0.5.0
|
65
|
+
# @api private
|
66
|
+
#
|
67
|
+
# @see Lotus::Model::Coercer
|
68
|
+
class Date < Coercer
|
69
|
+
# Transform a value from the database into a Date, unless nil
|
70
|
+
#
|
71
|
+
# @param value [Object] the object to coerce
|
72
|
+
#
|
73
|
+
# @return [Date] the result of the coercion
|
74
|
+
#
|
75
|
+
# @raise [TypeError] if the value can't be coerced
|
76
|
+
#
|
77
|
+
# @since 0.5.0
|
78
|
+
# @api private
|
79
|
+
#
|
80
|
+
# @see Lotus::Model::Coercer.load
|
81
|
+
# @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#Date-class_method
|
82
|
+
def self.load(value)
|
83
|
+
Utils::Kernel.Date(value) unless value.nil?
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# DateTime coercer
|
88
|
+
#
|
89
|
+
# @since 0.5.0
|
90
|
+
# @api private
|
91
|
+
#
|
92
|
+
# @see Lotus::Model::Coercer
|
93
|
+
class DateTime < Coercer
|
94
|
+
# Transform a value from the database into a DateTime, unless nil
|
95
|
+
#
|
96
|
+
# @param value [Object] the object to coerce
|
97
|
+
#
|
98
|
+
# @return [DateTime] the result of the coercion
|
99
|
+
#
|
100
|
+
# @raise [TypeError] if the value can't be coerced
|
101
|
+
#
|
102
|
+
# @since 0.5.0
|
103
|
+
# @api private
|
104
|
+
#
|
105
|
+
# @see Lotus::Model::Coercer.load
|
106
|
+
# @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#DateTime-class_method
|
107
|
+
def self.load(value)
|
108
|
+
Utils::Kernel.DateTime(value) unless value.nil?
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Float coercer
|
113
|
+
#
|
114
|
+
# @since 0.5.0
|
115
|
+
# @api private
|
116
|
+
#
|
117
|
+
# @see Lotus::Model::Coercer
|
118
|
+
class Float < Coercer
|
119
|
+
# Transform a value from the database into a Float, unless nil
|
120
|
+
#
|
121
|
+
# @param value [Object] the object to coerce
|
122
|
+
#
|
123
|
+
# @return [Float] the result of the coercion
|
124
|
+
#
|
125
|
+
# @raise [TypeError] if the value can't be coerced
|
126
|
+
#
|
127
|
+
# @since 0.5.0
|
128
|
+
# @api private
|
129
|
+
#
|
130
|
+
# @see Lotus::Model::Coercer.load
|
131
|
+
# @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#Float-class_method
|
132
|
+
def self.load(value)
|
133
|
+
Utils::Kernel.Float(value) unless value.nil?
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Hash coercer
|
138
|
+
#
|
139
|
+
# @since 0.5.0
|
140
|
+
# @api private
|
141
|
+
#
|
142
|
+
# @see Lotus::Model::Coercer
|
143
|
+
class Hash < Coercer
|
144
|
+
# Transform a value from the database into a Hash, unless nil
|
145
|
+
#
|
146
|
+
# @param value [Object] the object to coerce
|
147
|
+
#
|
148
|
+
# @return [Hash] the result of the coercion
|
149
|
+
#
|
150
|
+
# @raise [TypeError] if the value can't be coerced
|
151
|
+
#
|
152
|
+
# @since 0.5.0
|
153
|
+
# @api private
|
154
|
+
#
|
155
|
+
# @see Lotus::Model::Coercer.load
|
156
|
+
# @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#Hash-class_method
|
157
|
+
def self.load(value)
|
158
|
+
Utils::Kernel.Hash(value) unless value.nil?
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# Integer coercer
|
163
|
+
#
|
164
|
+
# @since 0.5.0
|
165
|
+
# @api private
|
166
|
+
#
|
167
|
+
# @see Lotus::Model::Coercer
|
168
|
+
class Integer < Coercer
|
169
|
+
# Transform a value from the database into a Integer, unless nil
|
170
|
+
#
|
171
|
+
# @param value [Object] the object to coerce
|
172
|
+
#
|
173
|
+
# @return [Integer] the result of the coercion
|
174
|
+
#
|
175
|
+
# @raise [TypeError] if the value can't be coerced
|
176
|
+
#
|
177
|
+
# @since 0.5.0
|
178
|
+
# @api private
|
179
|
+
#
|
180
|
+
# @see Lotus::Model::Coercer.load
|
181
|
+
# @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#Integer-class_method
|
182
|
+
def self.load(value)
|
183
|
+
Utils::Kernel.Integer(value) unless value.nil?
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# BigDecimal coercer
|
188
|
+
#
|
189
|
+
# @since 0.5.0
|
190
|
+
# @api private
|
191
|
+
#
|
192
|
+
# @see Lotus::Model::Coercer
|
193
|
+
class BigDecimal < Coercer
|
194
|
+
# Transform a value from the database into a BigDecimal, unless nil
|
195
|
+
#
|
196
|
+
# @param value [Object] the object to coerce
|
197
|
+
#
|
198
|
+
# @return [BigDecimal] the result of the coercion
|
199
|
+
#
|
200
|
+
# @raise [TypeError] if the value can't be coerced
|
201
|
+
#
|
202
|
+
# @since 0.5.0
|
203
|
+
# @api private
|
204
|
+
#
|
205
|
+
# @see Lotus::Model::Coercer.load
|
206
|
+
# @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#BigDecimal-class_method
|
207
|
+
def self.load(value)
|
208
|
+
Utils::Kernel.BigDecimal(value) unless value.nil?
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# Set coercer
|
213
|
+
#
|
214
|
+
# @since 0.5.0
|
215
|
+
# @api private
|
216
|
+
#
|
217
|
+
# @see Lotus::Model::Coercer
|
218
|
+
class Set < Coercer
|
219
|
+
# Transform a value from the database into a Set, unless nil
|
220
|
+
#
|
221
|
+
# @param value [Object] the object to coerce
|
222
|
+
#
|
223
|
+
# @return [Set] the result of the coercion
|
224
|
+
#
|
225
|
+
# @raise [TypeError] if the value can't be coerced
|
226
|
+
#
|
227
|
+
# @since 0.5.0
|
228
|
+
# @api private
|
229
|
+
#
|
230
|
+
# @see Lotus::Model::Coercer.load
|
231
|
+
# @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#Set-class_method
|
232
|
+
def self.load(value)
|
233
|
+
Utils::Kernel.Set(value) unless value.nil?
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
# String coercer
|
238
|
+
#
|
239
|
+
# @since 0.5.0
|
240
|
+
# @api private
|
241
|
+
#
|
242
|
+
# @see Lotus::Model::Coercer
|
243
|
+
class String < Coercer
|
244
|
+
# Transform a value from the database into a String, unless nil
|
245
|
+
#
|
246
|
+
# @param value [Object] the object to coerce
|
247
|
+
#
|
248
|
+
# @return [String] the result of the coercion
|
249
|
+
#
|
250
|
+
# @raise [TypeError] if the value can't be coerced
|
251
|
+
#
|
252
|
+
# @since 0.5.0
|
253
|
+
# @api private
|
254
|
+
#
|
255
|
+
# @see Lotus::Model::Coercer.load
|
256
|
+
# @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#String-class_method
|
257
|
+
def self.load(value)
|
258
|
+
Utils::Kernel.String(value) unless value.nil?
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# Symbol coercer
|
263
|
+
#
|
264
|
+
# @since 0.5.0
|
265
|
+
# @api private
|
266
|
+
#
|
267
|
+
# @see Lotus::Model::Coercer
|
268
|
+
class Symbol < Coercer
|
269
|
+
# Transform a value from the database into a Symbol, unless nil
|
270
|
+
#
|
271
|
+
# @param value [Object] the object to coerce
|
272
|
+
#
|
273
|
+
# @return [Symbol] the result of the coercion
|
274
|
+
#
|
275
|
+
# @raise [TypeError] if the value can't be coerced
|
276
|
+
#
|
277
|
+
# @since 0.5.0
|
278
|
+
# @api private
|
279
|
+
#
|
280
|
+
# @see Lotus::Model::Coercer.load
|
281
|
+
# @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#Symbol-class_method
|
282
|
+
def self.load(value)
|
283
|
+
Utils::Kernel.Symbol(value) unless value.nil?
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
# Time coercer
|
288
|
+
#
|
289
|
+
# @since 0.5.0
|
290
|
+
# @api private
|
291
|
+
#
|
292
|
+
# @see Lotus::Model::Coercer
|
293
|
+
class Time < Coercer
|
294
|
+
# Transform a value from the database into a Time, unless nil
|
295
|
+
#
|
296
|
+
# @param value [Object] the object to coerce
|
297
|
+
#
|
298
|
+
# @return [Time] the result of the coercion
|
299
|
+
#
|
300
|
+
# @raise [TypeError] if the value can't be coerced
|
301
|
+
#
|
302
|
+
# @since 0.5.0
|
303
|
+
# @api private
|
304
|
+
#
|
305
|
+
# @see Lotus::Model::Coercer.load
|
306
|
+
# @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#Time-class_method
|
307
|
+
def self.load(value)
|
308
|
+
Utils::Kernel.Time(value) unless value.nil?
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|