bootinq 1.3.1 → 1.6

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 (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