hot_reloader 0.3.2 → 0.7.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
2
  SHA256:
3
- metadata.gz: 7f7a23dab8a6321213fc337a02d143cb8ed0eb8414a08178d5ab485975935822
4
- data.tar.gz: 94240e3303b304cb0ab08ef8be9c587a0e77944a1b52203d3f2970a553a454af
3
+ metadata.gz: 9421c166738e6fafb613ca2dac2bc28bd99b53a6229d4c0720db14f2e0c0ae25
4
+ data.tar.gz: a5677eaf835907fc683a591bd5e746008aa9fe42f296fa0585372482f2df92fd
5
5
  SHA512:
6
- metadata.gz: 88e7cc2a2ab94b09f50bed1c095c6d446472f09f47f3de402c2b7c515a660251ac5551a4ca14dd7a1713e2096fbcc32f12b23fd306d29af7760c44d3c36d51f0
7
- data.tar.gz: 7c872ea05e0146a656758cd6ee2d4b0a08905c342e34029f3f42a0f32f7838b99377874b117a5c1ac330325cef949f09eca767a29c3852e00a853167741f54ed
6
+ metadata.gz: 14c1d5918b46577369366f01912de5b1b61907195eedf2c182b87022c1d33796a65ec43a90efe21e72d3211b341b29a247c24383f2da499ed5a7a98116dc136b
7
+ data.tar.gz: f6668adecc4df04439245a41d5b7327ec03b0f3e14b8bee313ec529b9275ebc5b57a4667d93c85e1e21118a54b33169d77765bb83eca73e8c24491eeb2091e0a
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # HotReloader [![Build Status](https://travis-ci.org/zw963/hot_reloader.svg?branch=master)](https://travis-ci.org/zw963/hot_reloader) [![Gem Version](https://badge.fury.io/rb/hot_reloader.svg)](http://badge.fury.io/rb/hot_reloader)
1
+ # HotReloader [![Build Status](https://travis-ci.com/zw963/hot_reloader.svg?branch=master)](https://travis-ci.com/zw963/hot_reloader) [![Gem Version](https://badge.fury.io/rb/hot_reloader.svg)](http://badge.fury.io/rb/hot_reloader)
2
2
 
