rails_live_reload 0.0.2 → 0.1.2

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: 196b1a989e9edbbb5a2e50612eb9aab60f6cb84b8715e1cc5c9d762bc3a3fb88
4
- data.tar.gz: 90ea51cc27fd92551f44093fcf37e86f7cd7f1a7f456ac28ed26b853fabe6244
3
+ metadata.gz: 04c014926a43e8cba8e586fa5aca93a4e002357fffee35d2a553db0ec88f04a0
4
+ data.tar.gz: 7c5b64509ab169603cd32b62adc9390eb2f1d939d2e626e9bca960f325d45876
5
5
  SHA512:
6
- metadata.gz: 2b76a54f034ae6077091db8feb2d8aa1995845c442880fa198c03b9ee2381eccd4a692bf9d3fd3bc073b9c569fb8f93fc64a8315050da80d60346cb09abbab9e
7
- data.tar.gz: 47260a57c05b2d3b895609f6dc162a4f37fc042eeba997109abdc44c5b085efc895cc7d8530c9aced2082e5eecac001ca0e01c31b29f7bb27d086ab11df6e69b
6
+ metadata.gz: 6e365d7ffad4d351c35c84f8839c4b55318c9769c2191c8aab53cd441253d26950cfabeb98f76c8b556e7bb80d9b329f0b6e5d81ce1c4b0841239d106b38a406
7
+ data.tar.gz: ec660e96b97075b0c7663e5d0b3be0e59d3a505805feda8c0e7262c2e9c7889f560f0a308edaecf1dc03aaeb7e3a987e709718196ae7b42d47b98df03074449f
data/README.md CHANGED
@@ -1,18 +1,23 @@
1
1
  # Rails Live Reload
2
2
 
3
- This is the simplest and probably the most robust way to add a support for a live reload to your Rails app.
3
+ [![RailsJazz](https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/my_other.svg?raw=true)](https://www.railsjazz.com)
4
4
 
5
- Just add the gem and thats all - congratulation, now you have a live reload.
5
+ ![RailsLiveReload](docs/rails_live_reload.gif)
6
+
7
+ This is the simplest and probably the most robust way to add live reloading to your Rails app.
8
+
9
+ Just add the gem and thats it, now you have a live reloading. No 3rd party dependencies.
6
10
 
7
11
  Works with:
8
12
 
9
- - views (EBR/HAML/SLIM) (reloading page only if you editing views which were rendered)
13
+ - views (EBR/HAML/SLIM) (the page is reloaded only when changed views which were rendered on the page)
10
14
  - partials
11
15
  - CSS/JS
12
- - helpers, locales (if you configure)
13
- - on a "crash" page, so once you made a fix page it will be reloaded
16
+ - helpers (if configured)
17
+ - YAML locales (if configured)
18
+ - on the "crash" page, so it will be reloaded as soon as you make a fix
14
19
 
15
- Page is reloaded with `window.location.reload()` so it's the most robust way to reload the page because of CSS/JS/etc.
20
+ The page is reloaded fully with `window.location.reload()` to make sure that every chage will be displayed.
16
21
 
17
22
  ## Usage
18
23
 
@@ -35,31 +40,49 @@ $ bundle
35
40
 
36
41
  ## Configuration
37
42
 
38
- Default configuration `config/initializers/rails_live_reload.rb`:
43
+ ### There are two modes:
44
+ 1. `:long_polling` - This is a default mode, it uses [long polling](https://javascript.info/long-polling) techunique, client opens a connection that will hang until either change is detected, or timeout happens, if later, a new connection is oppened
45
+ 2. `:polling` - This mode will use regular polling to detect changes, you can configure custom `polling_interval` (default is 100ms). We recommend using `:long_polling` as it makes much less requests to the server.
46
+
47
+ ### Create initializer `config/initializers/rails_live_reload.rb`:
39
48
 
40
49
 
41
50
  ```ruby
42
- RailsLiveReload.setup do |config|
43
- config.url = "/rails/live/reload"
44
- config.timeout = 100
45
-
46
- # Watched folders & files
47
- config.watch %r{app/views/.+\.(erb|haml|slim)$}
48
- config.watch %r{(app|vendor)/(assets|javascript)/\w+/(.+\.(css|js|html|png|jpg|ts|jsx)).*}, reload: :always
49
-
51
+ RailsLiveReload.configure do |config|
52
+ # config.url = "/rails/live/reload"
53
+ # Available modes are: :long_polling (default) and :polling
54
+ # config.mode = :long_polling
55
+
56
+ # This is used with :long_polling mode
57
+ # config.timeout = 30
58
+ # config.long_polling_sleep_duration = 0.1
59
+
60
+ # This is used with :polling mode
61
+ # config.polling_interval = 100
62
+
63
+ # Default watched folders & files
64
+ # config.watch %r{app/views/.+\.(erb|haml|slim)$}
65
+ # config.watch %r{(app|vendor)/(assets|javascript)/\w+/(.+\.(css|js|html|png|jpg|ts|jsx)).*}, reload: :always
66
+
50
67
  # More examples:
51
68
  # config.watch %r{app/helpers/.+\.rb}, reload: :always
52
69
  # config.watch %r{config/locales/.+\.yml}, reload: :always
53
- end
70
+
71
+ # config.enabled = Rails.env.development?
72
+ end if defined?(RailsLiveReload)
54
73
  ```
55
74
 
56
75
  ## How it works
57
76
 
58
- There are 3 main pieces how it works:
77
+ There are 3 main parts:
59
78
 
60
- 1) listener for file changes using `listen` gem
79
+ 1) listener of file changes (using `listen` gem)
61
80
  2) collector of rendered views (see rails instrumentation)
