hanami-model 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -0
  3. data/README.md +54 -420
  4. data/hanami-model.gemspec +9 -6
  5. data/lib/hanami/entity.rb +107 -191
  6. data/lib/hanami/entity/schema.rb +236 -0
  7. data/lib/hanami/model.rb +52 -138
  8. data/lib/hanami/model/association.rb +37 -0
  9. data/lib/hanami/model/associations/belongs_to.rb +19 -0
  10. data/lib/hanami/model/associations/dsl.rb +29 -0
  11. data/lib/hanami/model/associations/has_many.rb +200 -0
  12. data/lib/hanami/model/configuration.rb +52 -224
  13. data/lib/hanami/model/configurator.rb +62 -0
  14. data/lib/hanami/model/entity_name.rb +35 -0
  15. data/lib/hanami/model/error.rb +37 -24
  16. data/lib/hanami/model/mapping.rb +29 -35
  17. data/lib/hanami/model/migration.rb +31 -0
  18. data/lib/hanami/model/migrator.rb +111 -88
  19. data/lib/hanami/model/migrator/adapter.rb +39 -16
  20. data/lib/hanami/model/migrator/connection.rb +23 -11
  21. data/lib/hanami/model/migrator/mysql_adapter.rb +38 -17
  22. data/lib/hanami/model/migrator/postgres_adapter.rb +20 -19
  23. data/lib/hanami/model/migrator/sqlite_adapter.rb +9 -8
  24. data/lib/hanami/model/plugins.rb +25 -0
  25. data/lib/hanami/model/plugins/mapping.rb +55 -0
  26. data/lib/hanami/model/plugins/schema.rb +55 -0
  27. data/lib/hanami/model/plugins/timestamps.rb +118 -0
  28. data/lib/hanami/model/relation_name.rb +24 -0
  29. data/lib/hanami/model/sql.rb +161 -0
  30. data/lib/hanami/model/sql/console.rb +41 -0
  31. data/lib/hanami/model/sql/consoles/abstract.rb +33 -0
  32. data/lib/hanami/model/sql/consoles/mysql.rb +63 -0
  33. data/lib/hanami/model/sql/consoles/postgresql.rb +68 -0
  34. data/lib/hanami/model/sql/consoles/sqlite.rb +46 -0
  35. data/lib/hanami/model/sql/entity/schema.rb +125 -0
  36. data/lib/hanami/model/sql/types.rb +95 -0
  37. data/lib/hanami/model/sql/types/schema/coercions.rb +198 -0
  38. data/lib/hanami/model/types.rb +99 -0
  39. data/lib/hanami/model/version.rb +1 -1
  40. data/lib/hanami/repository.rb +287 -723
  41. metadata +77 -40
  42. data/EXAMPLE.md +0 -213
  43. data/lib/hanami/entity/dirty_tracking.rb +0 -74
  44. data/lib/hanami/model/adapters/abstract.rb +0 -281
  45. data/lib/hanami/model/adapters/file_system_adapter.rb +0 -288
  46. data/lib/hanami/model/adapters/implementation.rb +0 -111
  47. data/lib/hanami/model/adapters/memory/collection.rb +0 -132
  48. data/lib/hanami/model/adapters/memory/command.rb +0 -113
  49. data/lib/hanami/model/adapters/memory/query.rb +0 -653
  50. data/lib/hanami/model/adapters/memory_adapter.rb +0 -179
  51. data/lib/hanami/model/adapters/null_adapter.rb +0 -24
  52. data/lib/hanami/model/adapters/sql/collection.rb +0 -287
  53. data/lib/hanami/model/adapters/sql/command.rb +0 -88
  54. data/lib/hanami/model/adapters/sql/console.rb +0 -33
  55. data/lib/hanami/model/adapters/sql/consoles/mysql.rb +0 -49
  56. data/lib/hanami/model/adapters/sql/consoles/postgresql.rb +0 -48
  57. data/lib/hanami/model/adapters/sql/consoles/sqlite.rb +0 -26
  58. data/lib/hanami/model/adapters/sql/query.rb +0 -788
  59. data/lib/hanami/model/adapters/sql_adapter.rb +0 -296
  60. data/lib/hanami/model/coercer.rb +0 -74
  61. data/lib/hanami/model/config/adapter.rb +0 -116
  62. data/lib/hanami/model/config/mapper.rb +0 -45
  63. data/lib/hanami/model/mapper.rb +0 -124
  64. data/lib/hanami/model/mapping/attribute.rb +0 -85
  65. data/lib/hanami/model/mapping/coercers.rb +0 -314
  66. data/lib/hanami/model/mapping/collection.rb +0 -490
  67. data/lib/hanami/model/mapping/collection_coercer.rb +0 -79
