rom 0.4.2 → 0.5.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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +81 -0
  3. data/.travis.yml +2 -1
  4. data/CHANGELOG.md +41 -0
  5. data/Gemfile +12 -8
  6. data/Guardfile +17 -11
  7. data/README.md +7 -7
  8. data/Rakefile +29 -0
  9. data/lib/rom.rb +9 -66
  10. data/lib/rom/adapter.rb +45 -12
  11. data/lib/rom/adapter/memory.rb +0 -4
  12. data/lib/rom/adapter/memory/commands.rb +0 -10
  13. data/lib/rom/adapter/memory/dataset.rb +18 -6
  14. data/lib/rom/adapter/memory/storage.rb +0 -3
  15. data/lib/rom/command_registry.rb +24 -43
  16. data/lib/rom/commands.rb +5 -6
  17. data/lib/rom/commands/create.rb +5 -5
  18. data/lib/rom/commands/delete.rb +8 -6
  19. data/lib/rom/commands/result.rb +82 -0
  20. data/lib/rom/commands/update.rb +5 -4
  21. data/lib/rom/commands/with_options.rb +1 -4
  22. data/lib/rom/config.rb +70 -0
  23. data/lib/rom/env.rb +11 -3
  24. data/lib/rom/global.rb +107 -0
  25. data/lib/rom/header.rb +122 -89
  26. data/lib/rom/header/attribute.rb +148 -0
  27. data/lib/rom/mapper.rb +46 -67
  28. data/lib/rom/mapper_builder.rb +20 -73
  29. data/lib/rom/mapper_builder/mapper_dsl.rb +114 -0
  30. data/lib/rom/mapper_builder/model_dsl.rb +29 -0
  31. data/lib/rom/mapper_registry.rb +21 -0
  32. data/lib/rom/model_builder.rb +11 -17
  33. data/lib/rom/processor.rb +28 -0
  34. data/lib/rom/processor/transproc.rb +105 -0
  35. data/lib/rom/reader.rb +81 -21
  36. data/lib/rom/reader_builder.rb +14 -4
  37. data/lib/rom/relation.rb +19 -5
  38. data/lib/rom/relation_builder.rb +20 -6
  39. data/lib/rom/repository.rb +0 -2
  40. data/lib/rom/setup.rb +156 -0
  41. data/lib/rom/{boot → setup}/base_relation_dsl.rb +4 -8
  42. data/lib/rom/setup/command_dsl.rb +46 -0
  43. data/lib/rom/setup/finalize.rb +125 -0
  44. data/lib/rom/setup/mapper_dsl.rb +19 -0
  45. data/lib/rom/{boot → setup}/relation_dsl.rb +1 -4
  46. data/lib/rom/setup/schema_dsl.rb +33 -0
  47. data/lib/rom/support/registry.rb +10 -6
  48. data/lib/rom/version.rb +1 -1
  49. data/rom.gemspec +3 -1
  50. data/spec/integration/adapters/extending_relations_spec.rb +0 -2
  51. data/spec/integration/commands/create_spec.rb +2 -9
  52. data/spec/integration/commands/delete_spec.rb +4 -5
  53. data/spec/integration/commands/error_handling_spec.rb +4 -3
  54. data/spec/integration/commands/update_spec.rb +3 -8
  55. data/spec/integration/mappers/deep_embedded_spec.rb +52 -0
  56. data/spec/integration/mappers/definition_dsl_spec.rb +0 -118
  57. data/spec/integration/mappers/embedded_spec.rb +82 -0
  58. data/spec/integration/mappers/group_spec.rb +170 -0
  59. data/spec/integration/mappers/prefixing_attributes_spec.rb +2 -2
  60. data/spec/integration/mappers/renaming_attributes_spec.rb +8 -6
  61. data/spec/integration/mappers/symbolizing_attributes_spec.rb +80 -0
  62. data/spec/integration/mappers/wrap_spec.rb +162 -0
  63. data/spec/integration/multi_repo_spec.rb +64 -0
  64. data/spec/integration/relations/reading_spec.rb +12 -8
  65. data/spec/integration/relations/registry_dsl_spec.rb +1 -3
  66. data/spec/integration/schema_spec.rb +10 -0
  67. data/spec/integration/setup_spec.rb +57 -6
  68. data/spec/spec_helper.rb +2 -1
  69. data/spec/unit/config_spec.rb +60 -0
  70. data/spec/unit/rom/adapter/memory/dataset_spec.rb +52 -0
  71. data/spec/unit/rom/adapter_spec.rb +31 -11
  72. data/spec/unit/rom/header_spec.rb +60 -16
  73. data/spec/unit/rom/mapper_builder_spec.rb +311 -0
  74. data/spec/unit/rom/mapper_registry_spec.rb +25 -0
  75. data/spec/unit/rom/mapper_spec.rb +4 -5
  76. data/spec/unit/rom/model_builder_spec.rb +15 -13
  77. data/spec/unit/rom/processor/transproc_spec.rb +331 -0
  78. data/spec/unit/rom/reader_spec.rb +73 -0
  79. data/spec/unit/rom/registry_spec.rb +38 -0
  80. data/spec/unit/rom/relation_spec.rb +0 -1
  81. data/spec/unit/rom/setup_spec.rb +55 -0
  82. data/spec/unit/rom_spec.rb +14 -0
  83. metadata +62 -22
  84. data/Gemfile.devtools +0 -71
  85. data/lib/rom/boot.rb +0 -197
  86. data/lib/rom/boot/command_dsl.rb +0 -48
  87. data/lib/rom/boot/dsl.rb +0 -37
  88. data/lib/rom/boot/mapper_dsl.rb +0 -23
  89. data/lib/rom/boot/schema_dsl.rb +0 -27
  90. data/lib/rom/ra.rb +0 -172
  91. data/lib/rom/ra/operation/group.rb +0 -47
  92. data/lib/rom/ra/operation/join.rb +0 -39
  93. data/lib/rom/ra/operation/wrap.rb +0 -45
  94. data/lib/rom/transformer.rb +0 -77
  95. data/spec/integration/ra/group_spec.rb +0 -46
  96. data/spec/integration/ra/join_spec.rb +0 -50
  97. data/spec/integration/ra/wrap_spec.rb +0 -37
  98. data/spec/unit/rom/ra/operation/group_spec.rb +0 -55
  99. data/spec/unit/rom/ra/operation/wrap_spec.rb +0 -29
  100. data/spec/unit/rom/transformer_spec.rb +0 -41