62
- 3) middleware which is responding to setInterval JS calls
81
+ 3) middleware which is responding to polling JS calls
82
+
83
+ ## Notes
84
+
85
+ The default configuration assumes that you either use asset pipeline, or that your assets compile quickly (on most applications asset compilation takes around 50-200ms), so it watches for changes in `app/assets` and `app/javascript` folders, this will not be a problem for 99% of users, but in case your asset compilation takes couple of seconds, this might not work propperly, in that case we would recommend you to add configuration to watch output folder.
63
86
 
64
87
  ## Contributing
65
88
 
@@ -68,17 +91,19 @@ You are welcome to contribute. See list of `TODO's` below.
68
91
  ## TODO
69
92
 
70
93
  - reload CSS without reloading the whole page?
94
+ - add `:websocket` mode?
71
95
  - smarter reload if there is a change in helper (check methods from rendered views?)
72
96
  - generator for initializer
73
- - check how it works with webpacker/importmaps/etc
74
- - maybe complex rules, e.g. if "user.rb" file is changed - automatically reload all "users" views
97
+ - more complex rules? e.g. if "user.rb" file is changed - reload all pages with rendered "users" views
75
98
  - check with older Rails versions
76
99
  - tests or specs
77
100
  - CI (github actions)
101
+ - improve how JS code is injected into HTML
102
+ - improve work with turbo, turbolinks
78
103
 
79
104
  ## License
80
105
 
81
106
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
82
107
 
