rom 0.6.2 → 0.7.0

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