rom-repository 1.4.0 → 2.0.0.beta1

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -6
  3. data/{LICENSE.txt → LICENSE} +1 -1
  4. data/README.md +18 -1
  5. data/lib/rom-repository.rb +1 -2
  6. data/lib/rom/repository.rb +9 -216
  7. data/lib/rom/repository/class_interface.rb +16 -33
  8. data/lib/rom/repository/relation_reader.rb +46 -0
  9. data/lib/rom/repository/root.rb +3 -59
  10. data/lib/rom/repository/version.rb +1 -1
  11. metadata +9 -98
  12. data/.gitignore +0 -3
  13. data/.rspec +0 -3
  14. data/.travis.yml +0 -27
  15. data/.yardopts +0 -2
  16. data/Gemfile +0 -38
  17. data/Rakefile +0 -19
  18. data/lib/rom/open_struct.rb +0 -35
  19. data/lib/rom/repository/changeset.rb +0 -155
  20. data/lib/rom/repository/changeset/associated.rb +0 -100
  21. data/lib/rom/repository/changeset/create.rb +0 -16
  22. data/lib/rom/repository/changeset/delete.rb +0 -17
  23. data/lib/rom/repository/changeset/pipe.rb +0 -97
  24. data/lib/rom/repository/changeset/restricted.rb +0 -28
  25. data/lib/rom/repository/changeset/stateful.rb +0 -282
  26. data/lib/rom/repository/changeset/update.rb +0 -82
  27. data/lib/rom/repository/command_compiler.rb +0 -257
  28. data/lib/rom/repository/command_proxy.rb +0 -26
  29. data/lib/rom/repository/header_builder.rb +0 -65
  30. data/lib/rom/repository/mapper_builder.rb +0 -23
  31. data/lib/rom/repository/relation_proxy.rb +0 -337
  32. data/lib/rom/repository/relation_proxy/combine.rb +0 -320
  33. data/lib/rom/repository/relation_proxy/wrap.rb +0 -78
  34. data/lib/rom/repository/struct_builder.rb +0 -83
  35. data/lib/rom/struct.rb +0 -113
  36. data/log/.gitkeep +0 -0
  37. data/rom-repository.gemspec +0 -23
  38. data/spec/integration/changeset_spec.rb +0 -193
  39. data/spec/integration/command_macros_spec.rb +0 -191
  40. data/spec/integration/command_spec.rb +0 -228
  41. data/spec/integration/multi_adapter_spec.rb +0 -73
  42. data/spec/integration/repository/aggregate_spec.rb +0 -58
  43. data/spec/integration/repository_spec.rb +0 -406
  44. data/spec/integration/root_repository_spec.rb +0 -106
  45. data/spec/integration/typed_structs_spec.rb +0 -64
  46. data/spec/shared/database.rb +0 -79
  47. data/spec/shared/mappers.rb +0 -35
  48. data/spec/shared/models.rb +0 -41
  49. data/spec/shared/plugins.rb +0 -66
  50. data/spec/shared/relations.rb +0 -115
  51. data/spec/shared/repo.rb +0 -86
  52. data/spec/shared/seeds.rb +0 -30
  53. data/spec/shared/structs.rb +0 -140
  54. data/spec/spec_helper.rb +0 -83
  55. data/spec/support/mapper_registry.rb +0 -9
  56. data/spec/support/mutant.rb +0 -10
  57. data/spec/unit/changeset/associate_spec.rb +0 -120
  58. data/spec/unit/changeset/map_spec.rb +0 -111
  59. data/spec/unit/changeset_spec.rb +0 -186
  60. data/spec/unit/relation_proxy_spec.rb +0 -202
  61. data/spec/unit/repository/changeset_spec.rb +0 -197
  62. data/spec/unit/repository/inspect_spec.rb +0 -18
  63. data/spec/unit/repository/session_spec.rb +0 -251
  64. data/spec/unit/repository/transaction_spec.rb +0 -42
  65. data/spec/unit/session_spec.rb +0 -46
  66. data/spec/unit/struct_builder_spec.rb +0 -128
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 60e1932a1540f3a5db52bbb5a4ae073b83ee0289
4
- data.tar.gz: 8a430f76a00792c4d12d94d8271b0736310dc20b
3
+ metadata.gz: 748ea9ec748c486d611e4ac107cf338362a76b51
4
+ data.tar.gz: 111dd4763fbe363d22e4fe0179e52c3a0d343531
5
5
  SHA512:
6
- metadata.gz: 514906df2e8c7c3b33fb3cce5083d65f4b238ca1aa7ca03df9d736f0ceb4752b610d66937e372645cc0f71dd7a0d845cbcdeca27a69a8ca13a367bf75a42b3e8
7
- data.tar.gz: a75e84fd982d615e4f57802a130658d5d0482c62bf0216f6cf70c6c348c4b99d50561cdcd33de73f6b7ff3700fc15702d4023711b2fe0c0c599b184dc45a77b4
6
+ metadata.gz: 4027a4c8fd3cacfb40a6f0ffe99bae2d88b0e98cd3a8993ef83b6a07e2fac9510e528578b71a1abb673dea61e9dd93b832406a002d7b80e457d1abfc66174549
7
+ data.tar.gz: 5f45222483b70724de8837fa0e2d3cb87737f5acf6944fbccd3c26fc110dd2b5c9d52a76082902a29d3d96a17a8053c131af62214bcb56412ddb74662843871d
data/CHANGELOG.md CHANGED
@@ -1,17 +1,25 @@
1
- # v1.4.0 2017-07-04
1
+ # v2.0.0 to-be-released
2
2
 
3
- ### Added
3
+ ### Changed
4
+
5
+ * [BREAKING] `Relation#combine` no longer works with arbitrary `many` and `one` options. Configure associations instead and use their identifiers as arguments (solnic)
6
+ * [BREAKING] `Relation#combine_parents` was removed (solnic)
7
+ * [BREAKING] `Relation#combine_children` was removed (solnic)
8
+ * [BREAKING] `Relation#wrap_parent` was removed, configure associations and use their identifiers in `wrap` instead (solnic)
9
+ * [BREAKING] `Repository#command` was removed in favor of `Relation#command` (solnic)
4
10
 
5
- * `Relation#map_to` available in repository relations to ease upgrade to rom 4.0 (solnic)
6
- * Deprecation warnings in preparation for rom 4.0 release (solnic)
11
+ ### Internal
7
12
 