83
108
  [<img src="https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/more_gems.png?raw=true"
84
- />](https://www.railsjazz.com/?utm_source=github&utm_medium=bottom&utm_campaign=rails_live_reload)
109
+ />](https://www.railsjazz.com/?utm_source=github&utm_medium=bottom&utm_campaign=rails_live_reload)
@@ -5,22 +5,16 @@ module RailsLiveReload
5
5
  temp = []
6
6
 
7
7
  # all changed files
8
- RailsLiveReload.files.each do |file, fdt|
8
+ RailsLiveReload.watcher.files.each do |file, fdt|
9
9
  temp << file if fdt && fdt > dt
10
10
  end
11
11
 
12
- # ::Rails.logger.info "Changed: #{temp}"
13
-
14
12
  result = []
15
13
 
16
14
  temp.each do |file|
17
- # ::Rails.logger.info "Checking: #{file}"
18
15
  RailsLiveReload.patterns.each do |pattern, rule|
19
- #puts "pattern = #{pattern} & rule = #{rule}"
20
- # 1. CSS, JS, yaml, helper .rb
21
- # 2. checking if rendered file
22
- rule_1 = file.match(pattern) && rule == :always
23
- rule_2 = file.match(pattern) && rendered_files.include?(file)
16
+ rule_1 = file.match(pattern) && rule == :always # Used for CSS, JS, yaml, helpers, etc.
17
+ rule_2 = file.match(pattern) && rendered_files.include?(file) # Used to check if view was rendered
24
18
 
25
19
  if rule_1 || rule_2
26
20
  result << file
@@ -1,8 +1,49 @@
1
1
  module RailsLiveReload
2
- class Client
2
+ module Client
3
3
 
4
- def Client.js_code
5
- %Q{
4
+ def Client.long_polling_js
5
+ <<~HTML.html_safe
6
+ <script>
7
+ (function() {
8
+ const files = #{CurrentRequest.current.data.to_a.to_json};
9
+ let retries_count = 0;
10
+ function poll() {
11
+ const formData = new FormData();
12
+ formData.append('dt', #{Time.now.to_i})
13
+ formData.append('files', JSON.stringify(files))
14
+
15
+ fetch(
16
+ "#{RailsLiveReload.config.url}",
17
+ {
18
+ method: "post",
19
+ headers: { 'Accept': 'application/json', },
20
+ body: formData
21
+ }
22
+ )
23
+ .then(response => response.json())
24
+ .then(data => {
25
+ retries_count = 0;
26
+ if(data['command'] === 'RELOAD') {
27
+ window.location.reload();
28
+ } else {
29
+ poll();
30
+ }
31
+ }).catch(() => {
32
+ retries_count++;
33
+
34
+ if(retries_count < 10) {
35
+ setTimeout(poll, 5000)
36
+ }
37
+ })
38
+ }
39
+ poll();
40
+ })();
41
+ </script>
42
+ HTML
43
+ end
44
+
45
+ def Client.polling_js
46
+ <<~HTML.html_safe
6
47
  <script>
7
48
  const files = #{CurrentRequest.current.data.to_a.to_json};
8
49
  const timer = setInterval(
@@ -10,9 +51,8 @@ module RailsLiveReload
10
51
  const formData = new FormData();
11
52
  formData.append('dt', #{Time.now.to_i})
12
53
  formData.append('files', JSON.stringify(files))
13
-
14
54
  fetch(
15
- "#{RailsLiveReload.url}",
55
+ "#{RailsLiveReload.config.url}",
16
56
  {
17
57
  method: "post",
18
58
  headers: { 'Accept': 'application/json', },
@@ -26,11 +66,10 @@ module RailsLiveReload
26
66
  window.location.reload();
27
67
  }
28
68
  })
29
- }, #{RailsLiveReload.timeout}
69
+ }, #{RailsLiveReload.config.polling_interval}
30
70
  )
31
71
  </script>
32
- }.html_safe
72
+ HTML
33
73
  end
34
-
35
74
  end
36
- end
75
+ end
@@ -4,16 +4,22 @@ module RailsLiveReload
4
4
 
5
5
  def initialize(params)
6
6
  @dt = params["dt"].to_i
7
- @files = JSON.parse(params["files"])
7
+ @files = JSON.parse(params["files"]) rescue []
8
8
  end
9
9
 
10
- def command
11
- changes = RailsLiveReload::Checker.scan(dt, files)
10
+ def changes
11
+ RailsLiveReload::Checker.scan(dt, files)
12
+ end
12
13
 
13
- if changes.size == 0
14
- { command: "NO_CHANGES" }
15
- else
14
+ def reload?
15
+ !changes.size.zero?
16
+ end
17
+
18
+ def payload
19
+ if reload?
16
20
  { command: "RELOAD" }
21
+ else
22
+ { command: "NO_CHANGES" }
17
23
  end
18
24
  end
19
25
 
@@ -0,0 +1,51 @@
1
+ module RailsLiveReload
2
+ class << self
3
+ def configure
4
+ yield config
5
+ end
6
+
7
+ def config
8
+ @_config ||= Config.new
9
+ end
10
+
11
+ def patterns
12
+ config.patterns
13
+ end
14
+
15
+ def enabled?
16
+ config.enabled
17
+ end
18
+ end
19
+
20
+ class Config
21
+ attr_reader :patterns
22
+ attr_accessor :mode, :polling_interval, :timeout, :url, :watcher, :files, :enabled, :long_polling_sleep_duration
23
+
24
+ def initialize
25
+ @mode = :long_polling
26
+ @timeout = 30
27
+ @long_polling_sleep_duration = 0.1
28
+ @polling_interval = 100
29
+ @url = "/rails/live/reload"
30
+ @watcher = nil
31
+ @files = {}
32
+ @enabled = ::Rails.env.development?
33
+
34
+ # These configs work for 95% apps, see README for more info
35
+ @patterns = {
36
+ %r{app/views/.+\.(erb|haml|slim)$} => :on_change,
37
+ %r{(app|vendor)/(assets|javascript)/\w+/(.+\.(css|js|html|png|jpg|ts|jsx)).*} => :always
38
+ }
39
+ @default_patterns_changed = false
40
+ end
41
+
42
+ def watch(pattern, reload: :on_change)
43
+ unless @default_patterns_changed
44
+ @default_patterns_changed = true
45
+ @patterns = {}
46
+ end
47
+
48
+ patterns[pattern] = reload
49
+ end
50
+ end
51
+ end
@@ -1,26 +1,32 @@
1
1
  module RailsLiveReload