3
3
  A dead simple ruby code hot reloader wrap around [zeitwerk](https://github.com/fxn/zeitwerk) and [listen](https://github.com/guard/listen).
4
4
 
@@ -20,31 +20,136 @@ Add to your Gemfile
20
20
 
21
21
  Following is a example for use hot_reloader with [Roda](https://github.com/jeremyevans/roda):
22
22
 
23
+ `config.ru` which used to start rack based web server with `command rackup -o 0.0.0.0 -p 9393`
24
+
23
25
  ```rb
24
26
  # config.ru
25
27
 
26
- require 'roda'
27
- require 'hot_reloader'
28
+ require_relative './config/environment'
28
29
 
29
- if ENV['RACK_ENV'] == 'production'
30
- HotReloader.eager_load(__dir__, 'another/root/path')
31
- run App
32
- else
33
- HotReloader.will_listen([__dir__, 'another/root/path'])
30
+ if ENV['RACK_ENV'] == 'development'
34
31
  run ->(env) { App.call(env) }
32
+ else
33
+ run App.freeze.app
34
+ end
35
+ ```
36
+
37
+ Add loader initialize code into `config/environment.rb`
38
+
39
+ For simple use case, you just need pass paths to `HotReloader.eager_load` or `HotReloader.will_listen`.
40
+
41
+ ```rb
42
+ # config/environment.rb
43
+
44
+ require 'bundler'
45
+ Bundler.require(:default, ENV.fetch('RACK_ENV', "development"))
46
+ require_relative 'application'
47
+
48
+ paths = ["#{__dir__}/../app", "#{__dir__}/../app/models"]
49
+
50
+ if ENV['RACK_ENV'] == 'development'
51
+ HotReloader.will_listen(*paths)
52
+ else
53
+ HotReloader.eager_load(*paths)
35
54
  end
36
55
  ```
37
56
 
57
+ For more advanced case(e.g. you need setup zeitwerk loader instance yourself), you
58
+ can pass this instance to HotReloader methods too.
59
+
38
60
  ```rb
39
- # app.rb
61
+ # config/environment.rb
62
+
63
+ require 'bundler'
64
+ Bundler.require(:default, ENV.fetch('RACK_ENV', "development"))
65
+ require_relative 'application'
66
+
67
+ loader = Zeitwerk::Loader.new
68
+ loader.push_dir("#{__dir__}/../app")
69
+ loader.push_dir("#{__dir__}/../app/models")
70
+
71
+ if ENV['RACK_ENV'] == 'development'
72
+ HotReloader.will_listen(loader)
73
+ else
74
+ HotReloader.eager_load(loader)
75
+ end
76
+ ```
77
+
78
+ When you change root directories files(app/*.rb or app/models/*.rb for above case),
79
+ all monitored files will be reload.
80
+
81
+ it is possible to trigger reload from any `.rb` files, even this file not follow constant
82
+ lookup name convention, and this file folder not add to root directories use `push_dir` method.
83
+
84
+ Following is a example.
85
+
86
+ ```rb
87
+ # app/app.rb
40
88
 
41
89
  class App < Roda
42
- articles = []
90
+ plugin :hash_routes
91
+
92
+ Dir["routes/**/*.rb"].each do |route_file|
93
+ load route_file
94
+ end
95
+ end
96
+ ```
97
+
98
+ ```rb
99
+ # routes/blog.rb
100
+
101
+ class App
102
+ hash_routes.on "blog" do |r|
103
+ "blog"
104
+ end
105
+ end
106
+ ```
43
107
 
108
+ `routes/blog.rb` is not follow constant lookup name convention, so, `routes/` folder can't be
109
+ add to root directories use push_dir method, but you can always trigger with `loader.reload`
110
+ if `routes/blog.rb` was changed, then when `app/app.rb` reloaded, it will load the
111
+ newest code in `routes/blog.rb` from the Dir each loop.
112
+
113
+ For achieve this, you only need pass listened folders to will_listen method as secondary arg.
114
+
115
+ ```
116
+ loader = Zeitwerk::Loader.new
117
+ loader.push_dir("#{__dir__}/../app")
118
+
119
+ listened_folders = ["#{__dir__}/../routes"]
120
+
121
+ if ENV['RACK_ENV'] == 'development'
122
+ HotReloader.will_listen(loader, listened_folders)
123
+ else
124
+ HotReloader.eager_load(loader)
125
+ end
126
+ ```
127
+
128
+ Write whatever application initialize code which need add into application.rb
129
+
130
+ ```rb
131
+ # config/application.rb
132
+
133
+ DB = Sequel.connect(ENV.fetch("#{ENV.fetch('RACK_ENV', "development").upcase}_DATABASE_URL"), timeout: 10000)
134
+ Sequel::Model.plugin :timestamps
135
+ Sequel.extension :symbol_aref
136
+ ```
137
+
138
+ Add roda code into app/app.rb
139
+
140
+ ```rb
141
+ # app/app.rb
142
+
143
+ class App < Roda
144
+ articles = ['programming ruby', 'programming rust']
44
145
  route do |r|
45
146
  r.post "articles" do
46
- articles << r.params["content"]
47
- "Count: #{articles.count}"
147
+ articles << r.params["content"]
148
+ "Count: #{articles.count}"
149
+ end
150
+
151
+ r.get "articles" do
152
+ articles.join(', ')
48
153
  end
49
154
  end
50
155
  end
@@ -53,13 +158,17 @@ end
53
158
  Directory structure is like this:
54
159
 
55
160
  ```
56
- ├── app.rb
161
+ ├── app/app.rb
162
+ ├── config/environment.rb
163
+ ├── config/application.rb
57
164
  ├── config.ru
58
165
  ├── Gemfile
59
166
  └── Gemfile.lock
60
167
  ```
61
168
 
62
- Change code in app.rb, **all constant get removed from memory, and app.rb evaluated again**!
169
+ After change code in app.rb, **all constant get removed from memory, and app.rb evaluated again**!
170
+
171
+ For a more rich WIP sample project, please check my another project [marketbet_crawler](https://github.com/zw963/marketbet_crawler).
63
172
 
64
173
  ## Support
65
174
 
data/lib/hot_reloader.rb CHANGED
@@ -1,57 +1,74 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'singleton'
4
3
  require 'zeitwerk'
5
4
  require 'listen'
6
5
 
7
6
  class HotReloader
8
- include Singleton
9
-
10
- # @private
11
- def initialize
12
- @loader = Zeitwerk::Loader.new
13
- end
14
-
15
7
  class << self
16
- # Listen folders for file change, and reload changed rb file,
8
+ # Listen on folders for file change, and reload changed rb file if necessary.
17
9
  # Should be used for development mode only.
18
10
  #
19
11
  # @param [*String, Array<String>] folders Folders which should be monitor, can be multi-args or array.
20
- # @param [#call] logger logger or any object should response call.
12
+ # or only one Zeitwerk::Loader object can be provided.
13
+ # @param [#call] logger logger or any object should response call, e.g. method(:puts), $stdout, $stderr.
21
14
  # @param [Array<String>] ignore Glob patterns or Pathname object which should be excluded.
22
15
  # @return nil
23
- def will_listen(*folders, logger: method(:puts), ignore: [])
16
+ def will_listen(*folders, logger: Logger.new(IO::NULL), ignore: [])
24
17
  folders = folders.flatten
25
- setup_loader(folders, logger: logger, ignore: ignore)
26
- Listen.to(*folders, wait_for_delay: 1) { loader.reload }.start
18
+
19
+ if folders.first.is_a? Zeitwerk::Loader
20
+ loader, *listened_folders = folders
21
+ folders = loader.root_dirs.keys
22
+ # `folders' will add to zeitwerk root directories and listened.
23
+ # `reloadable_folder' listened only, it can be reload dynamically.
24
+ # but not constant lookup use name convention.
25
+ else
26
+ loader = Zeitwerk::Loader.new
27
+
28
+ raise 'you must set the root directories from which you want to load watched files.' if folders&.empty?
29
+ raise 'ignore: only accept an array of glob patterns string or Pathname objects.' unless ignore.is_a? Array
30
+
31
+ folders.each {|folder| loader.push_dir(folder) }
32
+ listened_folders = []
33
+ end
34
+
35
+ loader.enable_reloading if loader.respond_to? :enable_reloading
36
+ loader.logger = logger
37
+ loader.ignore(ignore) unless ignore.empty?
38
+ loader.setup
39
+
40
+ Listen.logger = logger
41
+
42
+ Listen.to(*(folders + listened_folders), wait_for_delay: 1, ignore: /\.#.*/) { loader.reload }.start
27
43
  end
28
44
 
29
45
  # Enable autoload ruby file based on default Zeitwerk rule.
30
46
  # More rule see https://github.com/fxn/zeitwerk
31
47
  #
32
48
  # @param [*String, Array<String>] folders folders which should be autoload, can be multi-args or array.
33
- # @param [#call] logger logger or any object should response call.
49
+ # or only one Zeitwerk::Loader object can be provided.
50
+ # @param [#call] logger logger or any object should response call, e.g. method(:puts), $stdout, $stderr.
34
51
  # @return nil
35
- def eager_load(*folders, logger: method(:puts))
52
+ def eager_load(*folders, logger: Logger.new(IO::NULL), ignore: [])
36
53
  folders = folders.flatten
37
- setup_loader(folders, logger: logger, ignore: [])
38
- loader.eager_load
39
- end
40
54
 
41
- private
55
+ if folders.first.is_a? Zeitwerk::Loader
56
+ loader = folders.first
57
+ folders = loader.root_dirs.keys
58
+ else
59
+ loader = Zeitwerk::Loader.new
42
60
 
43
- def loader
44
- instance.instance_variable_get(:@loader)
45
- end
61
+ raise 'you must set the root directories from which you want to load watched files.' if folders&.empty?
62
+ raise 'ignore: only accept an array of glob patterns string or Pathname objects.' unless ignore.is_a? Array
46
63
 
47
- def setup_loader(folders, logger:, ignore:)
48
- raise 'ignore: only accept an array of glob patterns string or Pathname objects.' unless ignore.is_a? Array
49
- raise 'you must set the root folders from which you want to load watched files.' if folders&.empty?
64
+ folders.each {|folder| loader.push_dir(folder) }
65
+ end
50
66
 
51
- folders.each {|folder| loader.push_dir(folder) }
52
67
  loader.logger = logger
53
68
  loader.ignore(ignore) unless ignore.empty?
69
+
54
70
  loader.setup
71
+ loader.eager_load
55
72
  end
56
73
  end
57
74
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class HotReloader
4
- VERSION = '0.3.2'
4
+ VERSION = '0.7.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hot_reloader
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Billy.Zheng(zw963)
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-31 00:00:00.000000000 Z
11
+ date: 2021-07-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: zeitwerk
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.4'
19
+ version: '2.3'
20
20
  type: :runtime
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.4'
26
+ version: '2.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: listen
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -53,7 +53,7 @@ homepage: http://github.com/zw963/hot_reloader
53
53
  licenses:
54
54
  - MIT
55
55
  metadata: {}
56
- post_install_message:
56
+ post_install_message:
57
57
  rdoc_options: []
58
58
  require_paths:
59
59
  - lib
@@ -68,8 +68,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
68
68
  - !ruby/object:Gem::Version
69
69
  version: '0'
70
70
  requirements: []
71
- rubygems_version: 3.0.3
72
- signing_key:
71
+ rubygems_version: 3.2.3
72
+ signing_key:
73
73
  specification_version: 4
74
74
  summary: A dead simple ruby code hot reloader wrap around zeitwerk and listen.
75
75
  test_files: []