react-rails-hot-loader 0.0.1 → 0.1.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
  SHA1:
3
- metadata.gz: 87d38a21b1f7917eb29e27a54592a9018402baeb
4
- data.tar.gz: 88269e19352ab97728fd47c4dd8fb21bd4021d4a
3
+ metadata.gz: 120d5f5ea466039d5d1aea66acdfd7a6b2d2b47c
4
+ data.tar.gz: 10591893cb60c6fdc558ec3efeece0910b79be9d
5
5
  SHA512:
6
- metadata.gz: 53c3b2306215e96d4fa626ee9f933c4aea0689d917b97365baf922e50f390b953b68dee8d53a71b65595c64dda0e5a52bf0b06b9c04a8f0c436e4804dc7ceda7
7
- data.tar.gz: 55291a15d02363ebe0bb1b671ec9458e51e55c76268230edcf6478a3cf103c5fb3b498f5de9f066e1ef2ea440ba02de969cf59143a5e104b8adf2de10a1586c0
6
+ metadata.gz: 243026941a4eed56d3b40af15007b960a9779d4fc04a491af319bc1f053069c70399f527f670e9f5059c49880ac837e397fce283ce1ff6dd9d80fa12faa4d257
7
+ data.tar.gz: 5f541a0af462ef1a961250cdf2573acffe7e7c1de737962a0ff86c46d52485c54d5fc10e294d369692f54412abf05b2e3ee823a2a57e1bcf636eab8a688a2bbc
@@ -1,4 +1,7 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.0.0
3
+ - 2.2.0
4
4
  before_install: gem install bundler -v 1.10.3
5
+ addons:
6
+ code_climate:
7
+ repo_token: 89617e5ca8a5789349231b46f543b5666f139bfb23d5946bc4517609926071f9
data/Guardfile CHANGED
@@ -3,3 +3,15 @@ guard :minitest do
3
3
  watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}#{m[2]}_test.rb" }
4
4
  watch(%r{^test/test_helper\.rb$}) { 'test' }
5
5
  end
6
+
7
+ guard :bundler do
8
+ require 'guard/bundler'
9
+ require 'guard/bundler/verify'
10
+ helper = Guard::Bundler::Verify.new
11
+
12
+ files = ['Gemfile']
13
+ files += Dir['*.gemspec'] if files.any? { |f| helper.uses_gemspec?(f) }
14
+
15
+ # Assume files are symlinked from somewhere
16
+ files.each { |file| watch(helper.real_path(file)) }
17
+ end
data/README.md CHANGED
@@ -1,7 +1,11 @@
1
- # React::Rails::HotLoader
1
+ # React::Rails::HotLoader
2
2
 
3
3
  Reload React.js components with Ruby on Rails & [`react-rails`](http://github.com/reactjs/react-rails).
4
4
 
5
+ When you edit components, they'll be reloaded by the browser & re-mounted in the page.
6
+
7
+ [![Gem Version](https://badge.fury.io/rb/react-rails-hot-loader.svg)](http://badge.fury.io/rb/react-rails-hot-loader) [![Build Status](https://travis-ci.org/rmosolgo/react-rails-hot-loader.svg)](https://travis-ci.org/rmosolgo/react-rails-hot-loader) [![Code Climate](https://codeclimate.com/github/rmosolgo/react-rails-hot-loader/badges/gpa.svg)](https://codeclimate.com/github/rmosolgo/react-rails-hot-loader) [![Test Coverage](https://codeclimate.com/github/rmosolgo/react-rails-hot-loader/badges/coverage.svg)](https://codeclimate.com/github/rmosolgo/react-rails-hot-loader/coverage)
8
+
5
9
  ## Installation
6
10
 
7
11
  Add this line to your application's Gemfile:
@@ -20,24 +24,28 @@ Or install it yourself as:
20
24
 
21
25
  ## Usage
22
26
 
23
- - Add an initializer (eg, `app/config/initializers/react_rails_hot_loader.rb`):
27
+ - Add an initializer:
24
28
 
25
29
  ```ruby
30
+ # app/config/initializers/react_rails_hot_loader.rb
26
31
  if Rails.env.development?
27
32
  React::Rails::HotLoader.start()
28
33
  end
29
34
  ```
30
35
 
31
- - Include the Javascript (eg, in `app/assets/javascripts/application.js`):
36
+ - Include the JavaScript:
32
37
 
33
38
  ```js
34
- //= require react_rails_hot_loader
39
+ // app/assets/javascripts/application.js
40
+ //= require react-rails-hot-loader
35
41
  ```
36
42
 
37
43
  (When not `Rails.env.development?`, this requires an empty file, so don't worry about leaving it in production deploys.)
38
44
 
39
45
  - Restart your development server
40
46
 
47
+ - Edit files in `/app/assets/javascripts` & save changes -- they'll be reloaded in the client and React components will be remounted.
48
+
41
49
  ## Doeses & Doesn'ts
42
50
 
43
51
  `react-rails-hot-loader` ...
@@ -53,7 +61,6 @@ Or install it yourself as:
53
61
 
54
62
  - Handle Passenger occasionally killing background threads :(
55
63
  - Replace pinging with file watching
56
- - Test Server, AssetPath
57
64
  - Add `rails g react-rails-hot-loader:install` to add initializer and JS
58
65
 
59
66
  ## License
@@ -1,22 +1,33 @@
1
- ReactRailsHotLoader = {
1
+ var ReactRailsHotLoader = {
2
2
  since: null,
3
3
  port: 8082,
4
- host: window.location.host,
4
+ host: window.location.hostname,
5
5
  shouldLog: true,
6
6
 
7
7
  start: function() {
8
8
  this._resetSince()
9
9
  var wsURL = "ws://" + this.host + ":" + this.port
10
- this.log(" connecting to " + wsURL)
10
+ this.log("connecting to " + wsURL)
11
11
  this._socket = new WebSocket(wsURL)
12
12
 
13
13
  var _this = this
14
14
 
15
+ this._socket.onopen = function() { _this.log("connected") }
16
+ this._socket.onclose = function() { _this.log("disconnected") }
17
+
15
18
  this._socket.onmessage = function(message) {
16
19
  var changes = JSON.parse(message.data)
17
- _this.log("updating " + changes.changed_asset_paths.length + " assets")
18
- changes.changed_asset_paths.forEach(_this._reloadAsset, _this)
20
+ _this.log("updating: " + changes.changed_file_names.join(", ") )
21
+ changes.changed_asset_contents.forEach(function(jsCode) {
22
+ try {
23
+ eval.call(window, jsCode)
24
+ } catch (err) {
25
+ _this.log(err)
26
+ }
27
+ })
28
+ ReactRailsUJS.mountComponents()
19
29
  _this._resetSince()
30
+ _this.log("update finished")
20
31
  }
21
32
 
22
33
  this._interval = setInterval(function() {
@@ -33,27 +44,6 @@ ReactRailsHotLoader = {
33
44
  clearInterval(this._interval)
34
45
  },
35
46
 
36
- _reloadAsset: function(path) {
37
- var _this = this
38
- var _handleResponse = function(js) {
39
- try {
40
- eval.call(window, js)
41
- } catch (err) {
42
- _this.log(err)
43
- }
44
- ReactRailsUJS.mountComponents()
45
- var name = path.split("/").pop()
46
- _this.log("reloaded " + name)
47
- }
48
-
49
- $.ajax({
50
- type: "GET",
51
- url: path,
52
- success: _handleResponse,
53
- error: _handleResponse,
54
- })
55
- },
56
-
57
47
  _resetSince: function() {
58
48
  // Ruby prefers seconds.
59
49
  this.since = Date.now() / 1000
@@ -2,19 +2,30 @@ module React
2
2
  module Rails
3
3
  module HotLoader
4
4
  mattr_accessor :server
5
- def self.start(*args)
6
- self.server = Server.new(*args)
7
- server.restart
5
+
6
+ # Create a new server with `options` & start it
7
+ def self.start(options={})
8
+ server_class = options.delete(:server_class) || Server
9
+ self.server = server_class.new(options)
10
+ restart
8
11
  end
9
12
 
13
+ # Restart the server with the same options
10
14
  def self.restart
11
15
  server.restart
12
16
  rescue StandardError => err
13
- log("failed to restart: #{err}")
17
+ React::Rails::HotLoader.error(err)
14
18
  end
15
19
 
16
20
  def self.log(message)
17
- ::Rails.logger.info("[HotLoader] #{message}")
21
+ msg = "[HotLoader] #{message}"
22
+ ::Rails.logger.info(msg)
23
+ ::Rails.logger.flush
24
+ end
25
+
26
+ def self.error(err)
27
+ msg = "#{err.class.name}: #{err}\n #{err.backtrace.join("\n")}"
28
+ log(msg)
18
29
  end
19
30
  end
20
31
  end
@@ -2,26 +2,31 @@ module React
2
2
  module Rails
3
3
  module HotLoader
4
4
  class AssetChangeSet
5
- attr_reader :since, :path, :changed_files, :changed_asset_paths
5
+ attr_reader :since, :path, :changed_files, :changed_file_names, :changed_asset_contents
6
6
  # initialize with a path and time
7
7
  # to find files which changed since that time
8
8
  def initialize(since:, path: ::Rails.root.join("app/assets/javascripts"))
9
9
  @since = since
10
10
  @path = path.to_s
11
- asset_glob = path.to_s + "/**/*.js.*"
11
+ asset_glob = path.to_s + "/**/*.js*"
12
12
  @changed_files = Dir.glob(asset_glob).select { |f| File.mtime(f) >= since }
13
- @changed_asset_paths = changed_files.map {|f| f.sub(path.to_s, "/assets").sub(/\.js.*/, ".js")}
13
+ @changed_file_names = changed_files.map { |f| f.split("/").last }
14
+ @changed_asset_contents = changed_files.map do |f|
15
+ logical_path = f.sub(path.to_s, "").sub(/^\//, '')
16
+ ::Rails.application.assets[logical_path].to_s
17
+ end
14
18
  end
15
19
 
16
20
  def any?
17
- changed_asset_paths.any?
21
+ changed_files.any?
18
22
  end
19
23
 
20
24
  def as_json(options={})
21
25
  {
22
26
  since: since,
23
27
  path: path,
24
- changed_asset_paths: changed_asset_paths,
28
+ changed_file_names: changed_file_names,
29
+ changed_asset_contents: changed_asset_contents,
25
30
  }
26
31
  end
27
32
  end
@@ -1,7 +1,9 @@
1
1
  module React
2
2
  module Rails
3
3
  module HotLoader
4
+ # We want to include different files in dev/prod. The production (dummy) file is empty!
4
5
  class AssetPath
6
+
5
7
  GEM_LIB_PATH = Pathname.new('../../').expand_path(__FILE__)
6
8
 
7
9
  attr_reader :to_s
@@ -3,8 +3,6 @@ module React
3
3
  module HotLoader
4
4
  class Railtie < ::Rails::Railtie
5
5
  config.before_initialize do |app|
6
- # We want to include different files in dev/prod.
7
- # The production file is empty!
8
6
  asset_path = React::Rails::HotLoader::AssetPath.new(dummy: !(::Rails.env.development?))
9
7
  app.config.assets.paths << asset_path.to_s
10
8
  end
@@ -14,7 +12,7 @@ module React
14
12
  begin
15
13
  React::Rails::HotLoader.restart
16
14
  rescue StandardError => err
17
- React::Rails::HotLoader.log("to_prepare failed: #{err}\n#{err.backtrace.join("\n")}")
15
+ React::Rails::HotLoader.error(err)
18
16
  end
19
17
  end
20
18
  end
@@ -10,49 +10,58 @@ module React
10
10
  @host = host
11
11
  @port = port
12
12
  @change_set_class = change_set_class
13
- @thread = nil
14
13
  end
15
14
 
15
+ # Restarts the server _if_ it has stopped
16
16
  def restart
17
- if @thread.blank? || @thread.stop?
18
- "[HotLoader] restarting: #{@thread}, #{@thread.try(:status)}"
19
- @thread = Thread.new do
20
- begin
21
- serve
22
- rescue StandardError => err
23
- React::Rails::HotLoader.log("failed to serve: #{err}\n#{err.backtrace.join("\n")}")
24
- end
17
+ return if running?
18
+ start
19
+ rescue StandardError => err
20
+ React::Rails::HotLoader.error(err)
21
+ end
22
+
23
+ private
24
+
25
+ def running?
26
+ @server_thread && @server_thread.alive?
27
+ end
28
+
29
+ def start
30
+ @server_thread = Thread.new do
31
+ begin
32
+ serve
33
+ rescue StandardError => err
34
+ React::Rails::HotLoader.error(err)
25
35
  end
26
36
  end
27
37
  end
28
38
 
29
39
  def serve
30
40
  EM.run {
31
- React::Rails::HotLoader.log("starting WS server...")
41
+ React::Rails::HotLoader.log("starting WS server: ws://#{host}:#{port}")
32
42
 
33
43
  EM::WebSocket.run(host: host, port: port) do |ws|
34
- ws.onopen { React::Rails::HotLoader.log("opened a connection") }
35
-
36
- ws.onmessage { |msg|
37
- begin
38
- since_time = Time.at(msg.to_i)
39
- changes = change_set_class.new(since: since_time)
40
- if changes.any?
41
- React::Rails::HotLoader.log("received message: #{msg}")
42
- React::Rails::HotLoader.log("sent response: #{changes.to_json}")
43
- ws.send(changes.to_json)
44
- end
45
- rescue StandardError => err
46
- React::Rails::HotLoader.log("message error: #{err}\n #{err.backtrace.join("\n")}")
47
- end
48
- }
49
-
50
- ws.onclose { React::Rails::HotLoader.log("closed a connection") }
44
+ ws.onopen { React::Rails::HotLoader.log("opened a connection") }
45
+ ws.onmessage { |msg| handle_message(ws, msg) }
46
+ ws.onclose { React::Rails::HotLoader.log("closed a connection") }
51
47
  end
52
48
 
53
49
  React::Rails::HotLoader.log("started WS server")
54
50
  }
55
51
  end
52
+
53
+ # Check for any changes since `msg`, respond if there are any changes
54
+ def handle_message(ws, msg)
55
+ # React::Rails::HotLoader.log("received message: #{msg}")
56
+ since_time = Time.at(msg.to_i)
57
+ changes = change_set_class.new(since: since_time)
58
+ if changes.any?
59
+ React::Rails::HotLoader.log("sent changes: #{changes.changed_file_names}")
60
+ ws.send(changes.to_json)
61
+ end
62
+ rescue StandardError => err
63
+ React::Rails::HotLoader.error(err)
64
+ end
56
65
  end
57
66
  end
58
67
  end
@@ -1,7 +1,7 @@
1
1
  module React
2
2
  module Rails
3
3
  module HotLoader
4
- VERSION = '0.0.1'
4
+ VERSION = '0.1.0'
5
5
  end
6
6
  end
7
7
  end
@@ -17,12 +17,19 @@ Gem::Specification.new do |spec|
17
17
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
18
  spec.require_paths = ["lib"]
19
19
 
20
+ spec.required_ruby_version = '>= 2.1.0'
21
+
20
22
  spec.add_runtime_dependency "em-websocket"
23
+ spec.add_runtime_dependency "rails"
21
24
  spec.add_runtime_dependency "react-rails"
22
25
 
23
26
  spec.add_development_dependency "bundler", "~> 1.10"
24
- spec.add_development_dependency "rake", "~> 10.0"
25
- spec.add_development_dependency "minitest"
27
+ spec.add_development_dependency "codeclimate-test-reporter"
26
28
  spec.add_development_dependency "guard"
29
+ spec.add_development_dependency "guard-bundler"
27
30
  spec.add_development_dependency "guard-minitest"
31
+ spec.add_development_dependency "minitest"
32
+ spec.add_development_dependency "rake", "~> 10.0"
33
+ spec.add_development_dependency "sqlite3"
34
+ spec.add_development_dependency "websocket-client-simple"
28
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: react-rails-hot-loader
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-18 00:00:00.000000000 Z
11
+ date: 2015-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: em-websocket
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: react-rails
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -53,21 +67,21 @@ dependencies:
53
67
  - !ruby/object:Gem::Version
54
68
  version: '1.10'
55
69
  - !ruby/object:Gem::Dependency
56
- name: rake
70
+ name: codeclimate-test-reporter
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
- - - "~>"
73
+ - - ">="
60
74
  - !ruby/object:Gem::Version
61
- version: '10.0'
75
+ version: '0'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
- - - "~>"
80
+ - - ">="
67
81
  - !ruby/object:Gem::Version
68
- version: '10.0'
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
- name: minitest
84
+ name: guard
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - ">="
@@ -81,7 +95,7 @@ dependencies:
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
- name: guard
98
+ name: guard-bundler
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
101
  - - ">="
@@ -108,6 +122,62 @@ dependencies:
108
122
  - - ">="
109
123
  - !ruby/object:Gem::Version
110
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: minitest
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rake
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '10.0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '10.0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: sqlite3
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: websocket-client-simple
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
111
181
  description: Tie into the `react-rails` gem to notify the client of changed files
112
182
  & reload assets on the client when they are changed.
113
183
  email:
@@ -147,7 +217,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
147
217
  requirements:
148
218
  - - ">="
149
219
  - !ruby/object:Gem::Version
150
- version: '0'
220
+ version: 2.1.0
151
221
  required_rubygems_version: !ruby/object:Gem::Requirement
152
222
  requirements:
153
223
  - - ">="