2
2
  class Railtie < ::Rails::Engine
3
3
 
4
- initializer "rails_live_reload.middleware" do |app|
5
- if ::Rails::VERSION::MAJOR.to_i >= 5
6
- app.middleware.insert_after ActionDispatch::Executor, RailsLiveReload::Rails::Middleware
7
- else
8
- begin
9
- app.middleware.insert_after ActionDispatch::Static, RailsLiveReload::Rails::Middleware
10
- rescue
11
- app.middleware.insert_after Rack::SendFile, RailsLiveReload::Rails::Middleware
4
+ if RailsLiveReload.enabled? && defined?(::Rails::Server)
5
+ initializer "rails_live_reload.middleware" do |app|
6
+ if ::Rails::VERSION::MAJOR.to_i >= 5
7
+ app.middleware.insert_after ActionDispatch::Executor, RailsLiveReload.middleware
8
+ else
9
+ begin
10
+ app.middleware.insert_after ActionDispatch::Static, RailsLiveReload.middleware
11
+ rescue
12
+ app.middleware.insert_after Rack::SendFile, RailsLiveReload.middleware
13
+ end
12
14
  end
15
+
16
+ RailsLiveReload::Watcher.init
13
17
  end
14
18
 
15
- RailsLiveReload::Watcher.init
16
- end
19
+ initializer :configure_metrics, after: :initialize_logger do
20
+ ActiveSupport::Notifications.subscribe(
21
+ /\.action_view/,
22
+ RailsLiveReload::Instrument::MetricsCollector.new
23
+ )
24
+ end
17
25
 
18
- initializer :configure_metrics, after: :initialize_logger do
19
- ActiveSupport::Notifications.subscribe(
20
- /\.action_view/,
21
- RailsLiveReload::Instrument::MetricsCollector.new
22
- )
26
+ initializer :reset_current_request, after: :initialize_logger do |app|
27
+ app.executor.to_run { CurrentRequest.cleanup }
28
+ app.executor.to_complete { CurrentRequest.cleanup }
29
+ end
23
30
  end
24
-
25
31
  end
26
32
  end
@@ -7,23 +7,3 @@ module RailsLiveReload
7
7
  end
8
8
  end
9
9
  end
