rom 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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