@@ -1,48 +0,0 @@
1
- require 'rom/mapper_builder'
2
-
3
- module ROM
4
-
5
- class CommandDSL
6
- attr_reader :commands
7
-
8
- class CommandDefinition
9
- attr_reader :options
10
-
11
- def initialize(options, &block)
12
- @options = options
13
- instance_exec(&block) if block
14
- end
15
-
16
- def to_h
17
- options
18
- end
19
-
20
- def type
21
- options[:type]
22
- end
23
-
24
- def method_missing(name, *args, &block)
25
- if args.size == 1
26
- options[name] = args.first
27
- else
28
- super
29
- end
30
- end
31
- end
32
-
33
- def initialize
34
- @commands = {}
35
- end
36
-
37
- def call
38
- commands
39
- end
40
-
41
- def define(name, options = {}, &block)
42
- commands[name] = CommandDefinition.new(options, &block)
43
- self
44
- end
45
-
46
- end
47
-
48
- end
@@ -1,37 +0,0 @@
1
- require 'rom/boot/schema_dsl'
2
- require 'rom/boot/mapper_dsl'
3
- require 'rom/boot/command_dsl'
4
-
5
- module ROM
6
- class Boot
7
-
8
- class DSL
9
- attr_reader :env
10
-
11
- def initialize(env)
12
- @env = env
13
- @schema = {}
14
- end
15
-
16
- def schema(&block)
17
- dsl = SchemaDSL.new(env, @schema)
18
- dsl.instance_exec(&block)
19
- dsl.call
20
- end
21
-
22
- def mappers(&block)
23
- dsl = MapperDSL.new
24
- dsl.instance_exec(&block)
25
- dsl.call
26
- end
27
-
28
- def commands(&block)
29
- dsl = CommandDSL.new
30
- dsl.instance_exec(&block)
31
- dsl.call
32
- end
33
-
34
- end
35
-
36
- end
37
- end
@@ -1,23 +0,0 @@
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
@@ -1,27 +0,0 @@
1
- require 'rom/boot/base_relation_dsl'
2
-
3
- module ROM
4
- class Boot
5
-
6
- class SchemaDSL
7
- attr_reader :env, :schema
8
-
9
- def initialize(env, schema = {})
10
- @env = env
11
- @schema = schema
12
- end
13
-
14
- def base_relation(name, &block)
15
- dsl = BaseRelationDSL.new(env, name)
16
- definition = dsl.call(&block)
17
- (schema[dsl.repository] ||= []) << definition
18
- end
19
-
20
- def call
21
- schema
22
- end
23
-
24
- end
25
-
26
- end
27
- end
@@ -1,172 +0,0 @@
1
- require 'rom/ra/operation/join'
2
- require 'rom/ra/operation/group'
3
- require 'rom/ra/operation/wrap'
4
-
5
- module ROM
6
-
7
- # Experimental DSL for in-memory relational operations
8
- #
9
- # @api private
10
- module RA
11
-
12
- # Join two relations in-memory using natural-join
13
- #
14
- # @example
15
- #
16
- # require 'rom'
17
- # require 'rom/adapter/memory'
18
- #
19
- # setup = ROM.setup(memory: 'memory://localhost')
20
- #
21
- # setup.schema do
22
- # base_relation(:users) do
23
- # repository :memory
24
- #
25
- # attribute :user_id
26
- # attribute :name
27
- # end
28
- #
29
- # base_relation(:tasks) do
30
- # repository :memory
31
- #
32
- # attribute :user_id
33
- # attribute :title
34
- # end
35
- # end
36
- #
37
- # setup.relation(:tasks)
38
- #
39
- # setup.relation(:users) do
40
- # def with_tasks
41
- # in_memory { join(tasks) }
42
- # end
43
- # end
44
- #
45
- # rom.relations.users.insert user_id: 1, name: 'Piotr'
46
- # rom.relations.tasks.insert user_id: 1, title: 'Relax'
47
- #
48
- # rom.relations.users.with_tasks.to_a
49
- # => [{:user_id=>1, :name=>"Piotr", :title=>"Relax"}]
50
- #
51
- # @api public
52
- def join(*args)
53
- left, right = args.size > 1 ? args : [self, args.first]
54
- Operation::Join.new(left, right)
55
- end
56
-
57
- # Groups two relations in-memory using group operation
58
- #
59
- # @example
60
- #
61
- # require 'rom'
62
- # require 'rom/adapter/memory'
63
- #
64
- # setup = ROM.setup(memory: 'memory://localhost')
65
- #
66
- # setup.schema do
67
- # base_relation(:users) do
68
- # repository :memory
69
- #
70
- # attribute :user_id
71
- # attribute :name
72
- # end
73
- #
74
- # base_relation(:tasks) do
75
- # repository :memory
76
- #
77
- # attribute :user_id
78
- # attribute :title
79
- # end
80
- # end
81
- #
82
- # setup.relation(:tasks)
83
- #
84
- # setup.relation(:users) do
85
- # def with_tasks
86
- # in_memory { group(join(tasks), tasks: [:title]) }
87
- # end
88
- # end
89
- #
90
- # rom.relations.users.insert user_id: 1, name: 'Piotr'
91
- # rom.relations.tasks.insert user_id: 1, title: 'Work'
92
- # rom.relations.tasks.insert user_id: 1, title: 'Relax'
93
- #
94
- # rom.relations.users.with_tasks.to_a
95
- # => [{:user_id=>1, :name=>"Piotr", tasks: [{:title=>"Relax"}, {:title=>"Work"}]}]
96
- #
97
- # @api public
98
- def group(*args)
99
- ra_with_options(*args) { |relation, options|
100
- Operation::Group.new(relation, options)
101
- }
102
- end
103
-
104
- # Embed one relation in another in-memory using wrap operation
105
- #
106
- # @example
107
- #
108
- # require 'rom'
109
- # require 'rom/adapter/memory'
110
- #
111
- # setup = ROM.setup(memory: 'memory://localhost')
112
- #
113
- # setup.schema do
114
- # base_relation(:users) do
115
- # repository :memory
116
- #
117
- # attribute :user_id
118
- # attribute :name
119
- # end
120
- #
121
- # base_relation(:addresses) do
122
- # repository :memory
123
- #
124
- # attribute :user_id
125
- # attribute :street
126
- # attribute :zipcode
127
- # attribute :city
128
- # end
129
- # end
130
- #
131
- # setup.relation(:addresses)
132
- #
133
- # setup.relation(:users) do
134
- # def with_address
135
- # in_memory { wrap(join(addresses), address: [:street, :zipcode, :city]) }
136
- # end
137
- # end
138
- #
139
- # rom = setup.finalize
140
- #
141
- # rom.relations.users.insert user_id: 1, name: 'Piotr'
142
- # rom.relations.addresses.insert user_id: 1, street: 'Street 1', zipcode: '123', city: 'Kraków'
143
- #
144
- # rom.relations.users.with_address.to_a
145
- # => [{:user_id=>1, :name=>"Piotr", :address=>{:street=>"Street 1", :zipcode=>"123", :city=>"Kraków"}}]
146
- #
147
- # @api public
148
- def wrap(*args)
149
- ra_with_options(*args) { |relation, options|
150
- Operation::Wrap.new(relation, options)
151
- }
152
- end
153
-
154
- private
155
-
156
- # @api private
157
- def ra_with_options(*args)
158
- relation =
159
- if args.size > 1
160
- args.first
161
- else
162
- self
163
- end
164
-
165
- options = args.last
166
-
167
- yield(relation, options)
168
- end
169
-
170
- end
171
-
172
- end
@@ -1,47 +0,0 @@
1
- module ROM
2
- module RA
3
- class Operation
4
-
5
- class Group
6
- # FIXME: only reading from a relation should be allowed here so this is
7
- # obviously too much
8
- include Charlatan.new(:relation)
9
-
10
- include Enumerable
11
-
12
- attr_reader :options, :header
13
-
14
- def initialize(relation, options)
15
- super
16
- @options = options
17
- @header = relation.header + options.keys - attribute_names
18
- end
19
-
20
- def each(&block)
21
- return to_enum unless block
22
-
23
- result = relation.each_with_object({}) do |tuple, grouped|
24
- left = tuple.reject { |k,_| attribute_names.include?(k) }
25
- right = tuple.reject { |k,_| !attribute_names.include?(k) }
26
-
27
- grouped[left] ||= {}
28
- grouped[left][key] ||= []
29
- grouped[left][key] << right if right.values.any?
30
- end
31
-
32
- result.map { |k,v| k.merge(v) }.each(&block)
33
- end
34
-
35
- def key
36
- options.keys.first
37
- end
38
-
39
- def attribute_names
40
- options.values.first
41
- end
42
-
43
- end
44
-
45
- end
46
- end
47
- end
@@ -1,39 +0,0 @@
1
- module ROM
2
- module RA
3
- class Operation
4
-
5
- class Join
6
- include Charlatan.new(:left)
7
- include Enumerable
8
-
9
- attr_reader :right
10
-
11
- def initialize(left, right)
12
- super
13
- @left, @right = left, right
14
- end
15
-
16
- def header
17
- left.header + right.header
18
- end
19
-
20
- def each(&block)
21
- return to_enum unless block
22
-
23
- join_map = left.each_with_object({}) { |tuple, h|
24
- others = right.find_all { |t| (tuple.to_a & t.to_a).any? }
25
- (h[tuple] ||= []).concat(others)
26
- }
27
-
28
- tuples = left.map { |tuple|
29
- join_map[tuple].map { |other| tuple.merge(other) }
30
- }.flatten
31
-
32
- tuples.each(&block)
33
- end
34
-
35
- end
36
-
37
- end
38
- end
39
- end
@@ -1,45 +0,0 @@
1
- module ROM
2
- module RA
3
- class Operation
4
-
5
- class Wrap
6
- # FIXME: only reading from a relation should be allowed here so this is
7
- # obviously too much
8
- include Charlatan.new(:relation)
9
-
10
- include Enumerable
11
-
12
- attr_reader :options, :header
13
-
14
- def initialize(relation, options)
15
- super
16
- @options = options
17
- @header = relation.header + options.keys - attribute_names
18
- end
19
-
20
- def each(&block)
21
- return to_enum unless block
22
-
23
- results = relation.each_with_object([]) do |tuple, wrapped|
24
- result = tuple.reject { |k,_| attribute_names.include?(k) }
25
- result[key] = tuple.reject { |k,_| !attribute_names.include?(k) }
26
-
27
- wrapped << result
28
- end
29
-
30
- results.each(&block)
31
- end
32
-
33
- def key
34
- options.keys.first
35
- end
36
-
37
- def attribute_names
38
- options.values.first
39
- end
40
-
41
- end
42
-
43
- end
44
- end
45
- end