rom 0.2.0 → 0.3.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.
Files changed (175) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -3
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +13 -14
  5. data/{Changelog.md → CHANGELOG.md} +12 -3
  6. data/Gemfile +14 -10
  7. data/Gemfile.devtools +16 -16
  8. data/Guardfile +2 -5
  9. data/README.md +68 -56
  10. data/Rakefile +3 -3
  11. data/config/flay.yml +2 -2
  12. data/config/mutant.yml +2 -4
  13. data/config/rubocop.yml +30 -0
  14. data/lib/rom.rb +47 -9
  15. data/lib/rom/adapter.rb +52 -0
  16. data/lib/rom/adapter/memory.rb +70 -0
  17. data/lib/rom/boot.rb +158 -0
  18. data/lib/rom/boot/base_relation_dsl.rb +43 -0
  19. data/lib/rom/boot/dsl.rb +30 -0
  20. data/lib/rom/boot/mapper_dsl.rb +23 -0
  21. data/lib/rom/boot/relation_dsl.rb +23 -0
  22. data/lib/rom/boot/schema_dsl.rb +27 -0
  23. data/lib/rom/env.rb +48 -0
  24. data/lib/rom/header.rb +123 -0
  25. data/lib/rom/mapper.rb +38 -153
  26. data/lib/rom/mapper_builder.rb +85 -0
  27. data/lib/rom/model_builder.rb +58 -0
  28. data/lib/rom/ra.rb +196 -0
  29. data/lib/rom/ra/operation/group.rb +49 -0
  30. data/lib/rom/ra/operation/join.rb +41 -0
  31. data/lib/rom/ra/operation/wrap.rb +45 -0
  32. data/lib/rom/reader.rb +62 -0
  33. data/lib/rom/reader_builder.rb +28 -0
  34. data/lib/rom/relation.rb +41 -350
  35. data/lib/rom/relation_builder.rb +48 -0
  36. data/lib/rom/repository.rb +28 -53
  37. data/lib/rom/support/registry.rb +34 -0
  38. data/lib/rom/version.rb +3 -0
  39. data/rom.gemspec +12 -10
  40. data/spec/integration/adapters/extending_relations_spec.rb +43 -0
  41. data/spec/integration/mappers/definition_dsl_spec.rb +82 -0
  42. data/spec/integration/mappers/prefixing_attributes_spec.rb +42 -0
  43. data/spec/integration/mappers/renaming_attributes_spec.rb +138 -0
  44. data/spec/integration/ra/group_spec.rb +47 -0
  45. data/spec/integration/ra/join_spec.rb +24 -0
  46. data/spec/integration/ra/wrap_spec.rb +37 -0
  47. data/spec/integration/relations/reading_spec.rb +116 -0
  48. data/spec/integration/relations/registry_dsl_spec.rb +44 -0
  49. data/spec/integration/schema_spec.rb +29 -0
  50. data/spec/integration/setup_spec.rb +18 -0
  51. data/spec/shared/users_and_tasks.rb +34 -0
  52. data/spec/spec_helper.rb +14 -36
  53. data/spec/unit/rom/adapter_spec.rb +59 -0
  54. data/spec/unit/rom/header_spec.rb +58 -0
  55. data/spec/unit/rom/mapper_spec.rb +27 -0
  56. data/spec/unit/rom/ra/operation/group_spec.rb +55 -0
  57. data/spec/unit/rom/ra/operation/wrap_spec.rb +29 -0
  58. data/spec/unit/rom/relation_spec.rb +34 -0
  59. metadata +122 -190
  60. data/lib/rom/constants.rb +0 -16
  61. data/lib/rom/environment.rb +0 -105
  62. data/lib/rom/environment/builder.rb +0 -71
  63. data/lib/rom/mapper/attribute.rb +0 -108
  64. data/lib/rom/mapper/builder.rb +0 -58
  65. data/lib/rom/mapper/builder/definition.rb +0 -162
  66. data/lib/rom/mapper/header.rb +0 -103
  67. data/lib/rom/mapper/loader_builder.rb +0 -26
  68. data/lib/rom/schema.rb +0 -21
  69. data/lib/rom/schema/builder.rb +0 -59
  70. data/lib/rom/schema/definition.rb +0 -84
  71. data/lib/rom/schema/definition/relation.rb +0 -80
  72. data/lib/rom/schema/definition/relation/base.rb +0 -27
  73. data/lib/rom/session.rb +0 -111
  74. data/lib/rom/session/environment.rb +0 -67
  75. data/lib/rom/session/identity_map.rb +0 -43
  76. data/lib/rom/session/mapper.rb +0 -62
  77. data/lib/rom/session/relation.rb +0 -140
  78. data/lib/rom/session/state.rb +0 -59
  79. data/lib/rom/session/state/created.rb +0 -22
  80. data/lib/rom/session/state/deleted.rb +0 -25
  81. data/lib/rom/session/state/persisted.rb +0 -34
  82. data/lib/rom/session/state/transient.rb +0 -20
  83. data/lib/rom/session/state/updated.rb +0 -29
  84. data/lib/rom/session/tracker.rb +0 -62
  85. data/lib/rom/support/axiom/adapter.rb +0 -111
  86. data/lib/rom/support/axiom/adapter/data_objects.rb +0 -38
  87. data/lib/rom/support/axiom/adapter/memory.rb +0 -25
  88. data/lib/rom/support/axiom/adapter/postgres.rb +0 -19
  89. data/lib/rom/support/axiom/adapter/sqlite3.rb +0 -20
  90. data/lib/version.rb +0 -3
  91. data/spec/integration/environment_setup_spec.rb +0 -24
  92. data/spec/integration/grouped_mappers_spec.rb +0 -87
  93. data/spec/integration/join_and_group_spec.rb +0 -76
  94. data/spec/integration/join_and_wrap_spec.rb +0 -68
  95. data/spec/integration/mapping_embedded_relations_spec.rb +0 -73
  96. data/spec/integration/mapping_relations_spec.rb +0 -120
  97. data/spec/integration/schema_definition_spec.rb +0 -152
  98. data/spec/integration/session_spec.rb +0 -87
  99. data/spec/integration/wrapped_mappers_spec.rb +0 -73
  100. data/spec/shared/unit/environment_context.rb +0 -6
  101. data/spec/shared/unit/loader.rb +0 -11
  102. data/spec/shared/unit/loader_identity.rb +0 -13
  103. data/spec/shared/unit/mapper_context.rb +0 -11
  104. data/spec/shared/unit/relation_context.rb +0 -82
  105. data/spec/shared/unit/session_environment_context.rb +0 -11
  106. data/spec/shared/unit/session_relation_context.rb +0 -18
  107. data/spec/support/helper.rb +0 -34
  108. data/spec/support/ice_nine_config.rb +0 -10
  109. data/spec/support/test_mapper.rb +0 -110
  110. data/spec/unit/rom/environment/builder/mapping_spec.rb +0 -24
  111. data/spec/unit/rom/environment/builder/schema_spec.rb +0 -33
  112. data/spec/unit/rom/environment/class_methods/setup_spec.rb +0 -18
  113. data/spec/unit/rom/environment/repository_spec.rb +0 -21
  114. data/spec/unit/rom/mapper/attribute/embedded_collection/to_ast_spec.rb +0 -18
  115. data/spec/unit/rom/mapper/attribute/embedded_value/to_ast_spec.rb +0 -16
  116. data/spec/unit/rom/mapper/attribute/rename_spec.rb +0 -9
  117. data/spec/unit/rom/mapper/attribute/to_ast_spec.rb +0 -9
  118. data/spec/unit/rom/mapper/builder/class_methods/call_spec.rb +0 -61
  119. data/spec/unit/rom/mapper/class_methods/build_spec.rb +0 -55
  120. data/spec/unit/rom/mapper/dump_spec.rb +0 -11
  121. data/spec/unit/rom/mapper/group_spec.rb +0 -35
  122. data/spec/unit/rom/mapper/header/each_spec.rb +0 -26
  123. data/spec/unit/rom/mapper/header/element_reader_spec.rb +0 -21
  124. data/spec/unit/rom/mapper/header/group_spec.rb +0 -18
  125. data/spec/unit/rom/mapper/header/join_spec.rb +0 -14
  126. data/spec/unit/rom/mapper/header/keys_spec.rb +0 -29
  127. data/spec/unit/rom/mapper/header/project_spec.rb +0 -13
  128. data/spec/unit/rom/mapper/header/rename_spec.rb +0 -11
  129. data/spec/unit/rom/mapper/header/to_ast_spec.rb +0 -11
  130. data/spec/unit/rom/mapper/header/wrap_spec.rb +0 -18
  131. data/spec/unit/rom/mapper/identity_from_tuple_spec.rb +0 -11
  132. data/spec/unit/rom/mapper/identity_spec.rb +0 -11
  133. data/spec/unit/rom/mapper/join_spec.rb +0 -15
  134. data/spec/unit/rom/mapper/load_spec.rb +0 -11
  135. data/spec/unit/rom/mapper/new_object_spec.rb +0 -14
  136. data/spec/unit/rom/mapper/project_spec.rb +0 -11
  137. data/spec/unit/rom/mapper/rename_spec.rb +0 -16
  138. data/spec/unit/rom/mapper/wrap_spec.rb +0 -35
  139. data/spec/unit/rom/relation/delete_spec.rb +0 -15
  140. data/spec/unit/rom/relation/drop_spec.rb +0 -11
  141. data/spec/unit/rom/relation/each_spec.rb +0 -23
  142. data/spec/unit/rom/relation/first_spec.rb +0 -19
  143. data/spec/unit/rom/relation/group_spec.rb +0 -29
  144. data/spec/unit/rom/relation/inject_mapper_spec.rb +0 -17
  145. data/spec/unit/rom/relation/insert_spec.rb +0 -13
  146. data/spec/unit/rom/relation/last_spec.rb +0 -19
  147. data/spec/unit/rom/relation/one_spec.rb +0 -49
  148. data/spec/unit/rom/relation/rename_spec.rb +0 -21
  149. data/spec/unit/rom/relation/replace_spec.rb +0 -13
  150. data/spec/unit/rom/relation/restrict_spec.rb +0 -25
  151. data/spec/unit/rom/relation/sort_by_spec.rb +0 -25
  152. data/spec/unit/rom/relation/take_spec.rb +0 -11
  153. data/spec/unit/rom/relation/to_a_spec.rb +0 -20
  154. data/spec/unit/rom/relation/update_spec.rb +0 -25
  155. data/spec/unit/rom/relation/wrap_spec.rb +0 -29
  156. data/spec/unit/rom/repository/class_methods/build_spec.rb +0 -27
  157. data/spec/unit/rom/repository/element_reader_spec.rb +0 -21
  158. data/spec/unit/rom/repository/element_writer_spec.rb +0 -18
  159. data/spec/unit/rom/schema/builder/class_methods/build_spec.rb +0 -103
  160. data/spec/unit/rom/schema/element_reader_spec.rb +0 -15
  161. data/spec/unit/rom/session/class_methods/start_spec.rb +0 -23
  162. data/spec/unit/rom/session/clean_predicate_spec.rb +0 -21
  163. data/spec/unit/rom/session/environment/element_reader_spec.rb +0 -13
  164. data/spec/unit/rom/session/flush_spec.rb +0 -58
  165. data/spec/unit/rom/session/mapper/load_spec.rb +0 -47
  166. data/spec/unit/rom/session/relation/delete_spec.rb +0 -28
  167. data/spec/unit/rom/session/relation/dirty_predicate_spec.rb +0 -35
  168. data/spec/unit/rom/session/relation/identity_spec.rb +0 -11
  169. data/spec/unit/rom/session/relation/new_spec.rb +0 -50
  170. data/spec/unit/rom/session/relation/save_spec.rb +0 -50
  171. data/spec/unit/rom/session/relation/state_spec.rb +0 -23
  172. data/spec/unit/rom/session/relation/track_spec.rb +0 -23
  173. data/spec/unit/rom/session/relation/tracking_predicate_spec.rb +0 -23
  174. data/spec/unit/rom/session/relation/update_attributes_spec.rb +0 -45
  175. data/spec/unit/rom/session/state_spec.rb +0 -79
