rails_live_reload 0.0.2 → 0.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
2
  SHA256:
3
- metadata.gz: 196b1a989e9edbbb5a2e50612eb9aab60f6cb84b8715e1cc5c9d762bc3a3fb88
4
- data.tar.gz: 90ea51cc27fd92551f44093fcf37e86f7cd7f1a7f456ac28ed26b853fabe6244
3
+ metadata.gz: 453d155a64c2869fea44301e05aa33cf32274ff501cfdb6a7eb1c061bb5cffa1
4
+ data.tar.gz: b7e734f2649d12365e8e346e2656fd386aea36187d6a295f19f8643460138d6d
5
5
  SHA512:
6
- metadata.gz: 2b76a54f034ae6077091db8feb2d8aa1995845c442880fa198c03b9ee2381eccd4a692bf9d3fd3bc073b9c569fb8f93fc64a8315050da80d60346cb09abbab9e
7
- data.tar.gz: 47260a57c05b2d3b895609f6dc162a4f37fc042eeba997109abdc44c5b085efc895cc7d8530c9aced2082e5eecac001ca0e01c31b29f7bb27d086ab11df6e69b
6
+ metadata.gz: 7519b3b746a4c58eb412e97743a24db2b39ae7e99351bff81edcfe69df682478e0c250f5b9f5a08022fd1c086f571df0bc52cfaa530bf0c1996c1d1240456ea7
7
+ data.tar.gz: 347cae5497f229eb42a38cd9e62f3fc8c33b1c2f03542af5546a156a54f80fff7e5fa4a16e3253e69a44b6e5df9ebe25e5930fd03e19a9d941d2be7a43fb431b
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,43 @@ $ 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 :polling mode
57
+ # config.polling_interval = 100
58
+
59
+ # Default watched folders & files
60
+ # config.watch %r{app/views/.+\.(erb|haml|slim)$}
61
+ # config.watch %r{(app|vendor)/(assets|javascript)/\w+/(.+\.(css|js|html|png|jpg|ts|jsx)).*}, reload: :always
62
+
50
63
  # More examples:
51
64
  # config.watch %r{app/helpers/.+\.rb}, reload: :always
52
65
  # config.watch %r{config/locales/.+\.yml}, reload: :always
53
- end
66
+ end if defined?(RailsLiveReload)
54
67
  ```
55
68
 
56
69
  ## How it works
57
70
 
58
- There are 3 main pieces how it works:
71
+ There are 3 main parts:
59
72
 
60
- 1) listener for file changes using `listen` gem
73
+ 1) listener of file changes (using `listen` gem)
61
74
  2) collector of rendered views (see rails instrumentation)
62
- 3) middleware which is responding to setInterval JS calls
75
+ 3) middleware which is responding to polling JS calls
76
+
77
+ ## Notes
78
+
79
+ 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
80
 
64
81
  ## Contributing
65
82
 
@@ -68,17 +85,19 @@ You are welcome to contribute. See list of `TODO's` below.
68
85
  ## TODO
69
86
 
70
87
  - reload CSS without reloading the whole page?
88
+ - add `:websocket` mode?
71
89
  - smarter reload if there is a change in helper (check methods from rendered views?)
72
90
  - 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
91
+ - more complex rules? e.g. if "user.rb" file is changed - reload all pages with rendered "users" views
75
92
  - check with older Rails versions
76
93
  - tests or specs
77
94
  - CI (github actions)
95
+ - improve how JS code is injected into HTML
96
+ - improve work with turbo, turbolinks
78
97
 
79
98
  ## License
80
99
 
81
100
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
82
101
 
83
102
  [<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)
103
+ />](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,39 @@
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
23
+
24
+ def initialize
25
+ @mode = :long_polling
26
+ @timeout = 30
27
+ @patterns = {}
28
+ @polling_interval = 100
29
+ @url = "/rails/live/reload"
30
+ @watcher = nil
31
+ @files = {}
32
+ @enabled = ::Rails.env.development? && !defined?(Rails::Console)
33
+ end
34
+
35
+ def watch(pattern, reload: :on_change)
36
+ patterns[pattern] = reload
37
+ end
38
+ end
39
+ 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?
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,53 @@
1
+ module RailsLiveReload
2
+ module Rails
3
+ module Middleware
4
+ class LongPolling < Base
5
+ private
6
+
7
+ POLLING_SLEEP = 0.1
8
+
9
+ def rails_live_response(request)
10
+ params = request.params
11
+ body = lambda do |stream|
12
+ new_thread do
13
+ counter = 0
14
+
15
+ loop do
16
+ command = RailsLiveReload::Command.new(params)
17
+
18
+ if command.reload?
19
+ stream.write(command.payload.to_json) and break
20
+ end
21
+
22
+ sleep(POLLING_SLEEP)
23
+ counter += 1
24
+
25
+ stream.write(command.payload.to_json) and break if counter >= max_sleeps_count
26
+ end
27
+ ensure
28
+ stream.close
29
+ end
30
+ end
31
+
32
+ [ 200, { 'Content-Type' => 'application/json', 'rack.hijack' => body }, nil ]
33
+ end
34
+
35
+ def client_javascript
36
+ RailsLiveReload::Client.long_polling_js
37
+ end
38
+
39
+ def max_sleeps_count
40
+ RailsLiveReload.config.timeout * (1 / POLLING_SLEEP)
41
+ end
42
+
43
+ def new_thread
44
+ Thread.new {
45
+ t2 = Thread.current
46
+ t2.abort_on_exception = true
47
+ yield
48
+ }
49
+ end
50
+ end
51
+ end
52
+ end
53
+ 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.0"
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,19 @@ 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
26
 
37
- # default watch settings
38
- RailsLiveReload.setup do |config|
27
+ # These configs work for 95% apps, see README for more info
28
+ RailsLiveReload.configure do |config|
39
29
  config.watch %r{app/views/.+\.(erb|haml|slim)$}
40
30
  config.watch %r{(app|vendor)/(assets|javascript)/\w+/(.+\.(css|js|html|png|jpg|ts|jsx)).*}, reload: :always
41
- end
31
+ 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.0
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
@@ -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