@@ -1,179 +0,0 @@
1
- require 'hanami/model/adapters/abstract'
2
- require 'hanami/model/adapters/implementation'
3
- require 'hanami/model/adapters/memory/collection'
4
- require 'hanami/model/adapters/memory/command'
5
- require 'hanami/model/adapters/memory/query'
6
-
7
- module Hanami
8
- module Model
9
- module Adapters
10
- # In memory adapter that behaves like a SQL database.
11
- # Not all the features of the SQL adapter are supported.
12
- #
13
- # This adapter SHOULD be used only for development or testing purposes,
14
- # because its computations are inefficient and the data is volatile.
15
- #
16
- # @see Hanami::Model::Adapters::Implementation
17
- #
18
- # @api private
19
- # @since 0.1.0
20
- class MemoryAdapter < Abstract
21
- include Implementation
22
-
23
- # Initialize the adapter.
24
- #
25
- # @param mapper [Object] the database mapper
26
- # @param uri [String] the connection uri (ignored)
27
- # @param options [Hash] a hash of non mandatory adapter options
28
- #
29
- # @return [Hanami::Model::Adapters::MemoryAdapter]
30
- #
31
- # @see Hanami::Model::Mapper
32
- #
33
- # @api private
34
- # @since 0.1.0
35
- def initialize(mapper, uri = nil, options = {})
36
- super
37
-
38
- @mutex = Mutex.new
39
- @collections = {}
40
- end
41
-
42
- # Creates a record in the database for the given entity.
43
- # It assigns the `id` attribute, in case of success.
44
- #
45
- # @param collection [Symbol] the target collection (it must be mapped).
46
- # @param entity [#id=] the entity to create
47
- #
48
- # @return [Object] the entity
49
- #
50
- # @api private
51
- # @since 0.1.0
52
- def create(collection, entity)
53
- synchronize do
54
- command(collection).create(entity)
55
- end
56
- end
57
-
58
- # Updates a record in the database corresponding to the given entity.
59
- #
60
- # @param collection [Symbol] the target collection (it must be mapped).
61
- # @param entity [#id] the entity to update
62
- #
63
- # @return [Object] the entity
64
- #
65
- # @api private
66
- # @since 0.1.0
67
- def update(collection, entity)
68
- synchronize do
69
- command(collection).update(entity)
70
- end
71
- end
72
-
73
- # Deletes a record in the database corresponding to the given entity.
74
- #
75
- # @param collection [Symbol] the target collection (it must be mapped).
76
- # @param entity [#id] the entity to delete
77
- #
78
- # @api private
79
- # @since 0.1.0
80
- def delete(collection, entity)
81
- synchronize do
82
- command(collection).delete(entity)
83
- end
84
- end
85
-
86
- # Deletes all the records from the given collection and resets the
87
- # identity counter.
88
- #
89
- # @param collection [Symbol] the target collection (it must be mapped).
90
- #
91
- # @api private
92
- # @since 0.1.0
93
- def clear(collection)
94
- synchronize do
95
- command(collection).clear
96
- end
97
- end
98
-
99
- # Fabricates a command for the given query.
100
- #
101
- # @param collection [Symbol] the collection name (it must be mapped)
102
- #
103
- # @return [Hanami::Model::Adapters::Memory::Command]
104
- #
105
- # @see Hanami::Model::Adapters::Memory::Command
106
- #
107
- # @api private
108
- # @since 0.1.0
109
- def command(collection)
110
- Memory::Command.new(_collection(collection), _mapped_collection(collection))
111
- end
112
-
113
- # Fabricates a query
114
- #
115
- # @param collection [Symbol] the target collection (it must be mapped).
116
- # @param blk [Proc] a block of code to be executed in the context of
117
- # the query.
118
- #
119
- # @return [Hanami::Model::Adapters::Memory::Query]
120
- #
121
- # @see Hanami::Model::Adapters::Memory::Query
122
- #
123
- # @api private
124
- # @since 0.1.0
125
- def query(collection, context = nil, &blk)
126
- synchronize do
127
- Memory::Query.new(_collection(collection), _mapped_collection(collection), &blk)
128
- end
129
- end
130
-
131
- # WARNING: this is a no-op. For "real" transactions please use
132
- # `SqlAdapter` or another adapter that supports them
133
- #
134
- # @param options [Hash] options for transaction
135
- #
136
- # @see Hanami::Model::Adapters::SqlAdapter#transaction
137
- # @see Hanami::Model::Adapters::Abstract#transaction
138
- #
139
- # @since 0.2.3
140
- def transaction(options = {})
141
- yield
142
- end
143
-
144
- # @api private
145
- # @since 0.5.0
146
- #
147
- # @see Hanami::Model::Adapters::Abstract#disconnect
148
- def disconnect
149
- @collections = DisconnectedResource.new
150
- @mutex = DisconnectedResource.new
151
- end
152
-
153
- private
154
-
155
- # Returns a collection from the given name.
156
- #
157
- # @param name [Symbol] a name of the collection (it must be mapped).
158
- #
159
- # @return [Hanami::Model::Adapters::Memory::Collection]
160
- #
161
- # @see Hanami::Model::Adapters::Memory::Collection
162
- #
163
- # @api private
164
- # @since 0.1.0
165
- def _collection(name)
166
- @collections[name] ||= Memory::Collection.new(name, _identity(name))
167
- end
168
-
169
- # Executes the given block within a critical section.
170
- #
171
- # @api private
172
- # @since 0.2.0
173
- def synchronize
174
- @mutex.synchronize { yield }
175
- end
176
- end
177
- end
178
- end
179
- end
@@ -1,24 +0,0 @@
1
- require 'hanami/model/error'
2
-
3
- module Hanami
4
- module Model
5
- module Adapters
6
- # @since 0.2.0
7
- class NoAdapterError < Hanami::Model::Error
8
- def initialize(method_name)
9
- super("Cannot invoke `#{ method_name }' on repository. "\
10
- "Please check if `adapter' and `mapping' are set, "\
11
- "and that you call `.load!' on the configuration.")
12
- end
13
- end
14
-
15
- # @since 0.2.0
16
- # @api private
17
- class NullAdapter
18
- def method_missing(m, *args)
19
- raise NoAdapterError.new(m)
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,287 +0,0 @@
1
- require 'delegate'
2
- require 'hanami/utils/kernel' unless RUBY_VERSION >= '2.1'
3
-
4
- module Hanami
5
- module Model
6
- module Adapters
7
- module Sql
8
- # Maps a SQL database table and perfoms manipulations on it.
9
- #
10
- # @api private
11
- # @since 0.1.0
12
- #
13
- # @see http://sequel.jeremyevans.net/rdoc/files/doc/dataset_basics_rdoc.html
14
- # @see http://sequel.jeremyevans.net/rdoc/files/doc/dataset_filtering_rdoc.html
15
- class Collection < SimpleDelegator
16
- # Initialize a collection
17
- #
18
- # @param dataset [Sequel::Dataset] the dataset that maps a table or a
19
- # subset of it.
20
- # @param mapped_collection [Hanami::Model::Mapping::Collection] a
21
- # mapped collection
22
- #
23
- # @return [Hanami::Model::Adapters::Sql::Collection]
24
- #
25
- # @api private
26
- # @since 0.1.0
27
- def initialize(dataset, mapped_collection)
28
- super(dataset)
29
- @mapped_collection = mapped_collection
30
- end
31
-
32
- # Filters the current scope with an `exclude` directive.
33
- #
34
- # @param args [Array] the array of arguments
35
- #
36
- # @see Hanami::Model::Adapters::Sql::Query#exclude
37
- #
38
- # @return [Hanami::Model::Adapters::Sql::Collection] the filtered
39
- # collection
40
- #
41
- # @api private
42
- # @since 0.1.0
43
- def exclude(*args)
44
- Collection.new(super, @mapped_collection)
45
- end
46
-
47
- # Creates a record for the given entity and assigns an id.
48
- #
49
- # @param entity [Object] the entity to persist
50
- #
51
- # @see Hanami::Model::Adapters::Sql::Command#create
52
- #
53
- # @return the primary key of the created record
54
- #
55
- # @api private
56
- # @since 0.1.0
57
- def insert(entity)
58
- serialized_entity = _serialize(entity)
59
- serialized_entity[identity] = super(serialized_entity)
60
-
61
- _deserialize(serialized_entity)
62
- end
63
-
64
- # Filters the current scope with a `limit` directive.
65
- #
66
- # @param args [Array] the array of arguments
67
- #
68
- # @see Hanami::Model::Adapters::Sql::Query#limit
69
- #
70
- # @return [Hanami::Model::Adapters::Sql::Collection] the filtered
71
- # collection
72
- #
73
- # @api private
74
- # @since 0.1.0
75
- def limit(*args)
76
- Collection.new(super, @mapped_collection)
77
- end
78
-
79
- # Filters the current scope with an `offset` directive.
80
- #
81
- # @param args [Array] the array of arguments
82
- #
83
- # @see Hanami::Model::Adapters::Sql::Query#offset
84
- #
85
- # @return [Hanami::Model::Adapters::Sql::Collection] the filtered
86
- # collection
87
- #
88
- # @api private
89
- # @since 0.1.0
90
- def offset(*args)
91
- Collection.new(super, @mapped_collection)
92
- end
93
-
94
- # Filters the current scope with an `or` directive.
95
- #
96
- # @param args [Array] the array of arguments
97
- #
98
- # @see Hanami::Model::Adapters::Sql::Query#or
99
- #
100
- # @return [Hanami::Model::Adapters::Sql::Collection] the filtered
101
- # collection
102
- #
103
- # @api private
104
- # @since 0.1.0
105
- def or(*args)
106
- Collection.new(super, @mapped_collection)
107
- end
108
-
109
- # Filters the current scope with an `order` directive.
110
- #
111
- # @param args [Array] the array of arguments
112
- #
113
- # @see Hanami::Model::Adapters::Sql::Query#order
114
- #
115
- # @return [Hanami::Model::Adapters::Sql::Collection] the filtered
116
- # collection
117
- #
118
- # @api private
119
- # @since 0.1.0
120
- def order(*args)
121
- Collection.new(super, @mapped_collection)
122
- end
123
-
124
- # Filters the current scope with an `order` directive.
125
- #
126
- # @param args [Array] the array of arguments
127
- #
128
- # @see Hanami::Model::Adapters::Sql::Query#order
129
- #
130
- # @return [Hanami::Model::Adapters::Sql::Collection] the filtered
131
- # collection
132
- #
133
- # @api private
134
- # @since 0.1.0
135
- def order_more(*args)
136
- Collection.new(super, @mapped_collection)
137
- end
138
-
139
- # Filters the current scope with a `select` directive.
140
- #
141
- # @param args [Array] the array of arguments
142
- #
143
- # @see Hanami::Model::Adapters::Sql::Query#select
144
- #
145
- # @return [Hanami::Model::Adapters::Sql::Collection] the filtered
146
- # collection
147
- #
148
- # @api private
149
- # @since 0.1.0
150
- if RUBY_VERSION >= '2.1'
151
- def select(*args)
152
- Collection.new(super, @mapped_collection)
153
- end
154
- else
155
- def select(*args)
156
- Collection.new(__getobj__.select(*Hanami::Utils::Kernel.Array(args)), @mapped_collection)
157
- end
158
- end
159
-
160
-
161
- # Filters the current scope with a `group` directive.
162
- #
163
- # @param args [Array] the array of arguments
164
- #
165
- # @see Hanami::Model::Adapters::Sql::Query#group
166
- #
167
- # @return [Hanami::Model::Adapters::Sql::Collection] the filtered
168
- # collection
169
- #
170
- # @api private
171
- # @since 0.5.0
172
- def group(*args)
173
- Collection.new(super, @mapped_collection)
174
- end
175
-
176
- # Filters the current scope with a `where` directive.
177
- #
178
- # @param args [Array] the array of arguments
179
- #
180
- # @see Hanami::Model::Adapters::Sql::Query#where
181
- #
182
- # @return [Hanami::Model::Adapters::Sql::Collection] the filtered
183
- # collection
184
- #
185
- # @api private
186
- # @since 0.1.0
187
- def where(*args)
188
- Collection.new(super, @mapped_collection)
189
- end
190
-
191
- # Updates the record corresponding to the given entity.
192
- #
193
- # @param entity [Object] the entity to persist
194
- #
195
- # @see Hanami::Model::Adapters::Sql::Command#update
196
- #
197
- # @api private
198
- # @since 0.1.0
199
- def update(entity)
200
- serialized_entity = _serialize(entity)
201
- super(serialized_entity)
202
-
203
- _deserialize(serialized_entity)
204
- end
205
-
206
- # Resolves self by fetching the records from the database and
207
- # translating them into entities.
208
- #
209
- # @return [Array] the result of the query
210
- #
211
- # @api private
212
- # @since 0.1.0
213
- def to_a
214
- @mapped_collection.deserialize(self)
215
- end
216
-
217
- # Select all attributes for current scope
218
- #
219
- # @return [Hanami::Model::Adapters::Sql::Collection] the filtered
220
- # collection
221
- #
222
- # @api private
223
- # @since 0.5.0
224
- #
225
- # @see http://www.rubydoc.info/github/jeremyevans/sequel/Sequel%2FDataset%3Aselect_all
226
- def select_all
227
- Collection.new(super(table_name), @mapped_collection)
228
- end
229
-
230
- # Use join table for current scope
231
- #
232
- # @return [Hanami::Model::Adapters::Sql::Collection] the filtered
233
- # collection
234
- #
235
- # @api private
236
- # @since 0.5.0
237
- #
238
- # @see http://www.rubydoc.info/github/jeremyevans/sequel/Sequel%2FDataset%3Ajoin_table
239
- def join_table(*args)
240
- Collection.new(super, @mapped_collection)
241
- end
242
-
243
- # Return table name mapped collection
244
- #
245
- # @return [String] table name
246
- #
247
- # @api private
248
- # @since 0.5.0
249
- def table_name
250
- @mapped_collection.name
251
- end
252
-
253
- # Name of the identity column in database
254
- #
255
- # @return [Symbol] the identity name
256
- #
257
- # @api private
258
- # @since 0.5.0
259
- def identity
260
- @mapped_collection.identity
261
- end
262
-
263
- private
264
- # Serialize the given entity before to persist in the database.
265
- #
266
- # @return [Hash] the serialized entity
267
- #
268
- # @api private
269
- # @since 0.1.0
270
- def _serialize(entity)
271
- @mapped_collection.serialize(entity)
272
- end
273
-
274
- # Deserialize the given entity after it was persisted in the database.
275
- #
276
- # @return [Hanami::Entity] the deserialized entity
277
- #
278
- # @api private
279
- # @since 0.2.2
280
- def _deserialize(entity)
281
- @mapped_collection.deserialize([entity]).first
282
- end
283
- end
284
- end
285
- end
286
- end
287
- end