bootinq 0.2.0 → 1.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a2e3311d9fe2f906d1d620e0bff5fa4271d6aaf0
4
- data.tar.gz: fa4bc277f3707743b340b53988252f425a6648c0
2
+ SHA256:
3
+ metadata.gz: f503e7ad103931ee10ce325a3590e3b7742f128a6947a37f59a1566ec57ceaed
4
+ data.tar.gz: 750b19a788035d9325cff83342cc67e2aac08b9ef4e892637eee07121a73b7b4
5
5
  SHA512:
6
- metadata.gz: d047b517e113b611dbfc62ad58f8f4ac86aa96cd30a4ae7ac9d11a5ac1564911e35307e5d651f01f5401224b8a31e4ae48ef1e38a152f9b8144edc0a99e5414f
7
- data.tar.gz: 4b09c5cff33cfc68c72dffeeea388673e4ab873283a34db963c9e73cbe6b818d3d1c3572253e6a040d00c44c964a38d7595b2a24e12b3a3bce7ba015b9369ebf
6
+ metadata.gz: f2878d2f0977783d2d586baa923bbc80945a2495120b522a5c198fd0c493c21f9b7ab4f591799b4f041130cfb62e3747f9287683d23db0bbccf92a64716fac49
7
+ data.tar.gz: 15eac28f64c7777dcafefb756d4a6e3644d22561c673bada3e5d6ff7187283d7596a8c62aae2e1933cab49e1f44531570a99c32e37b1db5a69e4fda4cf66eb34
data/.gitignore CHANGED
@@ -13,4 +13,5 @@
13
13
  /spec/dummy/log/*.log
14
14
  /spec/dummy/tmp/
15
15
  /spec/dummy/.sass-cache
16
- .rake_t_cache
16
+ .rake_t_cache
17
+ .ruby-version
data/Gemfile CHANGED
@@ -10,7 +10,7 @@ gemspec
10
10
  # Git. Remember to move these dependencies to your gemspec before releasing
11
11
  # your gem to rubygems.org.
12
12
 
13
- gem 'rails', '~> 4.2'
13
+ gem 'rails', '>= 5.0'
14
14
  gem 'sqlite3'
15
15
 
16
16
  # To use a debugger
@@ -18,6 +18,7 @@ gem 'byebug', group: [:development, :test]
18
18
 
19
19
  group :development, :test do
20
20
  # You need these
21
+ gem "rspec"
21
22
  gem "rspec-rails"
22
23
  gem "pry"
23
24
  end
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Anton
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -14,27 +14,122 @@ And then execute:
14
14
 
15
15
  $ bundle
16
16
 
17
- Insert `require "bootinq"` to the top of `config/application.rb` file.
18
17
 
19
- Find a `Bundler.require(*Rails.groups)` line below and replace it with the `Bootinq.require`.
18
+ ## Usage
19
+
20
+ There are few steps to setup partial gem booting in a Rails application using Bootinq:
21
+
22
+ ### 1. Declare loadable parts
23
+
24
+ The environment variable specifies which parts should be loaded using the assigned char keys. If the value is starts with `-`, all parts except the given will be loaded.
25
+
26
+ For example, looking at the configuration below, if we want to load only `api`, we should set `BOOTINQ=a`. If we want to load the all except `frontend` and `admin`, we should set `BOOTINQ=-fz`.
20
27
 
21
- ## Example `config/bootinq.yml`:
28
+ The name of the environment variable can be customized by changing the `env_key:`
22
29
 
23
30
  ```yaml
31
+ # config/bootinq.yml
24
32
  env_key: BOOTINQ
25
33
  default: "-f"
26
34
 
35
+ # Non-mountable parts
27
36
  parts:
28
- s: :shared
37
+ c: :console
29
38
 
39
+ # Mountable parts (engines)
30
40
  mount:
31
41
  a: :api
32
- f: :engine
42
+ f: :frontend
43
+ z: :admin
33
44
  ```
34
45
 
35
- ## Usage
46
+ ### 2. Add gem groups
47
+
48
+ For each app part you should add a gem group named as `#{group_name}_boot`:
49
+
50
+ ```ruby
51
+ # Gemfile
52
+
53
+ gem "api", path: "apps/api", group: :api_boot
54
+ gem "admin", path: "apps/admin", group: :admin_boot
55
+ gem "frontend", path: "apps/frontend", group: :frontend_boot
56
+
57
+ group :console_boot do
58
+ gem 'term-ansicolor', '1.1.5'
59
+ gem 'pry-rails'
60
+ end
61
+ ```
62
+
63
+ ### 3. Change config/application.rb
64
+
65
+ Insert `require "bootinq"` to the top of `config/application.rb` file and replace `Bundler.require(*Rails.groups)` with the `Bootinq.require`:
66
+
67
+ #### Simple
68
+
69
+ ```ruby
70
+ # config/application.rb
71
+
72
+ require File.expand_path('../boot', __FILE__)
73
+ require 'rails/all'
74
+ require 'bootinq'
36
75
 
37
- Using example `bootinq.yml` above, you can create `api_boot` group in your `Gemfile` and load gems from that only when flag `BOOTINQ=a` is set. The group can contain local `api` gem, which provides a mountable engine. Please, see `specs/dummy` for the example.
76
+ # With no additional gem groups:
77
+ Bootinq.require
78
+ # otherwise, set them like in <tt>Bundle.require(*Rails.groups(*groups))</tt>:
79
+ # Bootinq.require(:assets => %w(development test))
80
+
81
+ puts "* Bootinq: loading components #{Bootinq.components * ', '}"
82
+ ```
83
+
84
+ #### Separate load rails components with Bootinq
85
+
86
+ ```ruby
87
+ # config/application.rb
88
+ require File.expand_path('../boot', __FILE__)
89
+
90
+ require "rails"
91
+ # Pick the frameworks you want:
92
+ require "active_model/railtie"
93
+ require "active_record/railtie"
94
+ require "active_job/railtie"
95
+ require "action_mailer/railtie"
96
+ require "rails/test_unit/railtie"
97
+
98
+ Bootinq.require do
99
+ # Load the following components only when the frontend component is enabled
100
+ on :frontend do
101
+ require "sprockets/railtie"
102
+ require "action_controller/railtie"
103
+ require "action_view/railtie"
104
+ end
105
+ end
106
+ ```
107
+
108
+ ### 4. Mount enabled engines in config/routes.rb
109
+
110
+ Use the `Bootinq.each_mountable {}` helper to easily mount currently loaded engines or do it by yourself checking `Bootinq.enabled?(engine_name)` :
111
+
112
+ ```ruby
113
+ # config/routes.rb
114
+ Rails.application.routes.draw do
115
+ Bootinq.each_mountable do |part|
116
+ mount part.engine => '/', as: part.to_sym
117
+ end
118
+
119
+ root 'frontend/pages#index' if Bootinq.enabled?(:frontend)
120
+ end
121
+ ```
122
+
123
+ ### 5. Run app with only wanted parts
124
+
125
+ Now, you can set environment variable to tell workers which part of app it should load.
126
+
127
+ For example, with the [foreman](https://github.com/ddollar/foreman) in `Procfile`:
128
+
129
+ ```
130
+ api: env BOOTINQ=a MAX_THREADS=128 bundle exec puma -w 4
131
+ admin: env BOOTINQ=z bundle exec puma
132
+ ```
38
133
 
39
134
  ## Development
40
135
 
@@ -45,4 +140,3 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
45
140
  ## Contributing
46
141
 
47
142
  Bug reports and pull requests are welcome on GitHub at https://github.com/estum/bootinq.
48
-
@@ -12,13 +12,13 @@ Gem::Specification.new do |spec|
12
12
  spec.summary = %q{Rails Boot Inquirer}
13
13
  spec.description = %q{Allows to select which bundle groups to boot in the current rails process}
14
14
  spec.homepage = "https://github.com/estum/bootinq"
15
+ spec.license = "MIT"
15
16
 
16
17
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
18
  spec.bindir = "exe"
18
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
20
  spec.require_paths = ["lib"]
20
21
 
21
- spec.add_development_dependency "bundler", "~> 1.10"
22
- spec.add_development_dependency "rake", "~> 10.0"
23
- spec.add_development_dependency "rspec"
22
+ spec.add_development_dependency "bundler"
23
+ spec.add_development_dependency "rake"
24
24
  end
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "yaml"
2
- require "erb"
3
4
  require "singleton"
4
5
  require "forwardable"
5
6
  require "bootinq/component"
@@ -25,78 +26,180 @@ require "bootinq/component"
25
26
  # a: :api
26
27
  # f: :engine
27
28
  class Bootinq
28
- NEG = '-'.freeze
29
+ extend SingleForwardable
30
+ include Singleton
31
+
29
32
  DEFAULT = {
30
33
  "env_key" => 'BOOTINQ',
31
34
  "default" => '',
32
35
  "parts" => {},
33
36
  "mount" => {}
34
- }
37
+ }.freeze
35
38
 
36
- attr_reader :flags, :components
39
+ # The helper method to bootstrap the Bootinq.
40
+ # Sets the BOOTINQ_PATH enviroment variable, invokes <tt>Bootinq.setup</tt> method
41
+ # with given verbose argument & block, and, finally, gets Bundler to require the given groups.
42
+ def self.require(*groups, verbose: false, &block) # :yields: Bootinq.instance
43
+ ENV['BOOTINQ_PATH'] ||= File.expand_path('../bootinq.yml', caller_locations(1..1)[0].path)
37
44
 
38
- include Singleton
39
- extend SingleForwardable
45
+ setup(verbose: verbose, &block)
40
46
 
41
- def initialize
42
- config = YAML.load(File.read(ENV['BOOTINQ_PATH']))
43
- config.reject! { |_, v| v.nil? }
44
- config.reverse_merge!(DEFAULT)
47
+ Bundler.require(*instance.groups(*groups))
48
+ end
45
49
 
46
- config['parts'].merge!(config['mount'])
50
+ # :call-seq:
51
+ # Bootinq.setup(verbose: true, &block) -> true or false
52
+ #
53
+ # Initializes itself. When verbose: true
54
+ # Yields optional block in the own instance's binding and,
55
+ def self.setup(verbose: false, &block) # :yields: Bootinq.instance
56
+ instance
57
+ puts "Bootinq: loading components #{instance.components.join(', ')}" if verbose
58
+ instance.instance_exec(&block) if block_given?
59
+ instance
60
+ end
47
61
 
48
- value = ENV[config['env_key']] || config['default'].to_s
49
- neg = value.start_with?(NEG)
62
+ attr_reader :flags, :components
50
63
 
51
- flags = []
52
- parts = []
64
+ def initialize # :no-doc:
65
+ config_path = ENV.fetch('BOOTINQ_PATH')
66
+ config = YAML.safe_load(File.read(config_path), [Symbol])
67
+ config.merge!(DEFAULT) { |_, l, r| l.nil? ? r : l }
53
68
 
54
- config['parts'].each do |flag, name|
55
- if neg ^ value[flag]
56
- flags << flag
57
- parts << Component.new(name, mountable: config['mount'].key?(flag))
58
- end
59
- end
69
+ @_value = ENV.fetch(config['env_key']) { config['default'] }
70
+ @_neg = @_value.start_with?(?-, ?^)
71
+ @flags = []
72
+ @components = []
60
73
 
61
- @_value = value.freeze
62
- @_neg = neg.freeze
63
- @flags = flags.freeze
64
- @components = parts.freeze
74
+ config['parts'].each { |flag, name| enable_component(name, flag: flag) }
75
+ config['mount'].each { |flag, name| enable_component(name, flag: flag, as: Mountable) }
65
76
  end
66
77
 
67
- # Checks if a given gem (i.e. a gem group) is enabled
68
- def enabled?(gem_name)
69
- components.include?(gem_name)
78
+ # :call-seq:
79
+ # Bootinq.enable_component(name, flag: [, as: Component])
80
+ #
81
+ def enable_component(name, flag:, as: Component)
82
+ if @_neg ^ @_value.include?(flag)
83
+ @flags << flag
84
+ @components << as.new(name)
85
+ end
70
86
  end
71
87
 
88
+ # :call-seq:
89
+ # Bootinq.enabled?(name) -> true or false
90
+ #
91
+ # Checks if a component with the given name (i.e. the same gem group)
92
+ # is enabled
93
+ def enabled?(name)
94
+ components.include?(name)
95
+ end
96
+
97
+ # :call-seq:
98
+ # Bootinq.component(name) -> Bootinq::Component
99
+ # Bootinq[name] -> Bootinq::Component
100
+ #
72
101
  # Returns a <tt>Bootinq::Component</tt> object by its name
73
- def component(key)
74
- components[components.index(key)]
102
+ def component(name)
103
+ components[components.index(name)]
75
104
  end
76
105
 
77
- # Enums each mountable component
78
- def each_mountable
79
- return to_enum(__method__) unless block_given?
80
- components.each { |c| yield(c) if c.mountable? }
106
+ alias :[] :component
107
+
108
+
109
+ # :call-seq:
110
+ # Bootinq.each_mountable { |part| block } -> Array
111
+ # Bootinq.each_mountable -> Enumerator
112
+ #
113
+ # Calls the given block once for each enabled mountable component
114
+ # passing that part as a parameter. Returns the array of all mountable components.
115
+ #
116
+ # If no block is given, an Enumerator is returned.
117
+ def each_mountable(&block) # :yields: part
118
+ components.select(&:mountable?).each(&block)
81
119
  end
82
120
 
121
+ # :call-seq:
122
+ # Bootinq.groups(*groups)
123
+ #
83
124
  # Invokes <tt>Rails.groups</tt> method within enabled Bootinq's groups
84
125
  def groups(*groups)
85
126
  Rails.groups(*components.map(&:group), *groups)
86
127
  end
87
128
 
88
- def_delegators "instance", *instance_methods(false)
89
-
90
- class << self
91
- # The helper method to bootstrap the Bootinq. Sets the BOOTINQ_PATH enviroment variable
92
- # and requires selected bundler groups.
93
- def require(*groups)
94
- ENV['BOOTINQ_PATH'] ||= File.expand_path('../bootinq.yml', caller_locations(1..1)[0].path)
95
- Bundler.require(*instance.groups(*groups))
129
+ # :call-seq:
130
+ # Bootinq.on(name) { block } -> true or false
131
+ # Bootinq.on(any: [names]) { block } -> true or false
132
+ # Bootinq.on(all: [names]) { block } -> true or false
133
+ #
134
+ # Takes a component's name or single-key options hash as an argument and
135
+ # yields a given block if the target components are enabled.
136
+ #
137
+ # See examples for a usage.
138
+ #
139
+ # ==== Example:
140
+ #
141
+ # Bootinq.on :frontend do
142
+ # # make frontend thing...
143
+ # end
144
+ #
145
+ # Bootinq.on any: %i(frontend backend) do
146
+ # # do something when frontend or backend is enabled
147
+ # end
148
+ #
149
+ # Bootinq.on all: %i(frontend backend) do
150
+ # # do something when frontend and backend are enabled
151
+ # end
152
+ def on(name = nil, any: nil, all: nil) # :yields:
153
+ if name.nil? && any.nil? && all.nil?
154
+ raise ArgumentError, "wrong arguments (given 0, expected 1)"
155
+ elsif (any && all) || (name && (any || all))
156
+ raise ArgumentError, "expected single argument or one of keywords: `all' or `any'"
96
157
  end
97
158
 
98
- private def new
99
- super.freeze
100
- end
159
+ is_matched =
160
+ name ? enabled?(name) :
161
+ any ? on_any(*any) :
162
+ all ? on_all(*all) : false
163
+ yield if is_matched
164
+ is_matched
165
+ end
166
+
167
+ # :call-seq:
168
+ # Bootinq.on_all(*names) { block } -> true or false
169
+ #
170
+ # Takes a list of component names and yields a given block (optionally)
171
+ # if all of them are enabled. Returns boolean matching status.
172
+ def on_all(*parts) # :yields:
173
+ is_matched = parts.all? { |p| enabled?(p) }
174
+ yield if is_matched && block_given?
175
+ is_matched
176
+ end
177
+
178
+ # :call-seq:
179
+ # Bootinq.on_all(*names) { block } -> true or false
180
+ #
181
+ # Takes a list of component names and yields a given block (optionally)
182
+ # if any of them are enabled. Returns boolean matching status.
183
+ def on_any(*parts) # :yields:
184
+ is_matched = parts.any? { |p| enabled?(p) }
185
+ yield if is_matched && block_given?
186
+ is_matched
101
187
  end
188
+
189
+ # Freezes every instance variables and the instance itself.
190
+ def freeze
191
+ @_value.freeze
192
+ @_neg.freeze
193
+ @flags.freeze
194
+ @components.freeze
195
+ super
196
+ end
197
+
198
+ def_delegators "instance", *instance_methods(false)
199
+
200
+ def self.new # :no-doc:
201
+ super.freeze
202
+ end
203
+
204
+ private_class_method :new
102
205
  end
@@ -1,20 +1,62 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Bootinq
2
- class Component < DelegateClass(Symbol)
3
- attr_reader :gem_name, :mountable, :namespace, :group
4
- alias :to_s :gem_name
5
- alias :mountable? :mountable
6
-
7
- def initialize(name, mountable: false)
8
- super(name)
9
- @gem_name = name.to_s.freeze
10
- @mountable = !!mountable
11
- @group = :"#{gem_name}_boot"
12
- @namespace = :"#{gem_name.camelcase}" if mountable?
4
+ class Component
5
+ attr_reader :intern, :id2name, :group
6
+
7
+ alias :to_sym :intern
8
+ alias :to_s :id2name
9
+ alias :gem_name :id2name
10
+ alias :name :id2name
11
+
12
+ def initialize(intern)
13
+ @intern = intern.to_sym
14
+ @id2name = intern.to_s.freeze
15
+ @group = :"#@id2name\_boot"
13
16
  freeze
14
17
  end
15
18
 
19
+ def mountable?
20
+ false
21
+ end
22
+
23
+ def == other
24
+ case other
25
+ when String then other == @id2name
26
+ when Symbol then other == @intern
27
+ else super
28
+ end
29
+ end
30
+
31
+ def inspect
32
+ @intern.inspect
33
+ end
34
+
35
+ def engine
36
+ end
37
+
38
+ def module_name
39
+ @id2name.camelcase.to_sym
40
+ end
41
+
42
+ def respond_to_missing?(method_name, include_all=false)
43
+ @intern.respond_to?(method_name, include_all)
44
+ end
45
+
46
+ private
47
+
48
+ def method_missing(method_name, *args, &blk)
49
+ @intern.respond_to?(method_name) ? @intern.public_send(method_name, *args, &blk) : super
50
+ end
51
+ end
52
+
53
+ class Mountable < Component
54
+ def mountable?
55
+ true
56
+ end
57
+
16
58
  def engine
17
- Object.const_get(@namespace)::Engine
59
+ Object.const_get(module_name)::Engine
18
60
  end
19
61
  end
20
62
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Bootinq
2
- VERSION = "0.2.0"
4
+ VERSION = "1.1.0"
3
5
  end
metadata CHANGED
@@ -1,45 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bootinq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anton
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-08-01 00:00:00.000000000 Z
11
+ date: 2020-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.10'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.10'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '10.0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '10.0'
41
- - !ruby/object:Gem::Dependency
42
- name: rspec
43
29
  requirement: !ruby/object:Gem::Requirement
44
30
  requirements:
45
31
  - - ">="
@@ -63,6 +49,7 @@ files:
63
49
  - ".rspec"
64
50
  - ".travis.yml"
65
51
  - Gemfile
52
+ - LICENSE.txt
66
53
  - README.md
67
54
  - Rakefile
68
55
  - bin/console
@@ -72,9 +59,9 @@ files:
72
59
  - lib/bootinq.yml
73
60
  - lib/bootinq/component.rb
74
61
  - lib/bootinq/version.rb
75
- - lib/tasks/bootinq_tasks.rake
76
62
  homepage: https://github.com/estum/bootinq
77
- licenses: []
63
+ licenses:
64
+ - MIT
78
65
  metadata: {}
79
66
  post_install_message:
80
67
  rdoc_options: []
@@ -92,9 +79,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
79
  version: '0'
93
80
  requirements: []
94
81
  rubyforge_project:
95
- rubygems_version: 2.4.8
82
+ rubygems_version: 2.7.6
96
83
  signing_key:
97
84
  specification_version: 4
98
85
  summary: Rails Boot Inquirer
99
86
  test_files: []
100
- has_rdoc:
@@ -1,4 +0,0 @@
1
- # desc "Explaining what the task does"
2
- # task :bootinq do
3
- # # Task goes here
4
- # end