8
- [Compare v1.3.3...v1.3.4](https://github.com/rom-rb/rom-repository/compare/v1.3.3...v1.3.4)
13
+ * `RelationProxy` was removed as its functionality was ported and improved in rom-core (solnic)
9
14
 
10
15
  # v1.3.3 2017-05-31
11
16
 
12
17
  ### Added
13
18
 
14
- * `Changeset#extend` to exclude steps from the `#diff` output, this allows to filter out timestamp changes prior to updates so that we can avoid hitting the database in case of timestamp-only changes. You still can call `.map(:touch)` if you want to have `updated_at` refreshed unconditionally (flash-gordon)
19
+ * `Changeset#extend` to exclude steps from the `#diff` output, this allows
20
+ to filter out timestamp changes prior to updates so that we can avoid
21
+ hitting the database in case of timestamp-only changes. You still can call `.map(:touch)`
22
+ if you want to have `updated_at` refreshed unconditionally (flash-gordon)
15
23
 
16
24
  ## Fixed
17
25
 
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014 Piotr Solnica
1
+ Copyright (c) 2014-2017 Piotr Solnica
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -1 +1,18 @@
1
- # This project was moved to [rom-rb/rom](https://github.com/rom-rb/rom/tree/master/repository)
1
+ [gem]: https://rubygems.org/gems/rom-repository
2
+ [gemnasium]: https://gemnasium.com/rom-rb/rom-repository
3
+
4
+ # rom-repository
5
+
6
+ [![Gem Version](https://badge.fury.io/rb/rom-repository.svg)][gem]
7
+ [![Dependency Status](https://gemnasium.com/rom-rb/rom-repository.svg)][gemnasium]
8
+
9
+ Repositories for [rom-rb](https://github.com/rom-rb/rom) with auto-mapping, changesets and commands.
10
+
11
+ Resources:
12
+
13
+ * [User documentation](http://rom-rb.org/learn/repositories)
14
+ * [API documentation](http://rubydoc.info/gems/rom-repository)
15
+
16
+ ## License
17
+
18
+ See `LICENSE` file.
@@ -1,3 +1,2 @@
1
- require 'rom'
2
-
1
+ require 'rom/core'
3
2
  require 'rom/repository'
@@ -2,11 +2,6 @@ require 'dry/core/deprecations'
2
2
 
3
3
  require 'rom/initializer'
4
4
  require 'rom/repository/class_interface'
5
- require 'rom/repository/mapper_builder'
6
- require 'rom/repository/relation_proxy'
7
- require 'rom/repository/command_compiler'
8
-
9
- require 'rom/repository/changeset'
10
5
  require 'rom/repository/session'
11
6
 
12
7
  module ROM
@@ -55,13 +50,6 @@ module ROM
55
50
  #
56
51
  # @api public
57
52
  class Repository
58
- # Mapping for supported changeset classes used in #changeset(type => relation) method
59
- CHANGESET_TYPES = {
60
- create: Changeset::Create,
61
- update: Changeset::Update,
62
- delete: Changeset::Delete
63
- }.freeze
64
-
65
53
  extend ClassInterface
66
54
  extend Initializer
67
55
  extend Dry::Core::ClassAttributes
@@ -86,6 +74,11 @@ module ROM
86
74
  # Get or set struct namespace
87
75
  defines :struct_namespace
88
76
 
77
+ # @!method self.relation_reader
78
+ # Get or set relation reader module
79
+ # @return [RelationReader]
80
+ defines :relation_reader
81
+
89
82
  struct_namespace ROM::Struct
90
83
 
91
84
  # @!attribute [r] container
@@ -104,175 +97,15 @@ module ROM
104
97
  # @return [RelationRegistry] The relation proxy registry used by a repo
105
98
  attr_reader :relations
106
99
 
107
- # @!attribute [r] mappers
108
- # @return [MapperBuilder] The auto-generated mappers for repo relations
109
- attr_reader :mappers
110
-
111
- # @!attribute [r] commmand_compiler
112
- # @return [Method] Function for compiling commands bound to a repo instance
113
- attr_reader :command_compiler
114
-
115
100
  # Initializes a new repo by establishing configured relation proxies from
116
101
  # the passed container
117
102
  #
118
103
  # @param container [ROM::Container] The rom container with relations and optional commands
119
104
  #
120
- # @api public
121
- def initialize(container, opts = EMPTY_HASH)
105
+ # @api private
106
+ def initialize(container, options = EMPTY_HASH)
122
107
  super
123
-
124
- @mappers = MapperBuilder.new(struct_namespace: struct_namespace)
125
-
126
- @relations = RelationRegistry.new do |registry, relations|
127
- self.class.relations.each do |name|
128
- relation = container.relations[name]
129
- relation = relation.with(mappers: container.mappers[name]) if container.mappers.key?(name)
130
-
131
- proxy = RelationProxy.new(
132
- relation, name: name, mappers: mappers, registry: registry, auto_struct: auto_struct
133
- )
134
-
135
- instance_variable_set("@#{name}", proxy)
136
-
137
- relations[name] = proxy
138
- end
139
- end
140
-
141
- @command_compiler = method(:command)
142
- end
143
-
144
- # Return a command for a relation
145
- #
146
- # @overload command(type, relation)
147
- # Returns a command for a relation
148
- #
149
- # @example
150
- # repo.command(:create, repo.users)
151
- #
152
- # @param type [Symbol] The command type (:create, :update or :delete)
153
- # @param relation [RelationProxy] The relation for which command should be built for
154
- #
155
- # @overload command(options)
156
- # Builds a command for a given relation identifier
157
- #
158
- # @example
159
- # repo.command(create: :users)
160
- #
161
- # @param options [Hash<Symbol=>Symbol>] A type => rel_name map
162
- #
163
- # @overload command(rel_name)
164
- # Returns command registry for a given relation identifier
165
- #
166
- # @example
167
- # repo.command(:users)[:my_custom_command]
168
- #
169
- # @param rel_name [Symbol] The relation identifier from the container
170
- #
171
- # @return [CommandRegistry]
172
- #
173
- # @overload command(rel_name, &block)
174
- # Yields a command graph composer for a given relation identifier
175
- #
176
- # @param rel_name [Symbol] The relation identifier from the container
177
- #
178
- # @return [ROM::Command]
179
- #
180
- # @api public
181
- def command(*args, **opts, &block)
182
- all_args = args + opts.to_a.flatten
183
-
184
- if all_args.size > 1
185
- commands.fetch_or_store(all_args.hash) do
186
- compile_command(*args, **opts)
187
- end
188
- else
189
- container.command(*args, &block)
190
- end
191
- end
192
-
193
- # Return a changeset for a relation
194
- #
195
- # @overload changeset(name, attributes)
196
- # Return a create changeset for a given relation identifier
197
- #
198
- # @example
199
- # repo.changeset(:users, name: "Jane")
200
- #
201
- # @param name [Symbol] The relation container identifier
202
- # @param attributes [Hash]
203
- #
204
- # @return [Changeset::Create]
205
- #
206
- # @overload changeset(name, primary_key, attributes)
207
- # Return an update changeset for a given relation identifier
208
- #
209
- # @example
210
- # repo.changeset(:users, 1, name: "Jane Doe")
211
- #
212
- # @param name [Symbol] The relation container identifier
213
- # @param restriction_arg [Object] The argument passed to restricted view
214
- #
215
- # @return [Changeset::Update]
216
- #
217
- # @overload changeset(changeset_class)
218
- # Return a changeset object using provided class
219
- #
220
- # @example
221
- # repo.changeset(NewUserChangeset).data(attributes)
222
- #
223
- # @param [Class] changeset_class Custom changeset class
224
- #
225
- # @return [Changeset]
226
- #
227
- # @overload changeset(opts)
228
- # Return a changeset object using provided changeset type and relation
229
- #
230
- # @example
231
- # repo.changeset(delete: repo.users.where { id > 10 })
232
- #
233
- # @param [Hash<Symbol=>Relation] opts Command type => Relation config
234
- #
235
- # @return [Changeset]
236
- #
237
- # @api public
238
- def changeset(*args)
239
- opts = { command_compiler: command_compiler }
240
-
241
- if args.size == 2
242
- name, data = args
243
- elsif args.size == 3
244
- name, pk, data = args
245
- elsif args.size == 1
246
- if args[0].is_a?(Class)
247
- klass = args[0]
248
-
249
- if klass < Changeset
250
- return klass.new(relations[klass.relation], opts)
251
- else
252
- raise ArgumentError, "+#{klass.name}+ is not a Changeset subclass"
253
- end
254
- else
255
- type, relation = args[0].to_a[0]
256
- end
257
- else
258
- raise ArgumentError, 'Repository#changeset accepts 1-3 arguments'
259
- end
260
-
261
- if type
262
- klass = CHANGESET_TYPES.fetch(type) {
263
- raise ArgumentError, "+#{type.inspect}+ is not a valid changeset type. Must be one of: #{CHANGESET_TYPES.keys.inspect}"
264
- }
265
-
266
- klass.new(relation, opts)
267
- else
268
- relation = relations[name]
269
-
270
- if pk
271
- Changeset::Update.new(relation.by_pk(pk), opts.update(__data__: data))
272
- else
273
- Changeset::Create.new(relation, opts.update(__data__: data))
274
- end
275
- end
108
+ @relations = {}
276
109
  end
277
110
 
278
111
  # Open a database transaction
@@ -305,7 +138,7 @@ module ROM
305
138
  #
306
139
  # @api public
307
140
  def inspect
308
- %(#<#{self.class} relations=[#{self.class.relations.map(&:inspect).join(' ')}]>)
141
+ %(#<#{self.class} struct_namespace=#{struct_namespace} auto_struct=#{auto_struct}>)
309
142
  end
310
143
 
311
144
  # Start a session for multiple changesets
@@ -321,46 +154,6 @@ module ROM
321
154
  yield(session)
322
155
  transaction { session.commit! }
323
156
  end
324
-
325
- private
326
-
327
- # Local command cache
328
- #
329
- # @api private
330
- def commands
331
- @__commands__ ||= Concurrent::Map.new
332
- end
333
-
334
- # Build a new command or return existing one
335
- #
336
- # @api private
337
- def compile_command(*args, mapper: nil, use: nil, **opts)
338
- type, name = args + opts.to_a.flatten(1)
339
-
340
- relation = name.is_a?(Symbol) ? relations[name] : name
341
-
342
- ast = relation.to_ast
343
- adapter = relations[relation.name].adapter
344
-
345
- if mapper
346
- mapper_instance = container.mappers[relation.name.relation][mapper]
347
- elsif mapper.nil?
348
- mapper_instance = mappers[ast]
349
- end
350
-
351
- command = CommandCompiler[container, type, adapter, ast, use, opts]
352
-
353
- if mapper_instance
354
- command >> mapper_instance
355
- else
356
- command.new(relation)
357
- end
358
- end
359
-
360
- # @api private
361
- def map_tuple(relation, tuple)
362
- relations[relation.name].mapper.([tuple]).first
363
- end
364
157
  end
365
158
  end
366
159
 
@@ -1,3 +1,5 @@
1
+ require 'rom/repository/relation_reader'
2
+
1
3
  module ROM
2
4
  class Repository
3
5
  # Class-level APIs for repositories
@@ -18,11 +20,20 @@ module ROM
18
20
  # @api public
19
21
  def [](name)
20
22
  klass = Class.new(self < Repository::Root ? self : Repository::Root)
21
- klass.relations(name)
22
23
  klass.root(name)
23
24
  klass
24
25
  end
25
26
 
27
+ # @api public
28
+ def new(container, options = EMPTY_HASH)
29
+ unless relation_reader
30
+ relation_reader(RelationReader.new(self, container.relations.elements.keys))
31
+ include(relation_reader)
32
+ end
33
+
34
+ super
35
+ end
36
+
26
37
  # Inherits configured relations and commands
27
38
  #
28
39
  # @api private
@@ -31,34 +42,9 @@ module ROM
31
42
 
32
43
  return if self === Repository
33
44
 
34
- klass.relations(*relations)
35
45
  klass.commands(*commands)
36
46
  end
37
47
 
38
- # Define which relations your repository is going to use
39
- #
40
- # @example
41
- # class MyRepo < ROM::Repository
42
- # relations :users, :tasks
43
- # end
44
- #
45
- # my_repo = MyRepo.new(rom)
46
- #
47
- # my_repo.users
48
- # my_repo.tasks
49
- #
50
- # @return [Array<Symbol>]
51
- #
52
- # @api public
53
- def relations(*names)
54
- if names.empty?
55
- @relations ||= []
56
- else
57
- attr_reader(*(names - relations))
58
- @relations = relations | names
59
- end
60
- end
61
-
62
48
  # Defines command methods on a root repository
63
49
  #
64
50
  # @example
@@ -107,10 +93,9 @@ module ROM
107
93
  def define_command_method(type, **opts)
108
94
  define_method(type) do |*input|
109
95
  if input.size == 1 && input[0].respond_to?(:commit)
110
- changeset = input[0]
111
- map_tuple(changeset.relation, changeset.commit)
96
+ input[0].commit
112
97
  else
113
- command(type => self.class.root, **opts).call(*input)
98
+ root.command(type, **opts).call(*input)
114
99
  end
115
100
  end
116
101
  end
@@ -126,11 +111,9 @@ module ROM
126
111
  changeset = input.first
127
112
 
128
113
  if changeset.respond_to?(:commit)
129
- map_tuple(changeset.relation, changeset.commit)
114
+ changeset.commit
130
115
  else
131
- command(type => self.class.root, **opts)
132
- .public_send(view_name, *view_args)
133
- .call(*input)
116
+ root.command(type, **opts).public_send(view_name, *view_args).call(*input)
134
117
  end
135
118
  end
136
119
  end
@@ -0,0 +1,46 @@
1
+ module ROM
2
+ class Repository
3
+ # @api private
4
+ class RelationReader < Module
5
+ # @api private
6
+ attr_reader :klass
7
+
8
+ # @api private
9
+ attr_reader :relations
10
+
11
+ module InstanceMethods
12
+ # @api private
13
+ def set_relation(name)
14
+ container.
15
+ relations[name].
16
+ with(auto_struct: auto_struct).
17
+ struct_namespace(struct_namespace)
18
+ end
19
+ end
20
+
21
+ # @api private
22
+ def initialize(klass, relations)
23
+ @klass = klass
24
+ @relations = relations
25
+ define_readers!
26
+ end
27
+
28
+ # @api private
29
+ def included(klass)
30
+ super
31
+ klass.include(InstanceMethods)
32
+ end
33
+
34
+ private
35
+
36
+ # @api private
37
+ def define_readers!
38
+ relations.each do |name|
39
+ define_method(name) do
40
+ @relations[name] ||= set_relation(name)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end