bootinq 1.3.1 → 1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +8 -0
  3. data/lib/bootinq.rb +111 -47
  4. data/lib/bootinq/version.rb +1 -1
  5. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2132126092e2938ead320330a8866a61e496e47683b1a88c7ec3f8b15d3f1f2b
4
- data.tar.gz: 3eee6dabbc507a0d8234d2edc64461eddca66259b3df04c76799cbfffbbb94f8
3
+ metadata.gz: 33cdc97b02b2407bf6cf031dbac9e0fdae903d6a97a60e266b058729d6a43895
4
+ data.tar.gz: 1cba1d8a6a48ff92ba80dbcad36623a7389f95f512b8d844debc5c7c22644e6b
5
5
  SHA512:
6
- metadata.gz: e2b45226f655ee94a841ec79f70934af6948427ba97e4a1269a4371693b9c3d50bbd9857db2b2b7a914532cc04a571176c41dbeb7f44bbd5979b4464562e5dbe
7
- data.tar.gz: cd87ee76d07175f774202a45c20875d5e1c9a18ab2e0f469e75b2d4a9039520fda537ba29d12f05f67e5e1704b8797a4296ba5c277e56da14a1982731ff7678f
6
+ metadata.gz: 7a4b636bbdea12800a0b367bd5e4294c9681738200597100725595bd3ce3f4f6a5d4b95c14594249cba8755fa11206ba6a01fc516923e1e72493a34efbb79b1d
7
+ data.tar.gz: b6c5e5d242ffff08ac9f00a680dd760979879769e9a752193e039453f31d86684ce97f9d7e19167e36de4ede4003ae9e7a1e42647288082e36bee6badd58095e
data/Gemfile CHANGED
@@ -32,6 +32,14 @@ group :shared_boot do
32
32
  gem 'shared', path: 'spec/dummy/engines/shared'
33
33
  end
34
34
 
35
+ group :api_part_boot do
36
+ gem 'api_part', path: 'spec/dummy/engines/api_part'
37
+ end
38
+
35
39
  group :api_boot do
36
40
  gem 'api', path: 'spec/dummy/engines/api'
41
+ end
42
+
43
+ group :api2_boot do
44
+ gem 'api2', path: 'spec/dummy/engines/api2'
37
45
  end
data/lib/bootinq.rb CHANGED
@@ -37,7 +37,7 @@ require "bootinq/switch"
37
37
  # == Example <tt>config/bootinq.yml</tt>:
38
38
  #
39
39
  # env_key: BOOTINQ
40
- # default: "-f"
40
+ # default: a
41
41
  #
42
42
  # parts:
43
43
  # s: :shared
@@ -45,6 +45,11 @@ require "bootinq/switch"
45
45
  # mount:
46
46
  # a: :api
47
47
  # f: :engine
48
+ #
49
+ # deps:
50
+ # shared:
51
+ # in: af
52
+ #
48
53
  class Bootinq
49
54
  include Singleton
50
55
 
@@ -52,70 +57,106 @@ class Bootinq
52
57
  "env_key" => 'BOOTINQ',
53
58
  "default" => '',
54
59
  "parts" => {},
55
- "mount" => {}
60
+ "mount" => {},
61
+ "deps" => {}
56
62
  }.freeze
57
63
 
