rom 5.4.1 → 6.0.0.alpha1

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 (186) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +58 -65
  3. data/LICENSE +1 -1
  4. data/README.md +7 -6
  5. data/lib/rom/array_dataset.rb +46 -0
  6. data/lib/rom/associations/abstract.rb +217 -0
  7. data/lib/rom/associations/definitions/abstract.rb +150 -0
  8. data/lib/rom/associations/definitions/many_to_many.rb +29 -0
  9. data/lib/rom/associations/definitions/many_to_one.rb +14 -0
  10. data/lib/rom/associations/definitions/one_to_many.rb +14 -0
  11. data/lib/rom/associations/definitions/one_to_one.rb +14 -0
  12. data/lib/rom/associations/definitions/one_to_one_through.rb +14 -0
  13. data/lib/rom/associations/definitions.rb +7 -0
  14. data/lib/rom/associations/many_to_many.rb +128 -0
  15. data/lib/rom/associations/many_to_one.rb +65 -0
  16. data/lib/rom/associations/one_to_many.rb +65 -0
  17. data/lib/rom/associations/one_to_one.rb +13 -0
  18. data/lib/rom/associations/one_to_one_through.rb +13 -0
  19. data/lib/rom/associations/through_identifier.rb +41 -0
  20. data/lib/rom/attribute.rb +425 -0
  21. data/lib/rom/auto_curry.rb +70 -0
  22. data/lib/rom/cache.rb +87 -0
  23. data/lib/rom/changeset/associated.rb +110 -0
  24. data/lib/rom/changeset/create.rb +18 -0
  25. data/lib/rom/changeset/delete.rb +15 -0
  26. data/lib/rom/changeset/extensions/relation.rb +26 -0
  27. data/lib/rom/changeset/pipe.rb +81 -0
  28. data/lib/rom/changeset/pipe_registry.rb +27 -0
  29. data/lib/rom/changeset/stateful.rb +285 -0
  30. data/lib/rom/changeset/update.rb +81 -0
  31. data/lib/rom/changeset.rb +185 -0
  32. data/lib/rom/command.rb +351 -0
  33. data/lib/rom/command_compiler.rb +201 -0
  34. data/lib/rom/command_proxy.rb +36 -0
  35. data/lib/rom/commands/class_interface.rb +236 -0
  36. data/lib/rom/commands/composite.rb +55 -0
  37. data/lib/rom/commands/create.rb +15 -0
  38. data/lib/rom/commands/delete.rb +16 -0
  39. data/lib/rom/commands/graph/class_interface.rb +64 -0
  40. data/lib/rom/commands/graph/input_evaluator.rb +94 -0
  41. data/lib/rom/commands/graph.rb +88 -0
  42. data/lib/rom/commands/lazy/create.rb +35 -0
  43. data/lib/rom/commands/lazy/delete.rb +39 -0
  44. data/lib/rom/commands/lazy/update.rb +46 -0
  45. data/lib/rom/commands/lazy.rb +106 -0
  46. data/lib/rom/commands/update.rb +16 -0
  47. data/lib/rom/commands.rb +5 -0
  48. data/lib/rom/compat/auto_registration.rb +115 -0
  49. data/lib/rom/compat/auto_registration_strategies/base.rb +29 -0
  50. data/lib/rom/compat/auto_registration_strategies/custom_namespace.rb +84 -0
  51. data/lib/rom/compat/auto_registration_strategies/no_namespace.rb +33 -0
  52. data/lib/rom/compat/auto_registration_strategies/with_namespace.rb +29 -0
  53. data/lib/rom/compat/command.rb +74 -0
  54. data/lib/rom/compat/components/dsl/schema.rb +130 -0
  55. data/lib/rom/compat/components.rb +91 -0
  56. data/lib/rom/compat/global.rb +17 -0
  57. data/lib/rom/compat/mapper.rb +22 -0
  58. data/lib/rom/compat/registries.rb +47 -0
  59. data/lib/rom/compat/relation.rb +40 -0
  60. data/lib/rom/compat/schema/dsl.rb +260 -0
  61. data/lib/rom/compat/setting_proxy.rb +44 -0
  62. data/lib/rom/compat/setup.rb +151 -0
  63. data/lib/rom/compat/transformer.rb +49 -0
  64. data/lib/rom/compat.rb +22 -0
  65. data/lib/rom/components/association.rb +26 -0
  66. data/lib/rom/components/command.rb +24 -0
  67. data/lib/rom/components/core.rb +148 -0
  68. data/lib/rom/components/dataset.rb +60 -0
  69. data/lib/rom/components/dsl/association.rb +47 -0
  70. data/lib/rom/components/dsl/command.rb +60 -0
  71. data/lib/rom/components/dsl/core.rb +126 -0
  72. data/lib/rom/components/dsl/dataset.rb +33 -0
  73. data/lib/rom/components/dsl/gateway.rb +14 -0
  74. data/lib/rom/components/dsl/mapper.rb +70 -0
  75. data/lib/rom/components/dsl/relation.rb +49 -0
  76. data/lib/rom/components/dsl/schema.rb +150 -0
  77. data/lib/rom/components/dsl/view.rb +82 -0
  78. data/lib/rom/components/dsl.rb +255 -0
  79. data/lib/rom/components/gateway.rb +50 -0
  80. data/lib/rom/components/mapper.rb +29 -0
  81. data/lib/rom/components/provider.rb +160 -0
  82. data/lib/rom/components/registry.rb +154 -0
  83. data/lib/rom/components/relation.rb +41 -0
  84. data/lib/rom/components/schema.rb +61 -0
  85. data/lib/rom/components/view.rb +55 -0
  86. data/lib/rom/components.rb +55 -0
  87. data/lib/rom/configuration_dsl.rb +4 -0
  88. data/lib/rom/constants.rb +135 -0
  89. data/lib/rom/container.rb +182 -0
  90. data/lib/rom/core.rb +125 -0
  91. data/lib/rom/data_proxy.rb +97 -0
  92. data/lib/rom/enumerable_dataset.rb +70 -0
  93. data/lib/rom/gateway.rb +232 -0
  94. data/lib/rom/global.rb +56 -0
  95. data/lib/rom/header/attribute.rb +190 -0
  96. data/lib/rom/header.rb +198 -0
  97. data/lib/rom/inferrer.rb +55 -0
  98. data/lib/rom/initializer.rb +80 -0
  99. data/lib/rom/lint/enumerable_dataset.rb +56 -0
  100. data/lib/rom/lint/gateway.rb +120 -0
  101. data/lib/rom/lint/linter.rb +79 -0
  102. data/lib/rom/lint/spec.rb +22 -0
  103. data/lib/rom/lint/test.rb +98 -0
  104. data/lib/rom/loader.rb +161 -0
  105. data/lib/rom/mapper/attribute_dsl.rb +480 -0
  106. data/lib/rom/mapper/dsl.rb +107 -0
  107. data/lib/rom/mapper/model_dsl.rb +61 -0
  108. data/lib/rom/mapper.rb +99 -0
  109. data/lib/rom/mapper_compiler.rb +84 -0
  110. data/lib/rom/memory/associations/many_to_many.rb +12 -0
  111. data/lib/rom/memory/associations/many_to_one.rb +12 -0
  112. data/lib/rom/memory/associations/one_to_many.rb +12 -0
  113. data/lib/rom/memory/associations/one_to_one.rb +12 -0
  114. data/lib/rom/memory/associations.rb +6 -0
  115. data/lib/rom/memory/commands.rb +60 -0
  116. data/lib/rom/memory/dataset.rb +127 -0
  117. data/lib/rom/memory/gateway.rb +66 -0
  118. data/lib/rom/memory/mapper_compiler.rb +10 -0
  119. data/lib/rom/memory/relation.rb +91 -0
  120. data/lib/rom/memory/schema.rb +32 -0
  121. data/lib/rom/memory/storage.rb +61 -0
  122. data/lib/rom/memory/types.rb +11 -0
  123. data/lib/rom/memory.rb +7 -0
  124. data/lib/rom/model_builder.rb +103 -0
  125. data/lib/rom/open_struct.rb +112 -0
  126. data/lib/rom/pipeline.rb +111 -0
  127. data/lib/rom/plugin.rb +130 -0
  128. data/lib/rom/plugins/class_methods.rb +37 -0
  129. data/lib/rom/plugins/command/schema.rb +45 -0
  130. data/lib/rom/plugins/command/timestamps.rb +149 -0
  131. data/lib/rom/plugins/dsl.rb +53 -0
  132. data/lib/rom/plugins/relation/changeset.rb +97 -0
  133. data/lib/rom/plugins/relation/instrumentation.rb +66 -0
  134. data/lib/rom/plugins/relation/registry_reader.rb +36 -0
  135. data/lib/rom/plugins/schema/timestamps.rb +59 -0
  136. data/lib/rom/plugins.rb +100 -0
  137. data/lib/rom/processor/composer.rb +37 -0
  138. data/lib/rom/processor/transformer.rb +415 -0
  139. data/lib/rom/processor.rb +30 -0
  140. data/lib/rom/registries/associations.rb +26 -0
  141. data/lib/rom/registries/commands.rb +11 -0
  142. data/lib/rom/registries/container.rb +12 -0
  143. data/lib/rom/registries/datasets.rb +21 -0
  144. data/lib/rom/registries/gateways.rb +8 -0
  145. data/lib/rom/registries/mappers.rb +21 -0
  146. data/lib/rom/registries/nestable.rb +32 -0
  147. data/lib/rom/registries/relations.rb +8 -0
  148. data/lib/rom/registries/root.rb +203 -0
  149. data/lib/rom/registries/schemas.rb +44 -0
  150. data/lib/rom/registries/views.rb +11 -0
  151. data/lib/rom/relation/class_interface.rb +61 -0
  152. data/lib/rom/relation/combined.rb +160 -0
  153. data/lib/rom/relation/commands.rb +65 -0
  154. data/lib/rom/relation/composite.rb +53 -0
  155. data/lib/rom/relation/curried.rb +129 -0
  156. data/lib/rom/relation/graph.rb +107 -0
  157. data/lib/rom/relation/loaded.rb +136 -0
  158. data/lib/rom/relation/materializable.rb +62 -0
  159. data/lib/rom/relation/name.rb +122 -0
  160. data/lib/rom/relation/wrap.rb +64 -0
  161. data/lib/rom/relation.rb +625 -0
  162. data/lib/rom/repository/class_interface.rb +162 -0
  163. data/lib/rom/repository/relation_reader.rb +48 -0
  164. data/lib/rom/repository/root.rb +75 -0
  165. data/lib/rom/repository/session.rb +60 -0
  166. data/lib/rom/repository.rb +179 -0
  167. data/lib/rom/schema/associations_dsl.rb +222 -0
  168. data/lib/rom/schema/inferrer.rb +106 -0
  169. data/lib/rom/schema.rb +471 -0
  170. data/lib/rom/settings.rb +141 -0
  171. data/lib/rom/setup.rb +297 -0
  172. data/lib/rom/struct.rb +99 -0
  173. data/lib/rom/struct_compiler.rb +114 -0
  174. data/lib/rom/support/configurable.rb +213 -0
  175. data/lib/rom/support/inflector.rb +31 -0
  176. data/lib/rom/support/memoizable.rb +61 -0
  177. data/lib/rom/support/notifications.rb +238 -0
  178. data/lib/rom/transaction.rb +26 -0
  179. data/lib/rom/transformer.rb +46 -0
  180. data/lib/rom/types.rb +74 -0
  181. data/lib/rom/version.rb +1 -1
  182. data/lib/rom-changeset.rb +4 -0
  183. data/lib/rom-core.rb +3 -0
  184. data/lib/rom-repository.rb +4 -0
  185. data/lib/rom.rb +3 -3
  186. metadata +302 -23
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/core/cache"
4
+
5
+ require "rom/repository/relation_reader"
6
+
7
+ module ROM
8
+ class Repository
9
+ # Class-level APIs for repositories
10
+ #
11
+ # @api public
12
+ module ClassInterface
13
+ # Create a root-repository class and set its root relation
14
+ #
15
+ # @example
16
+ # # where :users is the relation name in your rom container
17
+ # class UserRepo < ROM::Repository[:users]
18
+ # end
19
+ #
20
+ # @param name [Symbol] The relation `register_as` value
21
+ #
22
+ # @return [Class] descendant of ROM::Repository::Root
23
+ #
24
+ # @api public
25
+ def [](name)
26
+ fetch_or_store(name) do
27
+ klass = Class.new(self < Repository::Root ? self : Repository::Root)
28
+ klass.root(name)
29
+ klass
30
+ end
31
+ end
32
+
33
+ # Initialize a new repository object, establishing configured relation proxies from
34
+ # the passed container
35
+ #
36
+ # @overload new(container, **options)
37
+ # Initialize with container as leading parameter
38
+ #
39
+ # @param [ROM::Container] container Finalized rom container
40
+ #
41
+ # @param [Hash] options Repository options
42
+ # @option options [Module] :struct_namespace Custom struct namespace
43
+ # @option options [Boolean] :auto_struct Enable/Disable auto-struct mapping
44
+ #
45
+ # @overload new(**options)
46
+ # Inititalize with container as option
47
+ #
48
+ # @param [Hash] options Repository options
49
+ # @option options [ROM::Container] :container Finalized rom container
50
+ # @option options [Module] :struct_namespace Custom struct namespace
51
+ # @option options [Boolean] :auto_struct Enable/Disable auto-struct mapping
52
+ #
53
+ # @api public
54
+ def new(container = nil, **options)
55
+ container ||= options.fetch(:container)
56
+
57
+ unless relation_reader
58
+ relation_reader(RelationReader.new(self, container.relation_ids))
59
+ include(relation_reader)
60
+ end
61
+
62
+ super(**options, container: container)
63
+ end
64
+
65
+ # Inherits configured relations and commands
66
+ #
67
+ # @api private
68
+ def inherited(klass)
69
+ super
70
+
71
+ return if equal?(Repository)
72
+
73
+ klass.extend(::Dry::Core::Cache)
74
+ klass.commands(*commands)
75
+ end
76
+
77
+ # Defines command methods on a root repository
78
+ #
79
+ # @example
80
+ # class UserRepo < ROM::Repository[:users]
81
+ # commands :create, update: :by_pk, delete: :by_pk
82
+ # end
83
+ #
84
+ # # with custom command plugin
85
+ # class UserRepo < ROM::Repository[:users]
86
+ # commands :create, use: :my_command_plugin
87
+ # end
88
+ #
89
+ # # with custom mapper
90
+ # class UserRepo < ROM::Repository[:users]
91
+ # commands :create, mapper: :my_custom_mapper
92
+ # end
93
+ #
94
+ # @param [Array<Symbol>] names A list of command names
95
+ # @option :mapper [Symbol] An optional mapper identifier
96
+ # @option :use [Symbol] An optional command plugin identifier
97
+ #
98
+ # @return [Array<Symbol>] A list of defined command names
99
+ #
100
+ # @api public
101
+ def commands(*names, mapper: nil, use: nil, plugins_options: EMPTY_HASH, **opts)
102
+ if names.any? || opts.any?
103
+ @commands = names + opts.to_a
104
+
105
+ @commands.each do |spec|
106
+ type, *view = Array(spec).flatten
107
+
108
+ if view.empty?
109
+ define_command_method(type, mapper: mapper, use: use,
110
+ plugins_options: plugins_options)
111
+ else
112
+ define_restricted_command_method(type, view, mapper: mapper, use: use,
113
+ plugins_options: plugins_options)
114
+ end
115
+ end
116
+ else
117
+ @commands ||= []
118
+ end
119
+ end
120
+
121
+ # @api public
122
+ def use(plugin, **options)
123
+ ROM.plugins[:repository].fetch(plugin).apply_to(self, **options)
124
+ end
125
+
126
+ private
127
+
128
+ # @api private
129
+ def define_command_method(type, **opts)
130
+ define_method(type) do |*input|
131
+ if input.size == 1 && input[0].respond_to?(:commit)
132
+ input[0].commit
133
+ else
134
+ root.command(type, **opts).call(*input)
135
+ end
136
+ end
137
+ end
138
+
139
+ # @api private
140
+ def define_restricted_command_method(type, views, **opts)
141
+ views.each do |view_name|
142
+ meth_name = views.size > 1 ? :"#{type}_#{view_name}" : type
143
+
144
+ define_method(meth_name) do |*args|
145
+ arity = root.__send__(view_name).arity
146
+
147
+ view_args = args[0..arity - 1]
148
+ input = args[arity..args.size - 1]
149
+
150
+ changeset = input.first
151
+
152
+ if changeset.respond_to?(:commit)
153
+ changeset.commit
154
+ else
155
+ root.public_send(view_name, *view_args).command(type, **opts).(*input)
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ROM
4
+ class Repository
5
+ # @api private
6
+ class RelationReader < Module
7
+ # @api private
8
+ attr_reader :klass
9
+
10
+ # @api private
11
+ attr_reader :relations
12
+
13
+ module InstanceMethods
14
+ # @api private
15
+ def set_relation(name)
16
+ container
17
+ .relations[name]
18
+ .with(auto_struct: auto_struct)
19
+ .struct_namespace(struct_namespace)
20
+ end
21
+ end
22
+
23
+ # @api private
24
+ def initialize(klass, relations)
25
+ @klass = klass
26
+ @relations = relations
27
+ define_readers!
28
+ end
29
+
30
+ # @api private
31
+ def included(klass)
32
+ super
33
+ klass.include(InstanceMethods)
34
+ end
35
+
36
+ private
37
+
38
+ # @api private
39
+ def define_readers!
40
+ relations.each do |name|
41
+ define_method(name) do
42
+ @relations[name] ||= set_relation(name)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/core/class_attributes"
4
+
5
+ module ROM
6
+ class Repository
7
+ # A specialized repository type dedicated to work with a root relation
8
+ #
9
+ # This repository type builds commands and aggregates for its root relation
10
+ #
11
+ # @example
12
+ # class UserRepo < ROM::Repository[:users]
13
+ # commands :create, update: :by_pk, delete: :by_pk
14
+ # end
15
+ #
16
+ # rom = ROM.setup(:sql, 'sqlite::memory') do |conf|
17
+ # conf.default.create_table(:users) do
18
+ # primary_key :id
19
+ # column :name, String
20
+ # end
21
+ # end
22
+ #
23
+ # user_repo = UserRepo.new(rom)
24
+ #
25
+ # user = user_repo.create(name: "Jane")
26
+ #
27
+ # user_repo.update(user.id, name: "Jane Doe")
28
+ #
29
+ # user_repo.delete(user.id)
30
+ #
31
+ # @api public
32
+ class Root < Repository
33
+ # @!method self.root
34
+ # Get or set repository root relation identifier
35
+ #
36
+ # This method is automatically used when you define a class using
37
+ # MyRepo[:rel_identifier] shortcut
38
+ #
39
+ # @overload root
40
+ # Return root relation identifier
41
+ # @return [Symbol]
42
+ #
43
+ # @overload root(identifier)
44
+ # Set root relation identifier
45
+ # @return [Symbol]
46
+ defines :root
47
+
48
+ # @!attribute [r] root
49
+ # @return [Relation] The root relation
50
+ attr_reader :root
51
+
52
+ # Sets descendant root relation
53
+ #
54
+ # @api private
55
+ def self.inherited(klass)
56
+ super
57
+ klass.root(root)
58
+ end
59
+
60
+ # @see Repository#initialize
61
+ def initialize(*)
62
+ super
63
+ @root = set_relation(self.class.root)
64
+ end
65
+ ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true)
66
+
67
+ # @see ROM::Repository#transaction
68
+ #
69
+ # @api public
70
+ def transaction(gateway: root.gateway, **opts, &block)
71
+ super
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/core/equalizer"
4
+
5
+ module ROM
6
+ # TODO: finish this in 1.1.0
7
+ #
8
+ # @api private
9
+ class Session
10
+ include Dry::Equalizer(:queue, :status)
11
+
12
+ attr_reader :repo
13
+
14
+ attr_reader :queue
15
+
16
+ attr_reader :status
17
+
18
+ def initialize(repo)
19
+ @repo = repo
20
+ @status = :pending
21
+ initialize_queue!
22
+ end
23
+
24
+ def add(changeset)
25
+ queue << changeset
26
+ self
27
+ end
28
+
29
+ def commit!
30
+ queue.each(&:commit)
31
+
32
+ @status = :success
33
+
34
+ self
35
+ rescue StandardError => e
36
+ @status = :failure
37
+ raise e
38
+ ensure
39
+ initialize_queue!
40
+ end
41
+
42
+ def pending?
43
+ status.equal?(:pending)
44
+ end
45
+
46
+ def success?
47
+ status.equal?(:success)
48
+ end
49
+
50
+ def failure?
51
+ status.equal?(:failure)
52
+ end
53
+
54
+ private
55
+
56
+ def initialize_queue!
57
+ @queue = []
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/core/cache"
4
+ require "dry/core/class_attributes"
5
+
6
+ require "rom/initializer"
7
+ require "rom/plugins"
8
+ require "rom/struct"
9
+ require "rom/container"
10
+ require "rom/repository/class_interface"
11
+ require "rom/repository/session"
12
+
13
+ module ROM
14
+ # Abstract repository class to inherit from
15
+ #
16
+ # A repository provides access to composable relations and commands.
17
+ # Its job is to provide application-specific data that is already materialized, so that
18
+ # relations don't leak into your application layer.
19
+ #
20
+ # Typically, you're going to work with Repository::Root that is configured to
21
+ # use a single relation as its root, and compose aggregates and use changesets and commands
22
+ # against the root relation.
23
+ #
24
+ # @example
25
+ # rom = ROM.setup(:sql, 'sqlite::memory') do |conf|
26
+ # conf.default.create_table(:users) do
27
+ # primary_key :id
28
+ # column :name, String
29
+ # end
30
+ #
31
+ # conf.default.create_table(:tasks) do
32
+ # primary_key :id
33
+ # column :user_id, Integer
34
+ # column :title, String
35
+ # end
36
+ #
37
+ # conf.relation(:users) do
38
+ # associations do
39
+ # has_many :tasks
40
+ # end
41
+ # end
42
+ # end
43
+ #
44
+ # class UserRepo < ROM::Repository[:users]
45
+ # def users_with_tasks
46
+ # aggregate(:tasks).to_a
47
+ # end
48
+ # end
49
+ #
50
+ # user_repo = UserRepo.new(rom)
51
+ # user_repo.users_with_tasks
52
+ #
53
+ # @see Repository::Root
54
+ #
55
+ # @api public
56
+ class Repository
57
+ extend Dry::Core::Cache
58
+ extend Dry::Core::ClassAttributes
59
+
60
+ extend ClassInterface
61
+ extend Initializer
62
+
63
+ # @!method self.auto_struct
64
+ # Get or set auto_struct setting
65
+ #
66
+ # When disabled, rom structs won't be created
67
+ #
68
+ # @overload auto_struct
69
+ # Return auto_struct setting value
70
+ # @return [TrueClass,FalseClass]
71
+ #
72
+ # @overload auto_struct(value)
73
+ # Set auto_struct value
74
+ # @return [Class]
75
+ defines :auto_struct
76
+
77
+ auto_struct true
78
+
79
+ # @!method self.auto_struct
80
+ # Get or set struct namespace
81
+ defines :struct_namespace
82
+
83
+ # @!method self.relation_reader
84
+ # Get or set relation reader module
85
+ # @return [RelationReader]
86
+ defines :relation_reader
87
+
88
+ struct_namespace ROM::Struct
89
+
90
+ # @!attribute [r] container
91
+ # @return [ROM::Container] The container used to set up a repo
92
+ option :container, allow: ROM::Container
93
+
94
+ # @!attribute [r] struct_namespace
95
+ # @return [Module,Class] The namespace for auto-generated structs
96
+ option :struct_namespace, default: -> { self.class.struct_namespace }
97
+
98
+ # @!attribute [r] auto_struct
99
+ # @return [Boolean] The container used to set up a repo
100
+ option :auto_struct, default: -> { self.class.auto_struct }
101
+
102
+ # @!attribute [r] relations
103
+ # @return [RelationRegistry] The relation proxy registry used by a repo
104
+ attr_reader :relations
105
+
106
+ # Initializes a new repository object
107
+ #
108
+ # @api private
109
+ def initialize(*)
110
+ super
111
+ @relations = {}
112
+ end
113
+ ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true)
114
+
115
+ # Open a database transaction
116
+ # @option gateway [Symbol] gateway key. For Repository::Root descendants
117
+ # it's taken from the root relation
118
+ #
119
+ # @example commited transaction
120
+ # user = transaction do |t|
121
+ # create(changeset(name: 'Jane'))
122
+ # end
123
+ #
124
+ # user
125
+ # # => #<ROM::Struct::User id=1 name="Jane">
126
+ #
127
+ # @example with a rollback
128
+ # user = transaction do |t|
129
+ # changeset(name: 'Jane').commit
130
+ # t.rollback!
131
+ # end
132
+ #
133
+ # user
134
+ # # nil
135
+ #
136
+ # @example with automatic savepoints
137
+ # user = transaction(auto_savepoint: true) do
138
+ # create(changeset(name: 'Jane'))
139
+ #
140
+ # transaction do |t|
141
+ # update(changeset(name: 'John'))
142
+ # t.rollback!
143
+ # end
144
+ # end
145
+ #
146
+ # user
147
+ # # => #<ROM::Struct::User id=1 name="Jane">
148
+ #
149
+ # @api public
150
+ def transaction(gateway: :default, **opts, &block)
151
+ container.gateways[gateway].transaction(**opts, &block)
152
+ end
153
+
154
+ # Return a string representation of a repository object
155
+ #
156
+ # @return [String]
157
+ #
158
+ # @api public
159
+ def inspect
160
+ %(#<#{self.class} struct_namespace=#{struct_namespace} auto_struct=#{auto_struct}>)
161
+ end
162
+
163
+ # Start a session for multiple changesets
164
+ #
165
+ # TODO: this is partly done, needs tweaks in changesets so that we can gather
166
+ # command results and return them in a nice way
167
+ #
168
+ # @!visibility private
169
+ #
170
+ # @api public
171
+ def session
172
+ session = Session.new(self)
173
+ yield(session)
174
+ transaction { session.commit! }
175
+ end
176
+ end
177
+ end
178
+
179
+ require "rom/repository/root"