rom 0.9.0.beta1 → 0.9.0.rc1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ae4a8d67f3c8c7869c5eafa16d721cc6c4ba90eb
4
- data.tar.gz: d2c9c1cdcde7ade22ad695dea60bea91a05bea42
3
+ metadata.gz: 68b700901edb358688ae8f41a8f474cab6dc1254
4
+ data.tar.gz: 97d2569ad4ad0b653e725b0598fe6edb0d6d70b8
5
5
  SHA512:
6
- metadata.gz: d8c3ba712a476f5f326863890e3e4abc42154601501595fb44e321854610ee4fed2d047b6d4c15b56be746c322d641f48f72f1ade653fc96ae547e6370218bef
7
- data.tar.gz: 728ea3d960c3f18e0e314706dd90e6f35e32aa5014755a0875ba0a1613caa29358cad2af2fe7bc2c2b55f7d7fdccc780b60d9be89b297da7a3550440dc9784b0
6
+ metadata.gz: 5627b18505dd2e30d7eca6b6514b84f6f81573cd99a44eb7fb67b15966e37fccc007df8b3d3016b8a65a4363321d10e056e5e93c255c0ef13704693592345c5c
7
+ data.tar.gz: 46dd954fd398b22e3a5a5af01215ff9f52ab51ee9b750de68d7a5c9510a4275f29fb9e04914d03cb52e026653cf3c0754fa88aad10fb4feebd8ae28d138ea122
@@ -1,5 +1,30 @@
1
1
  ## v0.9.0 to-be-released
2
2
 