10
-
11
- # render_template.action_view
12
- # {
13
- # identifier: "/Users/adam/projects/notifications/app/views/posts/index.html.erb",
14
- # layout: "layouts/application"
15
- # }
16
- # render_partial.action_view
17
- # {
18
- # identifier: "/Users/adam/projects/notifications/app/views/posts/_form.html.erb"
19
- # }
20
- # render_collection.action_view
21
- # {
22
- # identifier: "/Users/adam/projects/notifications/app/views/posts/_post.html.erb",
23
- # count: 3,
24
- # cache_hits: 0
25
- # }
26
- # render_layout.action_view
27
- # {
28
- # identifier: "/Users/adam/projects/notifications/app/views/layouts/application.html.erb"
29
- # }
@@ -0,0 +1,63 @@
1
+ module RailsLiveReload
2
+ module Rails
3
+ module Middleware
4
+ class Base
5
+ def initialize(app)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ dup.call!(env)
11
+ end
12
+
13
+ def call!(env)
14
+ request = Rack::Request.new(env)
15
+
16
+ if env["REQUEST_PATH"] == RailsLiveReload.config.url
17
+ rails_live_response(request)
18
+ else
19
+ @status, @headers, @response = @app.call(env)
20
+
21
+ if html? && @response.respond_to?(:[]) && (@status == 500 || (@status.to_s =~ /20./ && request.get?))
22
+ new_response = make_new_response(@response[0])
23
+ @headers['Content-Length'] = new_response.bytesize.to_s
24
+ @response = [new_response]
25
+ end
26
+
27
+ [@status, @headers, @response]
28
+ end
29
+ rescue Exception => ex
30
+ puts ex.message
31
+ puts ex.backtrace.take(10)
32
+ raise ex
33
+ end
34
+
35
+ private
36
+
37
+ def rails_live_response(request)
38
+ raise NotImplementedError
39
+ end
40
+
41
+ def client_javascript(request)
42
+ raise NotImplementedError
43
+ end
44
+
45
+ def make_new_response(body)
46
+ body.sub("</head>", "</head>#{client_javascript}")
47
+ end
48
+
49
+ def html?
50
+ @headers["Content-Type"].to_s.include?("text/html")
51
+ end
52
+
53
+ def new_thread
54
+ Thread.new {
55
+ t2 = Thread.current
56
+ t2.abort_on_exception = true
57
+ yield
58
+ }
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,51 @@
1
+ module RailsLiveReload
2
+ module Rails
3
+ module Middleware
4
+ class LongPolling < Base
5
+ private
6
+
7
+ def rails_live_response(request)
8
+ params = request.params
9
+ body = lambda do |stream|
10
+ new_thread do
11
+ counter = 0
12
+
13
+ loop do
14
+ command = RailsLiveReload::Command.new(params)
15
+
16
+ if command.reload?
17
+ stream.write(command.payload.to_json) and break
18
+ end
19
+
20
+ sleep(RailsLiveReload.config.long_polling_sleep_duration)
21
+ counter += 1
22
+
23
+ stream.write(command.payload.to_json) and break if counter >= max_sleeps_count
24
+ end
25
+ ensure
26
+ stream.close
27
+ end
28
+ end
29
+
30
+ [ 200, { 'Content-Type' => 'application/json', 'rack.hijack' => body }, nil ]
31
+ end
32
+
33
+ def client_javascript
34
+ RailsLiveReload::Client.long_polling_js
35
+ end
36
+
37
+ def max_sleeps_count
38
+ RailsLiveReload.config.timeout * (1 / RailsLiveReload.config.long_polling_sleep_duration)
39
+ end
40
+
41
+ def new_thread
42
+ Thread.new {
43
+ t2 = Thread.current
44
+ t2.abort_on_exception = true
45
+ yield
46
+ }
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,21 @@
1
+ module RailsLiveReload
2
+ module Rails
3
+ module Middleware
4
+ class Polling < Base
5
+ private
6
+
7
+ def rails_live_response(request)
8
+ [
9
+ 200,
10
+ { 'Content-Type' => 'application/json' },
11
+ [ RailsLiveReload::Command.new(request.params).payload.to_json ]
12
+ ]
13
+ end
14
+
15
+ def client_javascript
16
+ RailsLiveReload::Client.polling_js
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,3 +1,3 @@
1
1
  module RailsLiveReload
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -1,6 +1,6 @@
1
1
  module RailsLiveReload
2
2
  class Watcher
3
- attr_reader :root
3
+ attr_reader :root, :files
4
4
 
5
5
  def Watcher.init
6
6
  watcher = new
@@ -9,12 +9,15 @@ module RailsLiveReload
9
9
 
10
10
  def initialize
11
11
  @root = ::Rails.application.root
12
+ @files = {}
13
+
12
14
  puts "Watching: #{root}"
13
15
  RailsLiveReload.patterns.each do |pattern, rule|
14
16
  puts " #{pattern} => #{rule}"
15
17
  end
16
- self.build_tree
17
- self.start_listener
18
+
19
+ build_tree
20
+ start_listener
18
21
  end
19
22
 
20
23
  def start_listener
@@ -22,7 +25,7 @@ module RailsLiveReload
22
25
  listener = Listen.to(root) do |modified, added, removed|
23
26
  all = modified + added + removed
24
27
  all.each do |file|
25
- RailsLiveReload.files[file] = File.mtime(file).to_i rescue nil
28
+ files[file] = File.mtime(file).to_i rescue nil
26
29
  end
27
30
  end
28
31
  listener.start
@@ -31,8 +34,8 @@ module RailsLiveReload
31
34
 
32
35
  def build_tree
33
36
  Dir.glob(File.join(root, '**', '*')).select{|file| File.file?(file)}.each do |file|
34
- RailsLiveReload.files[file] = File.mtime(file).to_i rescue nil
37
+ files[file] = File.mtime(file).to_i rescue nil
35
38
  end
36
39
  end
37
40
  end
38
- end
41
+ end
@@ -1,8 +1,11 @@
1
1
  require "listen"
2
2
  require "rails_live_reload/version"
3
+ require "rails_live_reload/config"
3
4
  require "rails_live_reload/client"
4
5
  require "rails_live_reload/watcher"
5
- require "rails_live_reload/rails/middleware"
6
+ require "rails_live_reload/rails/middleware/base"
7
+ require "rails_live_reload/rails/middleware/long_polling"
8
+ require "rails_live_reload/rails/middleware/polling"
6
9
  require "rails_live_reload/instrument/metrics_collector"
7
10
  require "rails_live_reload/thread/current_request"
8
11
  require "rails_live_reload/checker"
@@ -10,32 +13,13 @@ require "rails_live_reload/command"
10
13
  require "rails_live_reload/engine"
11
14
 
12
15
  module RailsLiveReload
13
- mattr_accessor :files
14
- @@files = {}
15
-
16
16
  mattr_accessor :watcher
17
- @@watcher = nil
18
-
19
- mattr_accessor :url
20
- @@url = "/rails/live/reload"
21
-
22
- mattr_accessor :patterns
23
- @@patterns = {}
24
-
25
- mattr_accessor :timeout
26
- @@timeout = 100
17
+ @@watcher = {}
27
18
 
28
- def self.setup
29
- yield(self)
30
- end
31
-
32
- def self.watch(pattern, reload: :on_change)
33
- RailsLiveReload.patterns[pattern] = reload
19
+ def self.middleware
20
+ case config.mode
21
+ when :polling then RailsLiveReload::Rails::Middleware::Polling
22
+ when :long_polling then RailsLiveReload::Rails::Middleware::LongPolling
23
+ end
34
24
  end
35
25
  end
36
-
37
- # default watch settings
38
- RailsLiveReload.setup do |config|
39
- config.watch %r{app/views/.+\.(erb|haml|slim)$}
40
- config.watch %r{(app|vendor)/(assets|javascript)/\w+/(.+\.(css|js|html|png|jpg|ts|jsx)).*}, reload: :always
41
- end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_live_reload
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igor Kasyanchuk
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-05-29 00:00:00.000000000 Z
12
+ date: 2022-05-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -125,9 +125,12 @@ files:
125
125
  - lib/rails_live_reload/checker.rb
126
126
  - lib/rails_live_reload/client.rb
127
127
  - lib/rails_live_reload/command.rb
128
+ - lib/rails_live_reload/config.rb
128
129
  - lib/rails_live_reload/engine.rb
129
130
  - lib/rails_live_reload/instrument/metrics_collector.rb
130
- - lib/rails_live_reload/rails/middleware.rb
131
+ - lib/rails_live_reload/rails/middleware/base.rb
132
+ - lib/rails_live_reload/rails/middleware/long_polling.rb
133
+ - lib/rails_live_reload/rails/middleware/polling.rb
131
134
  - lib/rails_live_reload/thread/current_request.rb
132
135
  - lib/rails_live_reload/version.rb
133
136
  - lib/rails_live_reload/watcher.rb
@@ -150,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
153
  - !ruby/object:Gem::Version
151
154
  version: '0'
152
155
  requirements: []
153
- rubygems_version: 3.2.3
156
+ rubygems_version: 3.3.7
154
157
  signing_key:
155
158
  specification_version: 4
156
159
  summary: Ruby on Rails Live Reload
@@ -1,54 +0,0 @@
1
- module RailsLiveReload
2
- module Rails
3
- class Middleware
4
- def initialize(app)
5
- @app = app
6
- end
7
-
8
- def call(env)
9
- dup.call!(env)
10
- end
11
-
12
- def call!(env)
13
- request = Rack::Request.new(env)
14
-
15
- if env["REQUEST_PATH"] == RailsLiveReload.url
16
- rails_live_response(request)
17
- else
18
- @status, @headers, @response = @app.call(env)
19
-
20
- if html? && @response.respond_to?(:[]) && (@status == 500 || (@status.to_s =~ /20./ && request.get?))
21
- new_response = make_new_response(@response[0])
22
- @headers['Content-Length'] = new_response.bytesize.to_s
23
- @response = [new_response]
24
- end
25
-
26
- [@status, @headers, @response]
27
- end
28
- rescue Exception => ex
29
- puts ex.message
30
- puts ex.backtrace.take(10)
31
- raise ex
32
- end
33
-
34
- private
35
-
36
- def rails_live_response(request)
37
- [
38
- 200,
39
- { 'Content-Type' => 'application/json' },
40
- [ RailsLiveReload::Command.new(request.params).command.to_json ]
41
- ]
42
- end
43
-
44
- def make_new_response(body)
45
- body.sub("</head>", "</head>#{RailsLiveReload::Client.js_code}")
46
- end
47
-
48
- def html?
49
- @headers["Content-Type"].include?("text/html")
50
- end
51
-
52
- end
53
- end
54
- end