hot_reloader 0.3.2 → 0.7.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
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: []