bootinq 0.2.0 → 1.1.0

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