data/lib/rom.rb CHANGED
@@ -1,14 +1,52 @@
1
- # encoding: utf-8
2
-
3
- require 'adamantium'
4
1
  require 'concord'
5
- require 'equalizer'
6
2
  require 'charlatan'
7
- require 'morpher'
8
- require 'axiom'
9
- require 'axiom-optimizer'
3
+ require 'inflecto'
4
+
5
+ require 'rom/version'
6
+ require 'rom/support/registry'
10
7
 
11
- require 'rom/environment'
8
+ require 'rom/header'
12
9
  require 'rom/relation'
13
10
  require 'rom/mapper'
14
- require 'rom/session'
11
+ require 'rom/reader'
12
+
13
+ require 'rom/adapter'
14
+ require 'rom/repository'
15
+ require 'rom/env'
16
+
17
+ require 'rom/boot'
18
+
19
+ module ROM
20
+ EnvAlreadyFinalizedError = Class.new(StandardError)
21
+
22
+ Schema = Class.new(Registry)
23
+ RelationRegistry = Class.new(Registry)
24
+ ReaderRegistry = Class.new(Registry)
25
+
26
+ # Starts the setup process for schema, relations and mappers
27
+ #
28
+ # @param [Hash] options repository URIs
29
+ #
30
+ # @return [Boot] boot object
31
+ #
32
+ # @api public
33
+ def self.setup(options, &block)
34
+ adapters = options.each_with_object({}) do |(name, uri), hash|
35
+ hash[name] = Adapter.setup(uri)
36
+ end
37
+
38
+ repositories = adapters.each_with_object({}) do |(name, adapter), hash|
39
+ hash[name] = Repository.new(adapter)
40
+ end
41
+
42
+ boot = Boot.new(repositories)
43
+
44
+ if block
45
+ boot.instance_exec(&block)
46
+ boot.finalize
47
+ end
48
+
49
+ boot
50
+ end
51
+
52
+ end
@@ -0,0 +1,52 @@
1
+ require 'addressable/uri'
2
+
3
+ module ROM
4
+
5
+ class Adapter
6
+ include Equalizer.new(:connection)
7
+
8
+ @adapters = []
9
+
10
+ attr_reader :uri
11
+
12
+ def self.setup(uri_string)
13
+ uri = Addressable::URI.parse(uri_string)
14
+
15
+ unless adapter = self[uri.scheme]
16
+ raise ArgumentError, "#{uri_string.inspect} uri is not supported"
17
+ end
18
+
19
+ adapter.new(uri)
20
+ end
21
+
22
+ def self.register(adapter)
23
+ @adapters.unshift adapter
24
+ end
25
+
26
+ def self.[](scheme)
27
+ @adapters.detect { |adapter| adapter.schemes.include?(scheme.to_sym) }
28
+ end
29
+
30
+ def initialize(uri)
31
+ @uri = uri
32
+ end
33
+
34
+ def connection
35
+ raise NotImplementedError, "#{self.class}#connection must be implemented"
36
+ end
37
+
38
+ def extend_relation_class(klass)
39
+ klass
40
+ end
41
+
42
+ def extend_relation_instance(relation)
43
+ relation
44
+ end
45
+
46
+ def schema
47
+ []
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,70 @@
1
+ module ROM
2
+ class Adapter
3
+
4
+ class Memory < Adapter
5
+ attr_reader :connection
6
+
7
+ def self.schemes
8
+ [:memory]
9
+ end
10
+
11
+ class Dataset
12
+ include Charlatan.new(:data)
13
+
14
+ def each(&block)
15
+ return to_enum unless block
16
+ data.each(&block)
17
+ end
18
+
19
+ def restrict(criteria = nil, &block)
20
+ if criteria
21
+ find_all { |tuple| criteria.all? { |k, v| tuple[k] == v } }
22
+ else
23
+ find_all { |tuple| yield(tuple) }
24
+ end
25
+ end
26
+
27
+ def project(*names)
28
+ map { |tuple| tuple.reject { |key,_| names.include?(key) } }
29
+ end
30
+
31
+ def order(*names)
32
+ sort_by { |tuple| tuple.values_at(*names) }
33
+ end
34
+
35
+ def insert(tuple)
36
+ data << tuple
37
+ end
38
+
39
+ def header
40
+ []
41
+ end
42
+ end
43
+
44
+ class Storage
45
+ attr_reader :data
46
+
47
+ def initialize(*)
48
+ super
49
+ @data = {}
50
+ end
51
+
52
+ def [](name)
53
+ data[name] ||= Dataset.new([])
54
+ end
55
+ end
56
+
57
+ def initialize(*args)
58
+ super
59
+ @connection = Storage.new
60
+ end
61
+
62
+ def [](name)
63
+ connection[name]
64
+ end
65
+
66
+ Adapter.register(self)
67
+ end
68
+
69
+ end
70
+ end
data/lib/rom/boot.rb ADDED
@@ -0,0 +1,158 @@
1
+ require 'rom/boot/dsl'
2
+ require 'rom/relation_builder'
3
+ require 'rom/reader_builder'
4
+
5
+ module ROM
6
+
7
+ # Exposes DSL for defining schema, relations and mappers
8
+ #
9
+ # @api public
10
+ class Boot
11
+ attr_reader :repositories, :adapter_relation_map, :env
12
+
13
+ # @api private
14
+ def initialize(repositories)
15
+ @repositories = repositories
16
+ @schema = {}
17
+ @relations = {}
18
+ @mappers = []
19
+ @adapter_relation_map = {}
20
+ @env = nil
21
+ end
22
+
23
+ # Schema definition DSL
24
+ #
25
+ # @example
26
+ #
27
+ # setup.schema do
28
+ # base_relation(:users) do
29
+ # repository :sqlite
30
+ #
31
+ # attribute :id
32
+ # attribute :name
33
+ # end
34
+ # end
35
+ #
36
+ # @api public
37
+ def schema(&block)
38
+ @schema = DSL.new(self).schema(&block)
39
+ end
40
+
41
+ # Relation definition DSL
42
+ #
43
+ # @example
44
+ #
45
+ # setup.relation(:users) do
46
+ # def names
47
+ # project(:name)
48
+ # end
49
+ # end
50
+ #
51
+ # @api public
52
+ def relation(name, &block)
53
+ @relations.update(name => block)
54
+ end
55
+
56
+ # Mapper definition DSL
57
+ #
58
+ # @example
59
+ #
60
+ # setup.mappers do
61
+ # define(:users) do
62
+ # model name: 'User'
63
+ # end
64
+ #
65
+ # define(:names, parent: :users) do
66
+ # exclude :id
67
+ # end
68
+ # end
69
+ #
70
+ # @api public
71
+ def mappers(&block)
72
+ @mappers.concat(DSL.new(self).mappers(&block))
73
+ end
74
+
75
+ # Finalize the setup
76
+ #
77
+ # @return [Env] frozen env with access to repositories, schema, relations and mappers
78
+ #
79
+ # @api public
80
+ def finalize
81
+ raise EnvAlreadyFinalizedError if env
82
+
83
+ schema = load_schema
84
+ relations = load_relations(schema)
85
+ readers = load_readers(relations)
86
+
87
+ @env = Env.new(repositories, schema, relations, readers)
88
+ end
89
+
90
+ # @api private
91
+ def [](name)
92
+ repositories.fetch(name)
93
+ end
94
+
95
+ # @api private
96
+ def respond_to_missing?(name, include_context = false)
97
+ repositories.key?(name)
98
+ end
99
+
100
+ private
101
+
102
+ # @api private
103
+ def method_missing(name, *args)
104
+ repositories.fetch(name)
105
+ end
106
+
107
+ # @api private
108
+ def load_schema
109
+ repositories.values.each do |repo|
110
+ (@schema[repo] ||= []).concat(repo.schema)
111
+ end
112
+
113
+ base_relations = @schema.each_with_object({}) do |(repo, schema), h|
114
+ schema.each do |name, dataset, header|
115
+ adapter_relation_map[name] = repo.adapter
116
+ h[name] = Relation.new(dataset, header)
117
+ end
118
+ end
119
+
120
+ Schema.new(base_relations)
121
+ end
122
+
123
+ # @api private
124
+ def load_relations(schema)
125
+ builder = RelationBuilder.new(schema)
126
+
127
+ relations = @relations.each_with_object({}) do |(name, block), h|
128
+ adapter = adapter_relation_map[name]
129
+
130
+ relation = builder.call(name) { |klass|
131
+ adapter.extend_relation_class(klass)
132
+ klass.class_eval(&block) if block
133
+ }
134
+
135
+ adapter.extend_relation_instance(relation)
136
+
137
+ h[name] = relation
138
+ end
139
+
140
+ relations.each_value { |relation| relation.class.finalize(relations, relation) }
141
+
142
+ RelationRegistry.new(relations)
143
+ end
144
+
145
+ # @api private
146
+ def load_readers(relations)
147
+ reader_builder = ReaderBuilder.new(relations)
148
+
149
+ readers = @mappers.each_with_object({}) do |(name, options, block), h|
150
+ h[name] = reader_builder.call(name, options, &block)
151
+ end
152
+
153
+ RelationRegistry.new(readers)
154
+ end
155
+
156
+ end
157
+
158
+ end
@@ -0,0 +1,43 @@
1
+ module ROM
2
+ class Boot
3
+
4
+ class BaseRelationDSL
5
+ attr_reader :env, :name, :repositories, :attributes, :datasets
6
+
7
+ def initialize(env, name)
8
+ @env = env
9
+ @name = name
10
+ @attributes = []
11
+ end
12
+
13
+ def repository(name = nil)
14
+ if @repository
15
+ @repository
16
+ else
17
+ @repository = env[name]
18
+ end
19
+ end
20
+
21
+ def attribute(name)
22
+ attributes << name
23
+ end
24
+
25
+ def call(&block)
26
+ instance_exec(&block)
27
+
28
+ dataset = repository[name]
29
+
30
+ header =
31
+ if attributes.any?
32
+ attributes
33
+ else
34
+ dataset.header
35
+ end
36
+
37
+ [name, repository[name], header]
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,30 @@
1
+ require 'rom/boot/schema_dsl'
2
+ require 'rom/boot/mapper_dsl'
3
+
4
+ module ROM
5
+ class Boot
6
+
7
+ class DSL
8
+ attr_reader :env
9
+
10
+ def initialize(env)
11
+ @env = env
12
+ @schema = {}
13
+ end
14
+
15
+ def schema(&block)
16
+ dsl = SchemaDSL.new(env, @schema)
17
+ dsl.instance_exec(&block)
18
+ dsl.call
19
+ end
20
+
21
+ def mappers(&block)
22
+ dsl = MapperDSL.new
23
+ dsl.instance_exec(&block)
24
+ dsl.call
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ require 'rom/mapper_builder'
2
+
3
+ module ROM
4
+
5
+ class MapperDSL
6
+ attr_reader :mappers
7
+
8
+ def initialize
9
+ @mappers = []
10
+ end
11
+
12
+ def call
13
+ mappers
14
+ end
15
+
16
+ def define(name, options = {}, &block)
17
+ mappers << [name, options, block]
18
+ self
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,23 @@
1
+ module ROM
2
+ class Boot
3
+
4
+ class RelationDSL
5
+ attr_reader :schema, :relations
6
+
7
+ def initialize(schema, relations)
8
+ @schema = schema
9
+ @relations = relations
10
+ end
11
+
12
+ def register(name, &block)
13
+ relations[name] = [block]
14
+ end
15
+
16
+ def call
17
+ relations
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+ end