rom 0.5.0 → 0.6.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 (142) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +19 -15
  3. data/.rubocop_todo.yml +28 -0
  4. data/.travis.yml +8 -1
  5. data/CHANGELOG.md +40 -0
  6. data/Gemfile +10 -2
  7. data/Guardfile +12 -10
  8. data/README.md +42 -43
  9. data/Rakefile +13 -23
  10. data/lib/rom.rb +19 -27
  11. data/lib/rom/command.rb +118 -0
  12. data/lib/rom/command_registry.rb +13 -27
  13. data/lib/rom/commands.rb +1 -59
  14. data/lib/rom/commands/abstract.rb +147 -0
  15. data/lib/rom/commands/composite.rb +47 -0
  16. data/lib/rom/commands/create.rb +2 -17
  17. data/lib/rom/commands/delete.rb +5 -25
  18. data/lib/rom/commands/result.rb +5 -5
  19. data/lib/rom/commands/update.rb +3 -27
  20. data/lib/rom/constants.rb +19 -0
  21. data/lib/rom/env.rb +85 -35
  22. data/lib/rom/global.rb +173 -42
  23. data/lib/rom/header.rb +5 -5
  24. data/lib/rom/header/attribute.rb +2 -2
  25. data/lib/rom/lint/enumerable_dataset.rb +52 -0
  26. data/lib/rom/lint/linter.rb +64 -0
  27. data/lib/rom/lint/repository.rb +78 -0
  28. data/lib/rom/lint/spec.rb +20 -0
  29. data/lib/rom/lint/test.rb +98 -0
  30. data/lib/rom/mapper.rb +32 -5
  31. data/lib/rom/mapper/attribute_dsl.rb +240 -0
  32. data/lib/rom/mapper/dsl.rb +100 -0
  33. data/lib/rom/mapper/model_dsl.rb +55 -0
  34. data/lib/rom/mapper_registry.rb +8 -1
  35. data/lib/rom/memory.rb +4 -0
  36. data/lib/rom/memory/commands.rb +46 -0
  37. data/lib/rom/memory/dataset.rb +72 -0
  38. data/lib/rom/memory/relation.rb +44 -0
  39. data/lib/rom/memory/repository.rb +62 -0
  40. data/lib/rom/memory/storage.rb +57 -0
  41. data/lib/rom/model_builder.rb +44 -5
  42. data/lib/rom/processor.rb +1 -1
  43. data/lib/rom/processor/transproc.rb +109 -16
  44. data/lib/rom/reader.rb +91 -39
  45. data/lib/rom/relation.rb +165 -26
  46. data/lib/rom/relation/composite.rb +132 -0
  47. data/lib/rom/relation/curried.rb +48 -0
  48. data/lib/rom/relation/lazy.rb +173 -0
  49. data/lib/rom/relation/loaded.rb +75 -0
  50. data/lib/rom/relation/registry_reader.rb +23 -0
  51. data/lib/rom/repository.rb +93 -34
  52. data/lib/rom/setup.rb +54 -98
  53. data/lib/rom/setup/finalize.rb +85 -76
  54. data/lib/rom/setup_dsl/command.rb +36 -0
  55. data/lib/rom/setup_dsl/command_dsl.rb +34 -0
  56. data/lib/rom/setup_dsl/mapper.rb +32 -0
  57. data/lib/rom/setup_dsl/mapper_dsl.rb +30 -0
  58. data/lib/rom/setup_dsl/relation.rb +21 -0
  59. data/lib/rom/setup_dsl/setup.rb +75 -0
  60. data/lib/rom/support/array_dataset.rb +38 -0
  61. data/lib/rom/support/class_builder.rb +44 -0
  62. data/lib/rom/support/class_macros.rb +56 -0
  63. data/lib/rom/support/data_proxy.rb +102 -0
  64. data/lib/rom/support/enumerable_dataset.rb +58 -0
  65. data/lib/rom/support/inflector.rb +73 -0
  66. data/lib/rom/support/options.rb +188 -0
  67. data/lib/rom/support/registry.rb +4 -8
  68. data/lib/rom/version.rb +1 -1
  69. data/rakelib/benchmark.rake +13 -0
  70. data/rakelib/mutant.rake +16 -0
  71. data/rakelib/rubocop.rake +18 -0
  72. data/rom.gemspec +4 -7
  73. data/spec/integration/commands/create_spec.rb +32 -24
  74. data/spec/integration/commands/delete_spec.rb +15 -7
  75. data/spec/integration/commands/update_spec.rb +13 -11
  76. data/spec/integration/mappers/deep_embedded_spec.rb +4 -11
  77. data/spec/integration/mappers/definition_dsl_spec.rb +31 -44
  78. data/spec/integration/mappers/embedded_spec.rb +9 -24
  79. data/spec/integration/mappers/group_spec.rb +22 -30
  80. data/spec/integration/mappers/prefixing_attributes_spec.rb +18 -23
  81. data/spec/integration/mappers/renaming_attributes_spec.rb +23 -38
  82. data/spec/integration/mappers/symbolizing_attributes_spec.rb +18 -24
  83. data/spec/integration/mappers/wrap_spec.rb +22 -30
  84. data/spec/integration/multi_repo_spec.rb +15 -37
  85. data/spec/integration/relations/reading_spec.rb +82 -14
  86. data/spec/integration/repositories/extending_relations_spec.rb +50 -0
  87. data/spec/integration/{adapters → repositories}/setting_logger_spec.rb +6 -5
  88. data/spec/integration/setup_spec.rb +59 -62
  89. data/spec/shared/enumerable_dataset.rb +49 -0
  90. data/spec/shared/one_behavior.rb +26 -0
  91. data/spec/shared/users_and_tasks.rb +11 -23
  92. data/spec/spec_helper.rb +16 -7
  93. data/spec/support/constant_leak_finder.rb +14 -0
  94. data/spec/test/memory_repository_lint_test.rb +27 -0
  95. data/spec/unit/rom/command_registry_spec.rb +44 -0
  96. data/spec/unit/rom/commands/result_spec.rb +14 -0
  97. data/spec/unit/rom/commands_spec.rb +174 -0
  98. data/spec/unit/rom/env_spec.rb +40 -7
  99. data/spec/unit/rom/global_spec.rb +14 -0
  100. data/spec/unit/rom/{mapper_builder_spec.rb → mapper/dsl_spec.rb} +52 -38
  101. data/spec/unit/rom/mapper_spec.rb +51 -10
  102. data/spec/unit/rom/{adapter/memory → memory}/dataset_spec.rb +6 -4
  103. data/spec/unit/rom/memory/repository_spec.rb +12 -0
  104. data/spec/unit/rom/memory/storage_spec.rb +45 -0
  105. data/spec/unit/rom/model_builder_spec.rb +4 -3
  106. data/spec/unit/rom/processor/transproc_spec.rb +1 -0
  107. data/spec/unit/rom/reader_spec.rb +97 -24
  108. data/spec/unit/rom/relation/composite_spec.rb +65 -0
  109. data/spec/unit/rom/relation/lazy_spec.rb +145 -0
  110. data/spec/unit/rom/relation/loaded_spec.rb +28 -0
  111. data/spec/unit/rom/relation_spec.rb +111 -6
  112. data/spec/unit/rom/repository_spec.rb +59 -9
  113. data/spec/unit/rom/setup_spec.rb +99 -11
  114. data/spec/unit/rom/support/array_dataset_spec.rb +59 -0
  115. data/spec/unit/rom/support/class_builder_spec.rb +42 -0
  116. data/spec/unit/rom/support/enumerable_dataset_spec.rb +17 -0
  117. data/spec/unit/rom/support/inflector_spec.rb +89 -0
  118. data/spec/unit/rom/support/options_spec.rb +119 -0
  119. metadata +74 -112
  120. data/lib/rom/adapter.rb +0 -191
  121. data/lib/rom/adapter/memory.rb +0 -32
  122. data/lib/rom/adapter/memory/commands.rb +0 -31
  123. data/lib/rom/adapter/memory/dataset.rb +0 -67
  124. data/lib/rom/adapter/memory/storage.rb +0 -26
  125. data/lib/rom/commands/with_options.rb +0 -18
  126. data/lib/rom/config.rb +0 -70
  127. data/lib/rom/mapper_builder.rb +0 -52
  128. data/lib/rom/mapper_builder/mapper_dsl.rb +0 -114
  129. data/lib/rom/mapper_builder/model_dsl.rb +0 -29
  130. data/lib/rom/reader_builder.rb +0 -48
  131. data/lib/rom/relation_builder.rb +0 -62
  132. data/lib/rom/setup/base_relation_dsl.rb +0 -46
  133. data/lib/rom/setup/command_dsl.rb +0 -46
  134. data/lib/rom/setup/mapper_dsl.rb +0 -19
  135. data/lib/rom/setup/relation_dsl.rb +0 -20
  136. data/lib/rom/setup/schema_dsl.rb +0 -33
  137. data/spec/integration/adapters/extending_relations_spec.rb +0 -41
  138. data/spec/integration/commands/try_spec.rb +0 -27
  139. data/spec/integration/schema_spec.rb +0 -77
  140. data/spec/unit/config_spec.rb +0 -60
  141. data/spec/unit/rom/adapter_spec.rb +0 -79
  142. data/spec/unit/rom_spec.rb +0 -14
