rom 0.6.2 → 0.7.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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/.rubocop.yml +9 -0
  4. data/CHANGELOG.md +34 -0
  5. data/CONTRIBUTING.md +1 -0
  6. data/Gemfile +1 -1
  7. data/README.md +12 -7
  8. data/lib/rom.rb +8 -0
  9. data/lib/rom/command.rb +19 -0
  10. data/lib/rom/commands/abstract.rb +6 -1
  11. data/lib/rom/commands/composite.rb +1 -52
  12. data/lib/rom/commands/update.rb +4 -1
  13. data/lib/rom/constants.rb +1 -0
  14. data/lib/rom/env.rb +3 -25
  15. data/lib/rom/global.rb +23 -0
  16. data/lib/rom/global/plugin_dsl.rb +47 -0
  17. data/lib/rom/header.rb +19 -8
  18. data/lib/rom/header/attribute.rb +14 -2
  19. data/lib/rom/lint/enumerable_dataset.rb +3 -1
  20. data/lib/rom/lint/repository.rb +5 -5
  21. data/lib/rom/mapper.rb +2 -1
  22. data/lib/rom/mapper/attribute_dsl.rb +86 -13
  23. data/lib/rom/mapper/dsl.rb +20 -1
  24. data/lib/rom/memory/commands.rb +3 -1
  25. data/lib/rom/memory/dataset.rb +1 -1
  26. data/lib/rom/memory/relation.rb +1 -1
  27. data/lib/rom/pipeline.rb +91 -0
  28. data/lib/rom/plugin.rb +31 -0
  29. data/lib/rom/plugin_registry.rb +134 -0
  30. data/lib/rom/plugins/relation/registry_reader.rb +30 -0
  31. data/lib/rom/processor/transproc.rb +78 -3
  32. data/lib/rom/relation/class_interface.rb +14 -2
  33. data/lib/rom/relation/composite.rb +9 -97
  34. data/lib/rom/relation/graph.rb +76 -0
  35. data/lib/rom/relation/lazy.rb +15 -63
  36. data/lib/rom/relation/materializable.rb +66 -0
  37. data/lib/rom/setup/finalize.rb +16 -5
  38. data/lib/rom/setup_dsl/mapper_dsl.rb +10 -2
  39. data/lib/rom/setup_dsl/setup.rb +1 -1
  40. data/lib/rom/support/array_dataset.rb +7 -4
  41. data/lib/rom/support/data_proxy.rb +7 -7
  42. data/lib/rom/support/deprecations.rb +17 -0
  43. data/lib/rom/support/enumerable_dataset.rb +10 -3
  44. data/lib/rom/support/inflector.rb +1 -1
  45. data/lib/rom/version.rb +1 -1
  46. data/rom.gemspec +1 -1
  47. data/spec/integration/commands/create_spec.rb +3 -3
  48. data/spec/integration/commands/update_spec.rb +24 -4
  49. data/spec/integration/mappers/combine_spec.rb +107 -0
  50. data/spec/integration/mappers/registering_custom_mappers_spec.rb +29 -0
  51. data/spec/integration/mappers/reusing_mappers_spec.rb +22 -0
  52. data/spec/integration/mappers/unwrap_spec.rb +98 -0
  53. data/spec/integration/multi_repo_spec.rb +2 -2
  54. data/spec/integration/repositories/extending_relations_spec.rb +9 -0
  55. data/spec/integration/setup_spec.rb +2 -2
  56. data/spec/shared/enumerable_dataset.rb +4 -1
  57. data/spec/shared/materializable.rb +34 -0
  58. data/spec/shared/proxy.rb +0 -0
  59. data/spec/spec_helper.rb +6 -2
  60. data/spec/support/mutant.rb +9 -6
  61. data/spec/unit/rom/commands_spec.rb +3 -3
  62. data/spec/unit/rom/header_spec.rb +2 -2
  63. data/spec/unit/rom/mapper/dsl_spec.rb +102 -1
  64. data/spec/unit/rom/memory/dataset_spec.rb +10 -33
  65. data/spec/unit/rom/memory/relation_spec.rb +63 -0
  66. data/spec/unit/rom/memory/storage_spec.rb +2 -2
  67. data/spec/unit/rom/plugin_spec.rb +121 -0
  68. data/spec/unit/rom/processor/transproc_spec.rb +47 -6
  69. data/spec/unit/rom/relation/composite_spec.rb +3 -1
  70. data/spec/unit/rom/relation/graph_spec.rb +78 -0
  71. data/spec/unit/rom/relation/lazy/combine_spec.rb +130 -0
  72. data/spec/unit/rom/relation/lazy_spec.rb +3 -1
  73. data/spec/unit/rom/relation/loaded_spec.rb +3 -1
  74. data/spec/unit/rom/setup_spec.rb +8 -8
  75. data/spec/unit/rom/support/array_dataset_spec.rb +3 -1
  76. data/spec/unit/rom/support/class_builder_spec.rb +2 -2
  77. metadata +24 -7
  78. data/lib/rom/relation/registry_reader.rb +0 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4c8c7b27e645de962baf5ff8f13ec9d7bc49f99b