3
+ ### Added
4
+
5
+ * Configuration API for gateways supporting following options:
6
+ - `infer_relations` either `true` or `false` - if disabled schema inference
7
+ won't be used to automatically set up relations for you
8
+ - `inferrable_relations` a list of allowed relations that should be inferred
9
+ - `not_inferrable_relations` a list of relations that should not be inferred
10
+
11
+ ### Changed
12
+
13
+ * Global setup with auto-registration ported to the `:auto_registration` environment plugin (AMHOL)
14
+ * Multi-environment setup possible now via `ROM::Environment` object (AMHOL)
15
+ * All relations are now lazy with auto-currying enabled (solnic)
16
+ * Low-level query DSL provided by adapters is now public but using it directly in
17
+ application layer is discouraged (solnic)
18
+ * `ROM::Mapper` component extracted into standalone `rom-mapper` gem (solnic)
19
+ * Support libraries extracted to `rom-support` gem (solnic)
20
+
21
+ ## Fixed
22
+
23
+ * `register_as` is now properly inferred for relations and their descendants (solnic)
24
+ * Adapter-specific interface is properly included in relation descendants (solnic)
25
+ * Combined commands (aka command graph) properly rejects keys from nested input
26
+ prior sending the input to individual commands (solnic)
27
+
3
28
  [Compare v0.8.1...HEAD](https://github.com/rom-rb/rom/compare/v0.8.1...HEAD)
4
29
 
5
30
  ## v0.8.1 2015-07-12
data/Gemfile CHANGED
@@ -40,7 +40,7 @@ group :tools do
40
40
  gem 'guard-rspec'
41
41
  gem 'guard-rubocop'
42
42
 
43
- gem 'byebug'
43
+ gem 'byebug', platform: :mri
44
44
 
45
45
  platform :mri do
46
46
  gem 'mutant', '>= 0.8.0', github: 'mbj/mutant', branch: 'master'
@@ -77,7 +77,7 @@ module ROM
77
77
  #
78
78
  # @api public
79
79
  def curry(*args)
80
- if curry_args.empty? && args.first.is_a?(Proc)
80
+ if curry_args.empty? && args.first.is_a?(Graph::InputEvaluator)
81
81
  Lazy.new(self, args.first)
82
82
  else
83
83
  self.class.build(relation, options.merge(curry_args: args))
@@ -63,8 +63,6 @@ module ROM
63
63
  end
64
64
  rescue => err
65
65
  raise CommandFailure.new(node, err)
66
- rescue CommandFailure => err
67
- raise err
68
66
  end
69
67
 
70
68
  if node.one? && !node.graph?
@@ -81,8 +79,6 @@ module ROM
81
79
  end
82
80
  rescue => err
83
81
  raise CommandFailure.new(root, err)
84
- rescue CommandFailure => err
85
- raise err
86
82
  end
87
83
  end
88
84
 
@@ -1,3 +1,5 @@
1
+ require 'rom/commands/graph/input_evaluator'
2
+
1
3
  module ROM
2
4
  module Commands
3
5
  class Graph
@@ -31,25 +33,10 @@ module ROM
31
33
  [spec, spec]
32
34
  end
33
35
 
34
- command = registry[relation][name]
35
36
 
37
+ command = registry[relation][name]
36
38
  tuple_path = Array[*path] << key
37
-
38
- input_proc = -> *args do
39
- input, index = args
40
-
41
- begin
42
- if index
43
- tuple_path[0..tuple_path.size-2]
44
- .reduce(input) { |a,e| a.fetch(e) }
45
- .at(index)[tuple_path.last]
46
- else
47
- tuple_path.reduce(input) { |a,e| a.fetch(e) }
48
- end
49
- rescue KeyError => err
50
- raise CommandFailure.new(command, err)
51
- end
52
- end
39
+ input_proc = InputEvaluator.build(tuple_path, nodes)
53
40
 
54
41
  command = command.with(input_proc)
55
42
 
@@ -0,0 +1,58 @@
1
+ module ROM
2
+ module Commands
3
+ class Graph
4
+ class InputEvaluator
5
+ attr_reader :tuple_path
6
+
7
+ attr_reader :excluded_keys
8
+
9
+ attr_reader :exclude_proc
10
+
11
+ def self.build(tuple_path, nodes)
12
+ new(tuple_path, extract_excluded_keys(nodes))
13
+ end
14
+
15
+ def self.extract_excluded_keys(nodes)
16
+ return unless nodes
17
+
18
+ nodes
19
+ .map { |item| item.is_a?(Array) && item.size > 1 ? item.first : item }
20
+ .compact
21
+ .map { |item| item.is_a?(Hash) ? item.keys.first : item }
22
+ .reject { |item| item.is_a?(Array) }
23
+ end
24
+
25
+ def self.exclude_proc(excluded_keys)
26
+ -> input { input.reject { |k, _| excluded_keys.include?(k) } }
27
+ end
28
+
29
+ def initialize(tuple_path, excluded_keys)
30
+ @tuple_path = tuple_path
31
+ @excluded_keys = excluded_keys
32
+ @exclude_proc = self.class.exclude_proc(excluded_keys)
33
+ end
34
+
35
+ def call(*args)
36
+ input, index = args
37
+
38
+ begin
39
+ value =
40
+ if index
41
+ tuple_path[0..tuple_path.size-2]
42
+ .reduce(input) { |a,e| a.fetch(e) }
43
+ .at(index)[tuple_path.last]
44
+ else
45
+ tuple_path.reduce(input) { |a,e| a.fetch(e) }
46
+ end
47
+
48
+ if excluded_keys
49
+ value.is_a?(Array) ? value.map(&exclude_proc) : exclude_proc[value]
50
+ else
51
+ value
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -31,11 +31,15 @@ module ROM
31
31
 
32
32
  if size > 1 && last.is_a?(Array)
33
33
  last.map.with_index do |item, index|
34
- command.call(evaluator[first, index], item)
34
+ input = evaluator.call(first, index)
35
+ command.call(input, item)
35
36
  end.reduce(:concat)
36
37
  else
37
- command.call(evaluator[first], *args[1..size-1])
38
+ input = evaluator.call(first)
39
+ command.call(input, *args[1..size-1])
38
40
  end
41
+ rescue => err
42
+ raise CommandFailure.new(command, err)
39
43
  end
40
44
 
41
45
  # Compose a lazy command with another one
@@ -113,6 +113,11 @@ module ROM
113
113
  config = setup_config(*args)
114
114
  @boot = Setup.new(setup_gateways(config), adapters.keys.first)
115
115
 
116
+ config.each do |name, config_args|
117
+ options = config_args.is_a?(Array) && config_args.last
118
+ load_config(@boot.config.gateways[name], options) if options.is_a?(Hash)
119
+ end
120
+
116
121
  if block
117
122
  @boot.instance_exec(&block)
118
123
  @boot.finalize
@@ -172,7 +177,7 @@ module ROM
172
177
  boot.mappers(*args, &block)
173
178
  end
174
179
 
175
- # Finalize the setup and store default global container under
180
+ # Finalize the setup and store default global container under
176
181
  # ROM::Environmrnt#container
177
182
  #
178
183
  # @example
@@ -213,6 +218,15 @@ module ROM
213
218
  boot.register_command(klass) if boot
214
219
  end
215
220
 
221
+ # Return gateway config that was used to setup this environment's container
222
+ #
223
+ # @return [Configurable::Config]
224
+ #
225
+ # @api public
226
+ def config
227
+ boot.config
228
+ end
229
+
216
230
  private
217
231
 
218
232
  # Helper method to handle single- or multi-repo setup options
@@ -228,11 +242,23 @@ module ROM
228
242
  def setup_gateways(config)
229
243
  config.each_with_object({}) do |(name, spec), hash|
230
244
  identifier, *args = Array(spec)
245
+
231
246
  gateway = Gateway.setup(identifier, *(args.flatten))
232
247
  hash[name] = gateway
233
248
 
234
249
  gateways[gateway] = identifier unless identifier.is_a?(Gateway)
235
250
  end
236
251
  end
252
+
253
+ # @api private
254
+ def load_config(config, hash)
255
+ hash.each do |key, value|
256
+ if value.is_a?(Hash)
257
+ load_config(config[key], value)
258
+ else
259
+ config.send("#{key}=", value)
260
+ end
261
+ end
262
+ end
237
263
  end
238
264
  end
@@ -50,7 +50,13 @@ module ROM
50
50
  See https://github.com/rom-rb/rom/blob/master/CHANGELOG.md
51
51
  STRING
52
52
  when Symbol
53
- class_from_symbol(gateway_or_scheme).new(*args)
53
+ klass = class_from_symbol(gateway_or_scheme)
54
+
55
+ if klass.instance_method(:initialize).arity == 0
56
+ klass.new
57
+ else
58
+ klass.new(*args)
59
+ end
54
60
  else
55
61
  if args.empty?
56
62
  gateway_or_scheme
@@ -19,7 +19,9 @@ module ROM
19
19
  klass.extend Deprecations
20
20
  klass.defines :adapter
21
21
 
22
- return if klass.superclass == ROM::Relation
22
+ # Extend with functionality required by adapters *only* if this is a direct
23
+ # descendant of an adapter-specific relation subclass
24
+ return unless respond_to?(:adapter) && klass.superclass == ROM::Relation[adapter]
23
25
 
24
26
  klass.class_eval do
25
27
  use :registry_reader
@@ -31,7 +33,7 @@ module ROM
31
33
 
32
34
  gateway :default
33
35
 
34
- dataset(default_name)
36
+ dataset default_name
35
37
 
36
38
  # Relation's dataset name
37
39
  #
@@ -44,19 +46,26 @@ module ROM
44
46
 
45
47
  # Set or get name under which a relation will be registered
46
48
  #
47
- # This defaults to `dataset` name
49
+ # This defaults to `dataset` or `default_name` for descendant relations
48
50
  #
49
51
  # @return [Symbol]
50
52
  #
51
53
  # @api public
52
54
  def self.register_as(value = Undefined)
53
55
  if value == Undefined
54
- super() || dataset
56
+ super_val = super()
57
+
58
+ if superclass == ROM::Relation[adapter]
59
+ super_val || dataset
60
+ else
61
+ super_val == dataset ? default_name : super_val
62
+ end
55
63
  else
56
64
  super
57
65
  end
58
66
  end
59
67
 
68
+ # @api public
60
69
  def self.exposed_relations(*args)
61
70
  Deprecations.announce("#{self}.exposed_relations", 'this method has no effect anymore')
62
71
  Set.new
@@ -1,3 +1,5 @@
1
+ require 'rom/support/configurable'
2
+
1
3
  require 'rom/setup/finalize'
2
4
  require 'rom/support/deprecations'
3
5
 
@@ -6,6 +8,8 @@ module ROM
6
8
  #
7
9
  # @api public
8
10
  class Setup
11
+ include Configurable
12
+
9
13
  extend Deprecations
10
14
  include Equalizer.new(:gateways, :container)
11
15
 
@@ -57,15 +61,24 @@ module ROM
57
61
 
58
62
  # Finalize the setup
59
63
  #
60
- # @return [Container] frozen container with access to gateways,
64
+ # @return [Container] frozen container with access to gateways,
61
65
  # relations, mappers and commands
62
66
  #
63
67
  # @api public
64
68
  def finalize
65
69
  raise EnvAlreadyFinalizedError if container
70
+
71
+ # initialize default configs for all gateways
72
+ gateways.each_key do |key|
73
+ gateway_config = config.gateways[key]
74
+
75
+ gateway_config.infer_relations = true unless gateway_config.key?(:infer_relations)
76
+ end
77
+
66
78
  finalize = Finalize.new(
67
- gateways, relation_classes, mapper_classes, command_classes
79
+ gateways, relation_classes, mapper_classes, command_classes, config.freeze
68
80
  )
81
+
69
82
  @container = finalize.run!
70
83
  end
71
84
 
@@ -17,16 +17,17 @@ module ROM
17
17
  # @private
18
18
  class Finalize
19
19
  attr_reader :gateways, :repo_adapter, :datasets,
20
- :relation_classes, :mapper_classes, :mappers, :command_classes
20
+ :relation_classes, :mapper_classes, :mappers, :command_classes, :config
21
21
 
22
22
  # @api private
23
- def initialize(gateways, relation_classes, mappers, command_classes)
23
+ def initialize(gateways, relation_classes, mappers, command_classes, config)
24
24
  @gateways = gateways
25
25
  @repo_adapter_map = ROM.gateways
26
26
  @relation_classes = relation_classes
27
27
  @mapper_classes = mappers.select { |mapper| mapper.is_a?(Class) }
28
28
  @mappers = (mappers - @mapper_classes).reduce(:merge) || {}
29
29
  @command_classes = command_classes
30
+ @config = config
30
31
  initialize_datasets
31
32
  end
32
33
 
@@ -47,7 +48,7 @@ module ROM
47
48
  #
48
49
  # @api private
49
50
  def run!
50
- infer_schema_relations
51
+ infer_relations_relations
51
52
 
52
53
  relations = load_relations
53
54
  mappers = load_mappers
@@ -67,7 +68,7 @@ module ROM
67
68
  # @api private
68
69
  def initialize_datasets
69
70
  @datasets = gateways.each_with_object({}) do |(key, gateway), h|
70
- h[key] = gateway.schema
71
+ h[key] = gateway.schema if config.gateways[key][:infer_relations]
71
72
  end
72
73
  end
73
74
 
@@ -120,16 +121,35 @@ module ROM
120
121
  # Relations explicitly defined are being skipped
121
122
  #
122
123
  # @api private
123
- def infer_schema_relations
124
+ def infer_relations_relations
124
125
  datasets.each do |gateway, schema|
125
126
  schema.each do |name|
126
- next if relation_classes.any? { |klass| klass.dataset == name }
127
- klass = Relation.build_class(name, adapter: adapter_for(gateway))
128
- klass.gateway(gateway)
129
- klass.dataset(name)
127
+ if infer_relation?(gateway, name)
128
+ klass = Relation.build_class(name, adapter: adapter_for(gateway))
129
+ klass.gateway(gateway)
130
+ klass.dataset(name)
131
+ else
132
+ next
133
+ end
130
134
  end
131
135
  end
132
136
  end
137
+
138
+ def infer_relation?(gateway, name)
139
+ inferrable_relations(gateway).include?(name) && relation_classes.none? { |klass|
140
+ klass.dataset == name
141
+ }
142
+ end
143
+
144
+ def inferrable_relations(gateway)
145
+ gateway_config = config.gateways[gateway]
146
+ schema = gateways[gateway].schema
147
+
148
+ allowed = gateway_config[:inferrable_relations] || schema
149
+ skipped = gateway_config[:not_inferrable_relations] || []
150
+
151
+ schema & allowed - skipped
152
+ end
133
153
  end
134
154
  end
135
155
  end
@@ -0,0 +1,66 @@
1
+ module ROM
2
+ # @api private
3
+ module Configurable
4
+ class Config
5
+ WRITER_REGEXP = /=$/.freeze
6
+
7
+ attr_reader :settings
8
+
9
+ # @api private
10
+ def initialize
11
+ @settings = {}
12
+ end
13
+
14
+ # @api public
15
+ def [](name)
16
+ public_send(name)
17
+ end
18
+
19
+ # @api private
20
+ def key?(name)
21
+ settings.key?(name)
22
+ end
23
+
24
+ # @api private
25
+ def freeze
26
+ settings.each_value { |value| value.freeze }
27
+ super
28
+ end
29
+
30
+ # @api private
31
+ def respond_to_missing?(name, include_private = false)
32
+ true
33
+ end
34
+
35
+ private
36
+
37
+ # @api private
38
+ def method_missing(meth, *args, &block)
39
+ return settings.fetch(meth, nil) if frozen?
40
+
41
+ name = meth.to_s
42
+ key = name.gsub(WRITER_REGEXP, '').to_sym
43
+
44
+ if writer?(name)
45
+ settings[key] = args.first
46
+ else
47
+ settings.fetch(key) { settings[key] = self.class.new }
48
+ end
49
+ end
50
+
51
+ # @api private
52
+ def writer?(name)
53
+ ! WRITER_REGEXP.match(name).nil?
54
+ end
55
+ end
56
+
57
+ def config
58
+ @config ||= Config.new
59
+ end
60
+
61
+ # @api public
62
+ def configure
63
+ yield(config)
64
+ end
65
+ end
66
+ end
@@ -1,3 +1,3 @@
1
1
  module ROM
2
- VERSION = '0.9.0.beta1'.freeze
2
+ VERSION = '0.9.0.rc1'.freeze
3
3
  end
@@ -12,15 +12,12 @@ describe 'Building up a command graph for nested input' do
12
12
 
13
13
  setup.commands(:users) do
14
14
  define(:create) do
15
- input T(:accept_keys, [:name])
16
15
  result :one
17
16
  end
18
17
  end
19
18
 
20
19
  setup.commands(:books) do
21
20
  define(:create) do
22
- input T(:accept_keys, [:title, :user])
23
-
24
21
  def execute(tuples, user)
25
22
  super(tuples.map { |t| t.merge(user: user.fetch(:name)) })
26
23
  end
@@ -29,8 +26,6 @@ describe 'Building up a command graph for nested input' do
29
26
 
30
27
  setup.commands(:tags) do
31
28
  define(:create) do
32
- input T(:accept_keys, [:name, :task])
33
-
34
29
  def execute(tuples, task)
35
30
  super(tuples.map { |t| t.merge(task: task.fetch(:title)) })
36
31
  end
@@ -41,7 +36,6 @@ describe 'Building up a command graph for nested input' do
41
36
  it 'creates a command graph for nested input :one result as root' do
42
37
  setup.commands(:tasks) do
43
38
  define(:create) do
44
- input T(:accept_keys, [:title, :user])
45
39
  result :one
46
40
 
47
41
  def execute(tuple, user)
@@ -102,8 +96,6 @@ describe 'Building up a command graph for nested input' do
102
96
  it 'creates a command graph for nested input with :many results as root' do
103
97
  setup.commands(:tasks) do
104
98
  define(:create) do
105
- input T(:accept_keys, [:title, :user])
106
-
107
99
  def execute(tuples, user)
108
100
  super(tuples.map { |t| t.merge(user: user.fetch(:name)) })
109
101
  end
@@ -178,8 +170,6 @@ describe 'Building up a command graph for nested input' do
178
170
 
179
171
  setup.commands(:tasks) do
180
172
  define(:create) do
181
- input T(:accept_keys, [:title, :user])
182
-
183
173
  def execute(tuples, user)
184
174
  super(tuples.map { |t| t.merge(user: user.fetch(:name)) })
185
175
  end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'Inheritance relation hierarchy' do
4
+ before do
5
+ ROM.setup(:memory)
6
+
7
+ module Test
8
+ class Users < ROM::Relation[:memory]
9
+ dataset :users
10
+
11
+ def by_email(email)
12
+ restrict(email: email)
13
+ end
14
+ end
15
+
16
+ class OtherUsers < Users
17
+ register_as :other_users
18
+ end
19
+ end
20
+
21
+ ROM.finalize
22
+ end
23
+
24
+ it 'registers parent and descendant relations' do
25
+ rom = ROM.env
26
+
27
+ users = rom.relations.users
28
+ other_users = rom.relations.other_users
29
+
30
+ expect(users).to be_instance_of(Test::Users)
31
+ expect(other_users).to be_instance_of(Test::OtherUsers)
32
+
33
+ jane = { name: 'Jane', email: 'jane@doe.org' }
34
+
35
+ other_users.insert(jane)
36
+
37
+ expect(other_users.by_email('jane@doe.org').one).to eql(jane)
38
+ end
39
+ end
@@ -29,9 +29,51 @@ describe ROM::Relation do
29
29
  end
30
30
  end
31
31
 
32
- describe '#name' do
33
- before { ROM.setup(:memory) }
32
+ describe ".register_as" do
33
+ it "defaults to dataset with a generated class" do
34
+ rel = Class.new(ROM::Relation[:memory]) { dataset :users }
35
+ expect(rel.register_as).to eq(:users)
36
+ rel.register_as(:guests)
37
+ expect(rel.register_as).to eq(:guests)
38
+ end
39
+
40
+ it "defaults to dataset with a defined class that has dataset inferred" do
41
+ class Test::Users < ROM::Relation[:memory]; end
42
+ expect(Test::Users.register_as).to eq(:test_users)
43
+ end
44
+
45
+ it "defaults to dataset with a defined class that has dataset set manually" do
46
+ class Test::Users < ROM::Relation[:memory]
47
+ dataset :guests
48
+ end
49
+ expect(Test::Users.register_as).to eq(:guests)
50
+ end
51
+
52
+ it "defaults to :name for descendant classes" do
53
+ class Test::SuperUsers < ROM::Relation[:memory]
54
+ dataset :users
55
+ end
56
+
57
+ class Test::DescendantUsers < Test::SuperUsers;end
58
+
59
+ expect(Test::DescendantUsers.register_as).to eq(:test_descendant_users)
60
+ end
61
+
62
+ it "sets custom value for super and descendant classes" do
63
+ class Test::SuperUsers < ROM::Relation[:memory]
64
+ register_as :users
65
+ end
66
+
67
+ class Test::DescendantUsers < Test::SuperUsers
68
+ register_as :descendant_users
69
+ end
70
+
71
+ expect(Test::SuperUsers.register_as).to eq(:users)
72
+ expect(Test::DescendantUsers.register_as).to eq(:descendant_users)
73
+ end
74
+ end
34
75
 
76
+ describe '#name' do
35
77
  context 'missing dataset' do
36
78
  context 'with Relation inside module' do
37
79
  before do
@@ -58,6 +100,19 @@ describe ROM::Relation do
58
100
  expect(relation.name).to eq(:test_super_relation)
59
101
  end
60
102
  end
103
+
104
+ context 'with a descendant relation' do
105
+ before do
106
+ class Test::SuperRelation < ROM::Relation[:memory]; end
107
+ class Test::DescendantRelation < Test::SuperRelation; end
108
+ end
109
+
110
+ it 'inherits :name from the super relation' do
111
+ relation = Test::DescendantRelation.new([])
112
+
113
+ expect(relation.name).to eql(:test_super_relation)
114
+ end
115
+ end
61
116
  end
62
117
 
63
118
  context 'manualy set dataset' do
@@ -93,29 +148,6 @@ describe ROM::Relation do
93
148
  end
94
149
  end
95
150
 
96
- describe ".register_as" do
97
- before { ROM.setup(:memory) }
98
-
99
- it "defaults to dataset with a generated class" do
100
- rel = Class.new(ROM::Relation[:memory]) { dataset :users }
101
- expect(rel.register_as).to eq(:users)
102
- rel.register_as(:guests)
103
- expect(rel.register_as).to eq(:guests)
104
- end
105
-
106
- it "defaults to dataset with a defined class that has dataset inferred" do
107
- class Test::Users < ROM::Relation[:memory]; end
108
- expect(Test::Users.register_as).to eq(:test_users)
109
- end
110
-
111
- it "defaults to dataset with a defined class that has dataset set manually" do
112
- class Test::Users < ROM::Relation[:memory]
113
- dataset :guests
114
- end
115
- expect(Test::Users.register_as).to eq(:guests)
116
- end
117
- end
118
-
119
151
  describe "#to_a" do
120
152
  it "materializes relation to an array" do
121
153
  expect(relation.to_a).to eql([jane, joe])
@@ -1,6 +1,46 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ROM::Setup do
4
+ it 'is configurable' do
5
+ setup = ROM::Setup.new({})
6
+
7
+ setup.configure do |config|
8
+ config.sql.infer_relations = false
9
+ end
10
+
11
+ expect(setup.config.sql.infer_relations).to be(false)
12
+ expect(setup.config[:sql][:infer_relations]).to be(false)
13
+
14
+ expect(setup.config).to respond_to(:sql)
15
+ expect(setup.config).to respond_to(:other=)
16
+
17
+ setup.config.freeze
18
+
19
+ expect(setup.config.other).to be(nil)
20
+ expect(setup.config.key?(:other)).to be(false)
21
+ expect(setup.config.key?(:sql)).to be(true)
22
+ end
23
+
24
+ it 'is configurable via settings hash' do
25
+ setup = ROM.setup(:memory, 'something', infer_schema: false)
26
+
27
+ setup.finalize
28
+
29
+ expect(setup.config.gateways.default.infer_schema).to be(false)
30
+
31
+ setup = ROM.setup(:memory, infer_schema: false)
32
+
33
+ setup.finalize
34
+
35
+ expect(setup.config.gateways.default.infer_schema).to be(false)
36
+
37
+ setup = ROM.setup(default: [:memory, infer_schema: false])
38
+
39
+ setup.finalize
40
+
41
+ expect(setup.config.gateways.default.infer_schema).to be(false)
42
+ end
43
+
4
44
  describe '#finalize' do
5
45
  context 'with gateway that supports schema inferring' do
6
46
  it 'builds relation from inferred schema' do
@@ -33,6 +73,62 @@ describe ROM::Setup do
33
73
  expect(rom.relations.test_users).to be_instance_of(Test::Users)
34
74
  end
35
75
 
76
+ it 'skips inferring when it is turned off for the adapter' do
77
+ setup = ROM.setup(:memory)
78
+
79
+ setup.configure { |config| config.gateways.default.infer_relations = false }
80
+
81
+ repo = setup.default
82
+
83
+ expect(repo).not_to receive(:schema)
84
+
85
+ setup.finalize
86
+ end
87
+
88
+ it 'infers configured relations' do
89
+ setup = ROM.setup(:memory)
90
+
91
+ setup.configure do |config|
92
+ config.gateways.default.inferrable_relations = [:test_tasks]
93
+ end
94
+
95
+ repo = setup.default
96
+ dataset = double('dataset')
97
+
98
+ allow(repo).to receive(:schema).and_return([:test_tasks, :test_users])
99
+
100
+ expect(repo).to receive(:dataset).with(:test_tasks).and_return(dataset)
101
+ expect(repo).to_not receive(:dataset).with(:test_users)
102
+
103
+ rom = setup.finalize
104
+
105
+ expect(rom.relations.elements.key?(:test_users)).to be(false)
106
+ expect(rom.relations[:test_tasks]).to be_kind_of(ROM::Memory::Relation)
107
+ expect(rom.relations[:test_tasks].dataset).to be(dataset)
108
+ end
109
+
110
+ it 'skip inferring blacklisted relations' do
111
+ setup = ROM.setup(:memory)
112
+
113
+ setup.configure do |config|
114
+ config.gateways.default.not_inferrable_relations = [:test_users]
115
+ end
116
+
117
+ repo = setup.default
118
+ dataset = double('dataset')
119
+
120
+ allow(repo).to receive(:schema).and_return([:test_tasks, :test_users])
121
+
122
+ expect(repo).to receive(:dataset).with(:test_tasks).and_return(dataset)
123
+ expect(repo).to_not receive(:dataset).with(:test_users)
124
+
125
+ rom = setup.finalize
126
+
127
+ expect(rom.relations.elements.key?(:test_users)).to be(false)
128
+ expect(rom.relations[:test_tasks]).to be_kind_of(ROM::Memory::Relation)
129
+ expect(rom.relations[:test_tasks].dataset).to be(dataset)
130
+ end
131
+
36
132
  it 'can register multiple relations with same dataset' do
37
133
  setup = ROM.setup(:memory)
38
134
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0.beta1
4
+ version: 0.9.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-10 00:00:00.000000000 Z
11
+ date: 2015-08-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: transproc
@@ -147,6 +147,7 @@ files:
147
147
  - lib/rom/commands/delete.rb
148
148
  - lib/rom/commands/graph.rb
149
149
  - lib/rom/commands/graph/class_interface.rb
150
+ - lib/rom/commands/graph/input_evaluator.rb
150
151
  - lib/rom/commands/lazy.rb
151
152
  - lib/rom/commands/result.rb
152
153
  - lib/rom/commands/update.rb
@@ -192,6 +193,7 @@ files:
192
193
  - lib/rom/setup_dsl/mapper_dsl.rb
193
194
  - lib/rom/setup_dsl/relation.rb
194
195
  - lib/rom/setup_dsl/setup.rb
196
+ - lib/rom/support/configurable.rb
195
197
  - lib/rom/version.rb
196
198
  - rakelib/benchmark.rake
197
199
  - rakelib/mutant.rake
@@ -223,6 +225,7 @@ files:
223
225
  - spec/integration/mappers/unwrap_spec.rb
224
226
  - spec/integration/mappers/wrap_spec.rb
225
227
  - spec/integration/multi_repo_spec.rb
228
+ - spec/integration/relations/inheritance_spec.rb
226
229
  - spec/integration/relations/reading_spec.rb
227
230
  - spec/integration/relations/registry_dsl_spec.rb
228
231
  - spec/integration/repositories/extending_relations_spec.rb