data/lib/rom/adapter.rb DELETED
@@ -1,191 +0,0 @@
1
- require 'addressable/uri'
2
-
3
- module ROM
4
- # Abstract adapter class
5
- #
6
- # @api public
7
- class Adapter
8
- include Equalizer.new(:connection)
9
-
10
- # Return connection URI associated with the adapter
11
- #
12
- # @return [String]
13
- #
14
- # @api public
15
- attr_reader :uri
16
-
17
- # Return connection object
18
- #
19
- # @return [Object] type varies depending on the adapter
20
- #
21
- # @api public
22
- attr_reader :connection
23
-
24
- # Additional options hash
25
- #
26
- # @return [Hash]
27
- #
28
- # @api public
29
- attr_reader :options
30
-
31
- # @api private
32
- def self.inherited(adapter)
33
- Adapter.adapters.unshift(adapter)
34
- end
35
-
36
- # @api private
37
- def self.adapters
38
- @_adapters ||= []
39
- end
40
-
41
- # Setup an adapter instance with the given connection URI
42
- #
43
- # @example
44
- #
45
- # Adapter = Class.new(ROM::Adapter)
46
- #
47
- # adapter = Adapter.new('mysql://localhost/test')
48
- #
49
- # adapter.uri.scheme # => 'mysql'
50
- # adapter.uri.host # => 'localhost'
51
- # adapter.uri.path # => '/test'
52
- #
53
- # @param [String] uri_string
54
- #
55
- # @return [Adapter]
56
- #
57
- # @api public
58
- def self.setup(uri_string, options = {})
59
- uri = Addressable::URI.parse(uri_string)
60
- adapter = self[uri.scheme]
61
-
62
- unless adapter
63
- raise ArgumentError, "#{uri_string.inspect} uri is not supported"
64
- end
65
-
66
- adapter.new(uri, options)
67
- end
68
-
69
- # Register adapter class
70
- #
71
- # @example
72
- #
73
- # Adapter = Class.new(ROM::Adapter) {
74
- # def self.schemes
75
- # [:super_db]
76
- # end
77
- # }
78
- #
79
- # ROM::Adapter.register(Adapter)
80
- # ROM::Adapter[:super_db] # => Adapter
81
- #
82
- # @return [Array] registered adapters
83
- #
84
- # @api public
85
- def self.register(_adapter)
86
- warn "Adapter.register is no longer needed [#{caller[0]}"
87
- end
88
-
89
- # Return adapter class for the given scheme
90
- #
91
- # @see Adapter.register
92
- #
93
- # @return [Class] adapter class
94
- #
95
- # @api public
96
- def self.[](scheme)
97
- adapters.detect { |adapter| adapter.schemes.include?(scheme.to_sym) }
98
- end
99
-
100
- # Hook for adapters to normalize scheme name
101
- #
102
- # @api private
103
- def self.normalize_scheme(scheme)
104
- scheme
105
- end
106
-
107
- # @api private
108
- def self.database_file?(_scheme)
109
- false
110
- end
111
-
112
- # @api private
113
- def initialize(uri, options = {})
114
- @uri = uri
115
- @options = options
116
- end
117
-
118
- # Extension hook for adding adapter-specific behavior to a relation class
119
- #
120
- # @param [Class] klass Relation class generated by ROM
121
- #
122
- # @return [Class] extended relation class
123
- #
124
- # @api public
125
- def extend_relation_class(klass)
126
- klass
127
- end
128
-
129
- # Extension hook for adding adapter-specific behavior to a relation instance
130
- #
131
- # @param [Relation] relation
132
- #
133
- # @return [Relation] extended relation instance
134
- #
135
- # @api public
136
- def extend_relation_instance(relation)
137
- relation
138
- end
139
-
140
- # Builds a command
141
- #
142
- # @param [Symbol] name of the command
143
- # @param [Relation] relation used by the command
144
- # @param [CommandDSL::Definition] command definition object
145
- #
146
- # @return [Object] created command instance
147
- #
148
- # @api public
149
- def command(name, relation, definition)
150
- type = definition.type || name
151
-
152
- klass =
153
- case type
154
- when :create then command_namespace.const_get(:Create)
155
- when :update then command_namespace.const_get(:Update)
156
- when :delete then command_namespace.const_get(:Delete)
157
- else
158
- raise ArgumentError, "#{type.inspect} is not a supported command type"
159
- end
160
-
161
- klass.new(relation, definition.to_h)
162
- end
163
-
164
- # Schema inference hook
165
- #
166
- # Every adapter that supports schema inference should implement this method
167
- #
168
- # @return [Array] array with datasets and their names
169
- #
170
- # @api private
171
- def schema
172
- []
173
- end
174
-
175
- # Disconnect is optional and it's a no-op by default
176
- #
177
- # @api public
178
- def disconnect
179
- # noop
180
- end
181
-
182
- # Return namespace with adapter-specific command classes
183
- #
184
- # @return [Module]
185
- #
186
- # @api private
187
- def command_namespace
188
- self.class.const_get(:Commands)
189
- end
190
- end
191
- end
@@ -1,32 +0,0 @@
1
- require 'rom/adapter/memory/storage'
2
- require 'rom/adapter/memory/dataset'
3
- require 'rom/adapter/memory/commands'
4
-
5
- module ROM
6
- class Adapter
7
- class Memory < Adapter
8
- attr_accessor :logger
9
-
10
- def self.schemes
11
- [:memory]
12
- end
13
-
14
- def initialize(*args)
15
- super
16
- @connection = Storage.new
17
- end
18
-
19
- def dataset(name, header = [])
20
- connection.create_dataset(name, header)
21
- end
22
-
23
- def dataset?(name)
24
- connection.key?(name)
25
- end
26
-
27
- def [](name)
28
- connection[name]
29
- end
30
- end
31
- end
32
- end
@@ -1,31 +0,0 @@
1
- module ROM
2
- class Adapter
3
- class Memory < Adapter
4
- module Commands
5
- class Create < ROM::Commands::Create
6
- def execute(tuple)
7
- attributes = input[tuple]
8
- validator.call(attributes)
9
- [relation.insert(attributes.to_h).to_a.last]
10
- end
11
- end
12
-
13
- class Update < ROM::Commands::Update
14
- def execute(params)
15
- attributes = input[params]
16
- validator.call(attributes)
17
- relation.map { |tuple| tuple.update(attributes.to_h) }
18
- end
19
- end
20
-
21
- class Delete < ROM::Commands::Delete
22
- def execute
23
- tuples = target.to_a
24
- tuples.each { |tuple| relation.delete(tuple) }
25
- tuples
26
- end
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,67 +0,0 @@
1
- module ROM
2
- class Adapter
3
- class Memory < Adapter
4
- class Dataset
5
- include Charlatan.new(:data)
6
-
7
- attr_reader :header
8
-
9
- def initialize(data, header)
10
- super
11
- @header = header
12
- end
13
-
14
- def to_ary
15
- data.dup
16
- end
17
- alias_method :to_a, :to_ary
18
-
19
- def each(&block)
20
- return to_enum unless block
21
- data.each(&block)
22
- end
23
-
24
- def join(*args)
25
- left, right = args.size > 1 ? args : [self, args.first]
26
-
27
- join_map = left.to_a.each_with_object({}) { |tuple, h|
28
- others = right.to_a.find_all { |t| (tuple.to_a & t.to_a).any? }
29
- (h[tuple] ||= []).concat(others)
30
- }
31
-
32
- tuples = left.map { |tuple|
33
- join_map[tuple].map { |other| tuple.merge(other) }
34
- }.flatten
35
-
36
- self.class.new(tuples, left.header + right.header)
37
- end
38
-
39
- def restrict(criteria = nil)
40
- if criteria
41
- find_all { |tuple| criteria.all? { |k, v| tuple[k].eql?(v) } }
42
- else
43
- find_all { |tuple| yield(tuple) }
44
- end
45
- end
46
-
47
- def project(*names)
48
- map { |tuple| tuple.reject { |key| !names.include?(key) } }
49
- end
50
-
51
- def order(*names)
52
- sort_by { |tuple| tuple.values_at(*names) }
53
- end
54
-
55
- def insert(tuple)
56
- data << tuple
57
- self
58
- end
59
-
60
- def delete(tuple)
61
- data.delete(tuple)
62
- self
63
- end
64
- end
65
- end
66
- end
67
- end
@@ -1,26 +0,0 @@
1
- module ROM
2
- class Adapter
3
- class Memory < Adapter
4
- class Storage
5
- attr_reader :data
6
-
7
- def initialize(*)
8
- super
9
- @data = {}
10
- end
11
-
12
- def [](name)
13
- data[name]
14
- end
15
-
16
- def create_dataset(name, header)
17
- data[name] = Dataset.new([], header)
18
- end
19
-
20
- def key?(name)
21
- data.key?(name)
22
- end
23
- end
24
- end
25
- end
26
- end
@@ -1,18 +0,0 @@
1
- module ROM
2
- module Commands
3
- # Common behavior for Create and Update commands
4
- #
5
- # TODO: find a better name for this module
6
- module WithOptions
7
- attr_reader :validator, :input
8
-
9
- # @api private
10
- def initialize(relation, options)
11
- super
12
-
13
- @validator = options[:validator] || proc {}
14
- @input = options[:input] || Hash
15
- end
16
- end
17
- end
18
- end
data/lib/rom/config.rb DELETED
@@ -1,70 +0,0 @@
1
- module ROM
2
- # Helper class used by ROM internally to deal with various configuration hashes
3
- #
4
- # @private
5
- class Config
6
- BASE_OPTIONS = [
7
- :adapter,
8
- :database,
9
- :password,
10
- :username,
11
- :hostname,
12
- :root
13
- ].freeze
14
-
15
- # Builds a configuration hash from a flat database config hash or a string
16
- #
17
- # This is used to support typical database.yml-complaint configs. It also
18
- # uses adapter interface for things that are adapter-specific like handling
19
- # schema naming.
20
- #
21
- # @param [Hash,String]
22
- #
23
- # @return [Hash]
24
- #
25
- # @api private
26
- def self.build(config, options = {})
27
- return config_hash(config, options) if config.is_a?(String)
28
-
29
- return config unless config[:database]
30
-
31
- root = config[:root]
32
-
33
- raw_scheme = config[:adapter]
34
- database = config[:database]
35
- password = config.fetch(:password) { '' }
36
- username = config[:username]
37
- hostname = config.fetch(:hostname) { 'localhost' }
38
-
39
- adapter = Adapter[raw_scheme]
40
- scheme = adapter.normalize_scheme(raw_scheme)
41
-
42
- path =
43
- if adapter.database_file?(scheme)
44
- [root, database].compact.join('/')
45
- else
46
- db_path = [hostname, database].join('/')
47
-
48
- if username && password
49
- [[username, password].join(':'), db_path].join('@')
50
- else
51
- db_path
52
- end
53
- end
54
-
55
- other_keys = config.keys - BASE_OPTIONS
56
- options = Hash[other_keys.zip(config.values_at(*other_keys))]
57
-
58
- config_hash("#{scheme}://#{path}", options)
59
- end
60
-
61
- # @api private
62
- def self.config_hash(uri, options = {})
63
- if options.any?
64
- { default: { uri: uri, options: options } }
65
- else
66
- { default: uri }
67
- end
68
- end
69
- end
70
- end
@@ -1,52 +0,0 @@
1
- require 'rom/mapper_builder/model_dsl'
2
- require 'rom/mapper_builder/mapper_dsl'
3
-
4
- module ROM
5
- # @api private
6
- class MapperBuilder
7
- attr_reader :name, :root, :options, :prefix, :symbolize_keys, :dsl
8
-
9
- DEFAULT_PROCESSOR = :transproc
10
-
11
- def initialize(name, root, options = {})
12
- @name = name
13
- @options = options
14
- @root = root
15
- @prefix = options[:prefix]
16
- @symbolize_keys = options[:symbolize_keys]
17
-
18
- attributes =
19
- if options[:inherit_header]
20
- root.header.map { |attr| [prefix ? :"#{prefix}_#{attr}" : attr] }
21
- else
22
- []
23
- end
24
-
25
- @dsl = MapperDSL.new(attributes, options)
26
-
27
- @processor = DEFAULT_PROCESSOR
28
- end
29
-
30
- def processor(identifier = nil)
31
- if identifier
32
- @processor = identifier
33
- else
34
- @processor
35
- end
36
- end
37
-
38
- def call
39
- Mapper.build(dsl.header, processor)
40
- end
41
-
42
- private
43
-
44
- def method_missing(name, *args, &block)
45
- if dsl.respond_to?(name)
46
- dsl.public_send(name, *args, &block)
47
- else
48
- super
49
- end
50
- end
51
- end
52
- end