4
- data.tar.gz: 122627edb665db07dd980bab718b6d5478f74938
3
+ metadata.gz: 9513b27090115add08f6f4f4d8e446b7e805d0d8
4
+ data.tar.gz: 4a33b39b54ee48c1d551138688e864a3b6052970
5
5
  SHA512:
6
- metadata.gz: d2f9fa00b8f6d7d577a3cc30b415bba53f02b3820a29795f940bcd81025ef858524518580d603956fbf753b7de3c66b7b541e3b0f786383eff0e9f06eec29fb5
7
- data.tar.gz: d73cecf26ac256e6112e8a736f53a9e1621ec4faf7272214da4b229251d83b1636902b1d9ea92085bf971b449791e04e3c1c654270bd7b1d1495c4fb764d7987
6
+ metadata.gz: 17c5de3ec96c11fcf6d95fd06c89ef1f76af66f6468bdbb139a421f5a7125ae1aae228021303b778e8150abf4a3650753ec164eb4aa393997e3a44cd42bbfcaf
7
+ data.tar.gz: 5ded7613f606353f66371b9bc537c6a24c30f72e58d8a741f24133e976fa2d898609ca56bd4bf41a993827b3bda3f937b69dbc1f9c7ce9b432439ddfad0a1786
data/.rspec CHANGED
@@ -1,2 +1,3 @@
1
1
  --color
2
2
  --order random
3
+ --warnings
@@ -10,6 +10,15 @@ AllCops:
10
10
  Lint/AssignmentInCondition:
11
11
  Enabled: false
12
12
 
13
+ Style/BlockDelimiters:
14
+ EnforcedStyle: semantic
15
+ FunctionalMethods:
16
+ - let
17
+ - let!
18
+ - subject
19
+ - watch
20
+ - before
21
+
13
22
  # No need to handle LoadError in Rakefile
14
23
  Lint/HandleExceptions:
15
24
  Exclude:
@@ -1,3 +1,37 @@
1
+ ## v0.7.0 2015-05-17
2
+
3
+ ### Added
4
+
5
+ * `combine` interface in Relation and Mapper which allows simple and explicit
6
+ eager-loading that works with all adapters (solnic)
7
+ * `reject_keys` option in mapper which will filter out unspecified keys from
8
+ input tuples (solnic)
9
+ * `unwrap` mapping operation (aflatter)
10
+ * Arbitrary objects can be registered as mappers via `register` in mapping DSL (solnic)
11
+ * Ability to reuse existing mappers in `group`, `wrap` and `embedded` mappings (solnic)
12
+ * Plugin interface for Relation, Mapper and Command (cflipse)
13
+ * `Memory::Dataset` accepts options hash now which makes it more flexible for
14
+ any adapter that wants to subclass it (solnic)
15
+ * `ROM::Memory::Relation#take` (solnic)
16
+
17
+ ### Changed
18
+
19
+ * [BREAKING] `Command#call` applies curried args first (solnic)
20
+ * `Commands::Update#set` was deprecated in favor of `call` (solnic)
21
+ * `group` mapping reject empty tuples (solnic)
22
+
23
+ ### Fixed
24
+
25
+ * `Command` respond to missing properly now (solnic)
26
+ * `Mapper::DSL` respond to missing properly now (solnic)
27
+
28
+ ### Internal
29
+
30
+ * Fixed all the warnings \o/ (splattael)
31
+ * Introduced `Deprecations` helper module (solnic)
32
+
33
+ [Compare v0.6.2...v0.7.0](https://github.com/rom-rb/rom/compare/v0.6.2...v0.7.0)
34
+
1
35
  ## v0.6.2 2015-04-14
2
36
 
3
37
  ### Changed
@@ -0,0 +1 @@
1
+ For information about contributing please refer to [Contribute](http://rom-rb.org/contribute) section on ROM website.
data/Gemfile CHANGED
@@ -30,7 +30,7 @@ end
30
30
 
31
31
  group :benchmarks do
32
32
  gem 'activerecord', '4.2.0'
33
- gem 'benchmark-ips', git: 'https://github.com/evanphx/benchmark-ips.git', branch: 'master'
33
+ gem 'benchmark-ips', '~> 2.2.0'
34
34
  end
35
35
 
36
36
  group :tools do
data/README.md CHANGED
@@ -5,11 +5,11 @@
5
5
  [coveralls]: https://coveralls.io/r/rom-rb/rom
6
6
  [inchpages]: http://inch-ci.org/github/rom-rb/rom/
7
7
 
8
- # Ruby Object Mapper
8
+ # Ruby Object Mapper [![Gitter chat](https://badges.gitter.im/rom-rb/chat.svg)](https://gitter.im/rom-rb/chat) [![Stories in Ready](https://badge.waffle.io/rom-rb/rom.png?label=ready&title=Ready)](https://waffle.io/rom-rb/rom)
9
9
 
10
10
  [![Gem Version](https://badge.fury.io/rb/rom.svg)][gem]
11
11
  [![Build Status](https://travis-ci.org/rom-rb/rom.svg?branch=master)][travis]
12
- [![Dependency Status](https://gemnasium.com/rom-rb/rom.png)][gemnasium]
12
+ [![Dependency Status](https://gemnasium.com/rom-rb/rom.svg)][gemnasium]
13
13
  [![Code Climate](https://codeclimate.com/github/rom-rb/rom/badges/gpa.svg)][codeclimate]
14
14
  [![Test Coverage](https://codeclimate.com/github/rom-rb/rom/badges/coverage.svg)][codeclimate]
15
15
  [![Inline docs](http://inch-ci.org/github/rom-rb/rom.svg?branch=master&style=flat)][inchpages]
@@ -30,12 +30,19 @@ Learn more:
30
30
  * [rom-mongo](https://github.com/rom-rb/rom-mongo)
31
31
  * [rom-yaml](https://github.com/rom-rb/rom-yaml)
32
32
  * [rom-csv](https://github.com/rom-rb/rom-csv)
33
+ * [rom-neo4j](https://github.com/rom-rb/rom-neo4j)
34
+ * [rom-event_store](https://github.com/rom-rb/rom-event_store)
35
+ * [rom-influxdb](https://github.com/rom-rb/rom-influxdb)
36
+ * [rom-rethinkdb](https://github.com/rom-rb/rom-rethinkdb)
33
37
 
34
38
  See [issues](https://github.com/rom-rb/rom/issues?q=is%3Aopen+is%3Aissue+label%3Aadapter+label%3Afeature)
35
39
  for a list of adapters that are planned to be added soon.
36
40
 
37
- ROM can be used with Rails next to ActiveRecord via [rom-rails](https://github.com/rom-rb/rom-rails) railtie.
38
- Integration with other frameworks is planned.
41
+ ## Framework integrations
42
+
43
+ * [rom-lotus](https://github.com/rom-rb/rom-lotus)
44
+ * [rom-rails](https://github.com/rom-rb/rom-rails)
45
+ * [rom-roda](https://github.com/rom-rb/rom-roda)
39
46
 
40
47
  ## Synopsis
41
48
 
@@ -97,13 +104,11 @@ puts rom.relation(:users) { |r| r.by_name("Jane").adults }.as(:entity).to_a.insp
97
104
 
98
105
  ## ROADMAP
99
106
 
100
- ROM is on its way towards 1.0.0. Please refer to [issues](https://github.com/rom-rb/rom/issues)
101
- for details.
107
+ ROM is on its way towards 1.0.0. You can see an overview of tasks scheduled for 1.0.0 on our [waffle board](https://waffle.io/rom-rb/rom?label=1.0.0). Please notice that most of the 1.0.0 features/changes will become part of minor (0.x) upgrades before 1.0.0 final gets released.
102
108
 
103
109
  ## Community
104
110
 
105
111
  * [Official Blog](http://rom-rb.org/blog/)
106
- * [![Gitter chat](https://badges.gitter.im/rom-rb/chat.png)](https://gitter.im/rom-rb/chat)
107
112
  * [Ruby Object Mapper](https://groups.google.com/forum/#!forum/rom-rb) mailing list
108
113
 
109
114
  ## Credits
data/lib/rom.rb CHANGED
@@ -11,6 +11,7 @@ require 'rom/support/class_macros'
11
11
  require 'rom/support/class_builder'
12
12
 
13
13
  # core parts
14
+ require 'rom/plugin'
14
15
  require 'rom/relation'
15
16
  require 'rom/mapper'
16
17
  require 'rom/command'
@@ -33,3 +34,10 @@ module ROM
33
34
 
34
35
  RelationRegistry = Class.new(Registry)
35
36
  end
37
+
38
+ # register core plugins
39
+ require 'rom/plugins/relation/registry_reader'
40
+
41
+ ROM.plugins do
42
+ register :registry_reader, ROM::Plugins::Relation::RegistryReader, type: :relation
43
+ end
@@ -70,6 +70,25 @@ module ROM
70
70
  new(relation, self.options.merge(options))
71
71
  end
72
72
 
73
+ # Use a configured plugin in this relation
74
+ #
75
+ # @example
76
+ # class CreateUser < ROM::Commands::Create[:memory]
77
+ # use :pagintion
78
+ #
79
+ # per_page 30
80
+ # end
81
+ #
82
+ # @param [Symbol] plugin
83
+ # @param [Hash] options
84
+ # @option options [Symbol] :adapter (:default) first adapter to check for plugin
85
+ #
86
+ # @api public
87
+ def self.use(plugin, options = {})
88
+ adapter = options.fetch(:adapter, :default)
89
+ ROM.plugin_registry.commands.fetch(plugin, adapter).apply_to(self)
90
+ end
91
+
73
92
  # Build command registry hash for provided relations
74
93
  #
75
94
  # @param [RelationRegistry] relations registry
@@ -49,7 +49,7 @@ module ROM
49
49
  #
50
50
  # @api public
51
51
  def call(*args)
52
- tuples = execute(*(args + curry_args))
52
+ tuples = execute(*(curry_args + args))
53
53
 
54
54
  if result == :one
55
55
  tuples.first
@@ -133,6 +133,11 @@ module ROM
133
133
  target.count
134
134
  end
135
135
 
136
+ # @api private
137
+ def respond_to_missing?(name, _include_private = false)
138
+ relation.respond_to?(name) || super
139
+ end
140
+
136
141
  private
137
142
 
138
143
  # @api private
@@ -3,24 +3,7 @@ module ROM
3
3
  # Composite command that consists of left and right commands
4
4
  #
5
5
  # @api public
6
- class Composite
7
- include Equalizer.new(:left, :right)
8
-
9
- # @return [Proc,Command] left command
10
- #
11
- # @api private
12
- attr_reader :left
13
-
14
- # @return [Proc,Command] right command
15
- #
16
- # @api private
17
- attr_reader :right
18
-
19
- # @api private
20
- def initialize(left, right)
21
- @left, @right = left, right
22
- end
23
-
6
+ class Composite < Pipeline::Composite
24
7
  # Calls the composite command
25
8
  #
26
9
  # Right command is called with a result from the left one
@@ -43,44 +26,10 @@ module ROM
43
26
  end
44
27
  alias_method :[], :call
45
28
 
46
- # Compose another composite command from self and other
47
- #
48
- # @param [Proc, Command] other command
49
- #
50
- # @return [Composite]
51
- #
52
- # @api public
53
- def >>(other)
54
- self.class.new(self, other)
55
- end
56
-
57
29
  # @api private
58
30
  def result
59
31
  left.result
60
32
  end
61
-
62
- # @api private
63
- def respond_to_missing?(name, include_private = false)
64
- left.respond_to?(name) || super
65
- end
66
-
67
- private
68
-
69
- # Allow calling methods on the left side object
70
- #
71
- # @api private
72
- def method_missing(name, *args, &block)
73
- if left.respond_to?(name)
74
- response = left.__send__(name, *args, &block)
75
- if response.is_a?(left.class)
76
- self.class.new(response, right)
77
- else
78
- response
79
- end
80
- else
81
- super
82
- end
83
- end
84
33
  end
85
34
  end
86
35
  end
@@ -1,4 +1,5 @@
1
1
  require 'rom/command'
2
+ require 'rom/support/deprecations'
2
3
 
3
4
  module ROM
4
5
  module Commands
@@ -8,12 +9,14 @@ module ROM
8
9
  #
9
10
  # @abstract
10
11
  class Update < Command
12
+ extend Deprecations
13
+
11
14
  # @see AbstractCommand#call
12
15
  def call(*args)
13
16
  assert_tuple_count
14
17
  super
15
18
  end
16
- alias_method :set, :call
19
+ deprecate :set, :call
17
20
  end
18
21
  end
19
22
  end
@@ -10,6 +10,7 @@ module ROM
10
10
  CommandError = Class.new(StandardError)
11
11
  TupleCountMismatchError = Class.new(CommandError)
12
12
  MapperMissingError = Class.new(StandardError)
13
+ UnknownPluginError = Class.new(StandardError)
13
14
 
14
15
  InvalidOptionValueError = Class.new(StandardError)
15
16
  InvalidOptionKeyError = Class.new(StandardError)
@@ -1,10 +1,12 @@
1
1
  require 'rom/relation/loaded'
2
+ require 'rom/support/deprecations'
2
3
 
3
4
  module ROM
4
5
  # Exposes defined repositories, relations and mappers
5
6
  #
6
7
  # @api public
7
8
  class Env
9
+ extend Deprecations
8
10
  include Equalizer.new(:repositories, :relations, :mappers, :commands)
9
11
 
10
12
  # @return [Hash] configured repositories
@@ -69,31 +71,7 @@ module ROM
69
71
  relation.to_lazy
70
72
  end
71
73
  end
72
-
73
- # Returns a reader with access to defined mappers
74
- #
75
- # @example
76
- #
77
- # # with a mapper derived from relation access path "users.adults"
78
- # rom.read(:users).adults.to_a
79
- #
80
- # # or with explicit mapper name
81
- # rom.read(:users).with(:some_mapper).to_a
82
- #
83
- # @param [Symbol] name of the registered reader
84
- #
85
- # @deprecated
86
- #
87
- # @api public
88
- def read(name, &block)
89
- warn <<-MSG.gsub(/^\s+/, '')
90
- #{self.class}#read is deprecated.
91
- Please use `#{self.class}#relation(#{name.inspect})` instead.
92
- For mapping append `.map_with(:your_mapper_name)`
93
- [#{caller[0]}]
94
- MSG
95
- relation(name, &block)
96
- end
74
+ deprecate :read, :relation, "For mapping append `.map_with(:your_mapper_name)`"
97
75
 
98
76
  # Returns commands registry for the given relation
99
77
  #
@@ -1,5 +1,8 @@
1
1
  require 'rom/setup'
2
2
  require 'rom/repository'
3
+ require 'rom/plugin_registry'
4
+
5
+ require 'rom/global/plugin_dsl'
3
6
 
4
7
  module ROM
5
8
  # Globally accessible public interface exposed via ROM module
@@ -14,6 +17,7 @@ module ROM
14
17
 
15
18
  rom.instance_variable_set('@adapters', {})
16
19
  rom.instance_variable_set('@repositories', {})
20
+ rom.instance_variable_set('@plugin_registry', PluginRegistry.new)
17
21
  end
18
22
 
19
23
  # An internal adapter identifier => adapter module map used by setup
@@ -30,6 +34,13 @@ module ROM
30
34
  # @api private
31
35
  attr_reader :repositories
32
36
 
37
+ # An internal identifier => plugin map used by the setup
38
+ #
39
+ # @return [Hash]
40
+ #
41
+ # @api private
42
+ attr_reader :plugin_registry
43
+
33
44
  # Setup object created during env setup phase
34
45
  #
35
46
  # This gets set to nil after setup is finalized
@@ -161,6 +172,18 @@ module ROM
161
172
  boot.mappers(*args, &block)
162
173
  end
163
174
 
175
+ # Global plugin setup DSL
176
+ #
177
+ # @example
178
+ # ROM.plugins do
179
+ # register :publisher, Plugin::Publisher, type: :command
180
+ # end
181
+ #
182
+ # @example
183
+ def plugins(*args, &block)
184
+ PluginDSL.new(plugin_registry, *args, &block)
185
+ end
186
+
164
187
  # Finalize the setup and store default global env under ROM.env
165
188
  #
166
189
  # @example
@@ -0,0 +1,47 @@
1
+ module ROM
2
+ module Global
3
+ # plugin registration DSL
4
+ #
5
+ # @private
6
+ class PluginDSL
7
+ # Default options passed to plugin registration
8
+ #
9
+ # @return [Hash]
10
+ #
11
+ # @api private
12
+ attr_reader :defaults
13
+
14
+ # Plugin registry
15
+ #
16
+ # @return [PluginRegistry]
17
+ #
18
+ # @api private
19
+ attr_reader :registry
20
+
21
+ # @api private
22
+ def initialize(registry, defaults = {}, &block)
23
+ @registry = registry
24
+ @defaults = defaults
25
+ instance_exec(&block)
26
+ end
27
+
28
+ # Register a plugin
29
+ #
30
+ # @param [Symbol] name of the plugin
31
+ # @param [Module] mod to include
32
+ # @param [Hash] options
33
+ #
34
+ # @api public
35
+ def register(name, mod, options = {})
36
+ registry.register(name, mod, defaults.merge(options))
37
+ end
38
+
39
+ # Register plugins for a specific adapter
40
+ #
41
+ # @param [Symbol] adapter type
42
+ def adapter(type, &block)
43
+ self.class.new(registry, adapter: type, &block)
44
+ end
45
+ end
46
+ end
47
+ end