58
- class << self
59
- protected def delegated(sym) # :no-doc:
60
- location = caller_locations(1, 1).first
61
- file, line = location.path, location.lineno
62
- definiton = %(def self.#{sym}(*args, &block); instance.#{sym}(*args, &block); end)
63
- class_eval definiton, file, line
64
+ FilterNegValue = -> (value, config) do
65
+ if value.start_with?(?-, ?^)
66
+ value = value.tr('\\-', '\\^')
67
+ flags = (config['parts'].keys + config['mount'].keys).join
68
+ [true, flags.delete(flags.delete(value))]
69
+ else
70
+ [false, value.dup]
64
71
  end
65
72
  end
66
73
 
74
+ private_constant :FilterNegValue
75
+
67
76
  # :call-seq:
68
77
  # Bootinq.require(*groups, verbose: false, &block)
69
78
  #
70
- # The helper method to bootstrap the Bootinq.
71
- # Sets the BOOTINQ_PATH enviroment variable if it is missing,
72
- # invokes the <tt>Bootinq.setup</tt> method with the given verbose key argument & block,
73
- # and, finally, gets Bundler to require the given groups.
79
+ # Invokes the <tt>Bootinq.init</tt> method with the given verbose key argument & block,
80
+ # and, finally, makes Bundler to require the given groups.
74
81
  def self.require(*groups, verbose: false, &block) # :yields: Bootinq.instance
75
- ENV['BOOTINQ_PATH'] ||= File.expand_path('../bootinq.yml', caller_locations(1..1)[0].path)
76
-
77
- setup(verbose: verbose, &block)
78
-
82
+ init(verbose: verbose, &block)
79
83
  Bundler.require(*instance.groups(*groups))
80
84
  end
81
85
 
82
86
  # :call-seq:
83
- # Bootinq.setup(verbose: false, &block) -> true or false
87
+ # Bootinq.setup(*groups, verbose: false, &block)
84
88
  #
85
- # Initializes itself. To track inquired components use <tt>verbose: true</tt> key argument.
89
+ # Invokes the <tt>Bootinq.init</tt> method with the given verbose key argument & block,
90
+ # and, finally, makes Bundler to setup the given groups.
91
+ def self.setup(*groups, verbose: false, &block) # :yields: Bootinq.instance
92
+ init(verbose: verbose, &block)
93
+ Bundler.setup(*instance.groups(*groups))
94
+ end
95
+
96
+ # :call-seq:
97
+ # Bootinq.init(verbose: false, &block) -> true or false
98
+ #
99
+ # Initializes itself. Sets the BOOTINQ_PATH enviroment variable if it is missing.
100
+ # To track inquired components use <tt>verbose: true</tt> key argument.
86
101
  # Optionally yields block within the own instance's binding.
87
- def self.setup(verbose: false, &block) # :yields: Bootinq.instance
102
+ def self.init(verbose: false, &block) # :yields: Bootinq.instance
103
+ ENV['BOOTINQ_PATH'] ||= File.expand_path('../bootinq.yml', caller_locations(2, 1)[0].path)
104
+
88
105
  instance
106
+ instance.instance_variable_set(:@_on_ready, block.to_proc) if block_given?
89
107
  puts "Bootinq: loading components #{instance.components.join(', ')}" if verbose
90
- instance.instance_exec(&block) if block_given?
91
- instance
108
+ instance.ready!
109
+ end
110
+
111
+ # Reads config from the given or default path, deserializes it and returns as a hash.
112
+ def self.deserialized_config(path: nil)
113
+ bootinq_yaml = File.read(path || ENV.fetch('BOOTINQ_PATH'))
114
+ YAML.safe_load(bootinq_yaml, [Symbol])
92
115
  end
93
116
 
94
117
  attr_reader :flags
95
118
  attr_reader :components
96
119
 
97
- delegated :flags
98
- delegated :components
99
-
100
120
  def initialize # :no-doc:
101
- config_path = ENV.fetch('BOOTINQ_PATH')
102
- config = YAML.safe_load(File.read(config_path), [Symbol])
121
+ config = self.class.deserialized_config
103
122
  config.merge!(DEFAULT) { |_, l, r| l.nil? ? r : l }
104
123
 
105
- @_value = ENV.fetch(config['env_key']) { config['default'] }
106
- @_neg = @_value.start_with?(?-, ?^)
124
+ @_orig_value = ENV.fetch(config['env_key']) { config['default'] }
125
+ @_neg, @_value = FilterNegValue[@_orig_value, config]
126
+
127
+ @_deps = config['deps']
128
+
107
129
  @flags = []
108
130
  @components = []
109
131
 
110
- config['parts'].each { |flag, name| enable_component(name, flag: flag) }
111
- config['mount'].each { |flag, name| enable_component(name, flag: flag, as: Mountable) }
132
+ config['parts'].each { |flag, name| enable_component(name, flag: flag.to_s) }
133
+ config['mount'].each { |flag, name| enable_component(name, flag: flag.to_s, as: Mountable) }
134
+ end
135
+
136
+ def ready? # :no-doc:
137
+ !!@ready
138
+ end
139
+
140
+ # :call-seq:
141
+ # Bootinq.ready! -> nil or self
142
+ #
143
+ # At the first call marks Bootinq as ready and returns the instance,
144
+ # otherwise returns nil.
145
+ def ready!
146
+ return if ready?
147
+ @ready = true
148
+ if defined?(@_on_ready)
149
+ instance_exec(&@_on_ready)
150
+ remove_instance_variable :@_on_ready
151
+ end
152
+ freeze
112
153
  end
113
154
 
114
155
  # :call-seq:
115
156
  # Bootinq.enable_component(name, flag: [, as: Component])
116
157
  #
117
- delegated def enable_component(name, flag:, as: Component)
118
- if @_neg ^ @_value.include?(flag)
158
+ def enable_component(name, flag:, as: Component)
159
+ if is_dependency?(name) || @_value.include?(flag)
119
160
  @flags << flag
120
161
  @components << as.new(name)
121
162
  end
@@ -126,7 +167,7 @@ class Bootinq
126
167
  #
127
168
  # Checks if a component with the given name (i.e. the same gem group)
128
169
  # is enabled
129
- delegated def enabled?(name)
170
+ def enabled?(name)
130
171
  components.include?(name)
131
172
  end
132
173
 
@@ -135,12 +176,11 @@ class Bootinq
135
176
  # Bootinq[name] -> Bootinq::Component
136
177
  #
137
178
  # Returns a <tt>Bootinq::Component</tt> object by its name
138
- delegated def component(name)
179
+ def component(name)
139
180
  components[components.index(name)]
140
181
  end
141
182
 
142
183
  alias :[] :component
143
- delegated :[]
144
184
 
145
185
  # :call-seq:
146
186
  # Bootinq.each_mountable { |part| block } -> Array
@@ -150,7 +190,7 @@ class Bootinq
150
190
  # passing that part as a parameter. Returns the array of all mountable components.
151
191
  #
152
192
  # If no block is given, an Enumerator is returned.
153
- delegated def each_mountable(&block) # :yields: part
193
+ def each_mountable(&block) # :yields: part
154
194
  components.select(&:mountable?).each(&block)
155
195
  end
156
196
 
@@ -160,7 +200,7 @@ class Bootinq
160
200
  # Merges enabled Bootinq's groups with the given groups and, if loaded with Rails,
161
201
  # passes them to <tt>Rails.groups</tt> method, otherwise just returns the merged list
162
202
  # to use with <tt>Bundler.require</tt>.
163
- delegated def groups(*groups)
203
+ def groups(*groups)
164
204
  groups.unshift(*components.map(&:group))
165
205
  if defined?(Rails)
166
206
  Rails.groups(*groups)
@@ -192,7 +232,7 @@ class Bootinq
192
232
  # Bootinq.on all: %i(frontend backend) do
193
233
  # # do something when frontend and backend are enabled
194
234
  # end
195
- delegated def on(name = nil, any: nil, all: nil) # :yields:
235
+ def on(name = nil, any: nil, all: nil) # :yields:
196
236
  if name.nil? && any.nil? && all.nil?
197
237
  raise ArgumentError, "wrong arguments (given 0, expected 1)"
198
238
  elsif (any && all) || (name && (any || all))
@@ -212,7 +252,7 @@ class Bootinq
212
252
  #
213
253
  # Takes a list of component names and yields a given block (optionally)
214
254
  # if all of them are enabled. Returns boolean matching status.
215
- delegated def on_all(*parts) # :yields:
255
+ def on_all(*parts) # :yields:
216
256
  is_matched = parts.all? { |p| enabled?(p) }
217
257
  yield if is_matched && block_given?
218
258
  is_matched
@@ -223,14 +263,14 @@ class Bootinq
223
263
  #
224
264
  # Takes a list of component names and yields a given block (optionally)
225
265
  # if any of them are enabled. Returns boolean matching status.
226
- delegated def on_any(*parts) # :yields:
266
+ def on_any(*parts) # :yields:
227
267
  is_matched = parts.any? { |p| enabled?(p) }
228
268
  yield if is_matched && block_given?
229
269
  is_matched
230
270
  end
231
271
 
232
272
  # :call-seq:
233
- # Bottinq.switch(*parts) { block } -> nil
273
+ # Bootinq.switch(*parts) { block } -> nil
234
274
  #
235
275
  # Collector method.
236
276
  #
@@ -240,23 +280,47 @@ class Bootinq
240
280
  # part.frontend { … }
241
281
  # part.backend { … }
242
282
  # end
243
- delegated def switch # :yields: Bootinq::Switch.new
283
+ def switch # :yields: Bootinq::Switch.new
244
284
  yield(Switch.new)
245
285
  nil
246
286
  end
247
287
 
288
+ # :call-seq:
289
+ # is_dependency?(part_name) -> true or false
290
+ #
291
+ # Checks if the named component is a dependency of the enabled one.
292
+ def is_dependency?(name)
293
+ @_deps.key?(name) && @_value.count(@_deps[name]['in'].to_s) > 0
294
+ end
295
+
248
296
  # Freezes every instance variables and the instance itself.
249
297
  def freeze
250
298
  @_value.freeze
251
- @_neg.freeze
299
+ @_neg
252
300
  @flags.freeze
253
301
  @components.freeze
254
302
  super
255
303
  end
256
304
 
257
- def self.new
258
- super.freeze
259
- end
305
+ delegate_template = <<~RUBY
306
+ def self.%1$s(*args, &block)
307
+ instance.%1$s(*args, &block)
308
+ end
309
+ RUBY
260
310
 
261
- private_class_method :new
311
+ %I(flags
312
+ components
313
+ ready?
314
+ ready!
315
+ enable_component
316
+ enabled?
317
+ component
318
+ []
319
+ each_mountable
320
+ groups
321
+ on
322
+ on_all
323
+ on_any
324
+ switch
325
+ ).each { |sym| class_eval(delegate_template % sym, *instance_method(sym).source_location) }
262
326
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Bootinq
4
- VERSION = "1.3.1"
4
+ VERSION = "1.6"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bootinq
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: '1.6'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anton
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-06-27 00:00:00.000000000 Z
11
+ date: 2021-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler