react-rails-hot-loader 0.0.1 → 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
  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
  - - ">="