web-console 2.0.0.beta3 → 2.0.0.beta4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of web-console might be problematic. Click here for more details.

Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.markdown +16 -31
  3. data/app/assets/javascripts/web_console/console_sessions.js +16 -6
  4. data/app/controllers/web_console/console_sessions_controller.rb +8 -4
  5. data/app/models/web_console/console_session.rb +13 -0
  6. data/app/views/web_console/console_sessions/index.html.erb +3 -1
  7. data/lib/action_dispatch/debug_exceptions.rb +4 -8
  8. data/lib/action_dispatch/exception_wrapper.rb +1 -1
  9. data/lib/action_dispatch/templates/rescues/_web_console.html.erb +9 -8
  10. data/lib/action_dispatch/templates/routes/_route.html.erb +16 -0
  11. data/lib/action_dispatch/templates/routes/_table.html.erb +200 -0
  12. data/lib/web_console.rb +2 -1
  13. data/lib/web_console/controller_helpers.rb +44 -0
  14. data/lib/web_console/core_ext/exception.rb +59 -0
  15. data/lib/web_console/engine.rb +2 -1
  16. data/lib/web_console/repl_session.rb +4 -7
  17. data/lib/web_console/slave.rb +11 -3
  18. data/lib/web_console/version.rb +1 -1
  19. data/lib/web_console/view_helpers.rb +2 -5
  20. data/test/controllers/web_console/console_sessions_controller_test.rb +12 -7
  21. data/test/dummy/app/controllers/controller_helper_test_controller.rb +7 -0
  22. data/test/dummy/app/views/controller_helper_test/index.html.erb +1 -0
  23. data/test/dummy/config/routes.rb +1 -0
  24. data/test/dummy/log/test.log +257 -8122
  25. data/test/dummy/tmp/cache/assets/test/sprockets/{cb0065359d3b5b296f71d673f4b276e9 → 0c9b99b1b975b36a5b686845ae729db3} +0 -0
  26. data/test/dummy/tmp/cache/assets/{development/sprockets/8aa4c7aabff23c8089d41e9e54193483 → test/sprockets/12e9f58adcf819cf65fd68b6859a438f} +0 -0
  27. data/test/dummy/tmp/cache/assets/test/sprockets/1fd6abead3df36a4e4a2cb042a551b39 +0 -0
  28. data/test/dummy/tmp/cache/assets/test/sprockets/33b5eb81b5aaaa1e6dd5dcb6517792b4 +0 -0
  29. data/test/dummy/tmp/cache/assets/test/sprockets/{d1f6e06bc2f112c4ec3a4c3f68351878 → 3e460b2e021085f88b5597b38d194932} +0 -0
  30. data/test/dummy/tmp/cache/assets/test/sprockets/{55b7b76605fdffe31d737d4ac1f1ef7b → 52f04b2ea6e461f4661b6d0be393fa94} +0 -0
  31. data/test/dummy/tmp/cache/assets/test/sprockets/{e6d6b8bde546349764be7b44ffcf5807 → 688c344c2919f882338f06c5daaea209} +0 -0
  32. data/test/dummy/tmp/cache/assets/{development/sprockets/d982412def520c434e2240eae6d29cf2 → test/sprockets/7f079298e19bbef40a5d6a37dc03033a} +0 -0
  33. data/test/dummy/tmp/cache/assets/test/sprockets/{7a50a9e605754e99783de95715b976b0 → 91aa709f89e465f58056fabe5f75eef4} +0 -0
  34. data/test/dummy/tmp/cache/assets/test/sprockets/{6ad7acc9a22fe2a67ec24a1fc866c20e → 95f4e4e5217aec9f71b2c1a65a9a9231} +0 -0
  35. data/test/dummy/tmp/cache/assets/{development/sprockets/5ac98782fe3dfd0a766f75ce1801f0a0 → test/sprockets/9c41be9b6625756fbb6d05b7665dd911} +0 -0
  36. data/test/dummy/tmp/cache/assets/test/sprockets/a95f64d41fcf8244b8f5b84a55f07822 +0 -0
  37. data/test/dummy/tmp/cache/assets/{development/sprockets/6ad7acc9a22fe2a67ec24a1fc866c20e → test/sprockets/c5e6bf1efd5929bee63e28ad7c9f6f83} +0 -0
  38. data/test/dummy/tmp/cache/assets/test/sprockets/d863259e9eeca657a1624135cfe24446 +0 -0
  39. data/test/dummy/tmp/cache/assets/test/sprockets/e1d2fc4601b6423ec8a42415ee05dd14 +0 -0
  40. data/test/dummy/tmp/cache/assets/test/sprockets/e82616536a759c2e87d703adc77d65da +0 -0
  41. data/test/test_helper.rb +52 -0
  42. data/test/web_console/controller_helpers_test.rb +48 -0
  43. data/test/web_console/core_ext/exception_test.rb +34 -0
  44. data/test/web_console/engine_test.rb +9 -0
  45. data/test/web_console/repl_session_test.rb +4 -4
  46. data/test/web_console/slave_test.rb +1 -0
  47. metadata +46 -151
  48. data/lib/web_console/exception_extension.rb +0 -21
  49. data/test/dummy/db/development.sqlite3 +0 -0
  50. data/test/dummy/log/development.log +0 -61814
  51. data/test/dummy/tmp/cache/assets/development/sprockets/038461854af2e8bccdb29768efd4768f +0 -0
  52. data/test/dummy/tmp/cache/assets/development/sprockets/0ec396634a5f6808b026257fd107c355 +0 -0
  53. data/test/dummy/tmp/cache/assets/development/sprockets/127a54171eea8d294e4673599861787d +0 -0
  54. data/test/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  55. data/test/dummy/tmp/cache/assets/development/sprockets/17c571144b4e44da39bddb2d2c412414 +0 -0
  56. data/test/dummy/tmp/cache/assets/development/sprockets/1cb77d8cf661ccbc9de08f347c89b9f1 +0 -0
  57. data/test/dummy/tmp/cache/assets/development/sprockets/204edd12a29660722d4e0d8de9bd6652 +0 -0
  58. data/test/dummy/tmp/cache/assets/development/sprockets/2b96b037f3dfeccfe27113eb95b06ea1 +0 -0
  59. data/test/dummy/tmp/cache/assets/development/sprockets/2c853768baf811357d81d41bdfd05dcf +0 -0
  60. data/test/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  61. data/test/dummy/tmp/cache/assets/development/sprockets/314d48e543146f617c4d3439a4d8d40d +0 -0
  62. data/test/dummy/tmp/cache/assets/development/sprockets/34f21019a876722b8c24a6da4f0ef50b +0 -0
  63. data/test/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  64. data/test/dummy/tmp/cache/assets/development/sprockets/36341e42f23669574fa1027d0958ff3e +0 -0
  65. data/test/dummy/tmp/cache/assets/development/sprockets/44117154e909436e7eeaf10cdb18d2b4 +0 -0
  66. data/test/dummy/tmp/cache/assets/development/sprockets/496864a905d53afd8e176f29500f96a8 +0 -0
  67. data/test/dummy/tmp/cache/assets/development/sprockets/55b7b76605fdffe31d737d4ac1f1ef7b +0 -0
  68. data/test/dummy/tmp/cache/assets/development/sprockets/6088d6f344b38303cc8028057d69e0f9 +0 -0
  69. data/test/dummy/tmp/cache/assets/development/sprockets/676dcf9b2d01b9dc7bd3183d8da88463 +0 -0
  70. data/test/dummy/tmp/cache/assets/development/sprockets/680381170dc160e358fc28076ea6886c +0 -0
  71. data/test/dummy/tmp/cache/assets/development/sprockets/6bdb0d0c602e0e1bc304dc697e2cc6de +0 -0
  72. data/test/dummy/tmp/cache/assets/development/sprockets/6dc8d7aa69668fce85683aaad6615432 +0 -0
  73. data/test/dummy/tmp/cache/assets/development/sprockets/6e4d5b32cc444226f6597198994ccd5e +0 -0
  74. data/test/dummy/tmp/cache/assets/development/sprockets/74db0ca5cb8c8c347c9131a3ff516748 +0 -0
  75. data/test/dummy/tmp/cache/assets/development/sprockets/7999e525c88173c1beb785f002effc1d +0 -0
  76. data/test/dummy/tmp/cache/assets/development/sprockets/7a50a9e605754e99783de95715b976b0 +0 -0
  77. data/test/dummy/tmp/cache/assets/development/sprockets/806b0e33a2fe8e1245534345fa27c30a +0 -0
  78. data/test/dummy/tmp/cache/assets/development/sprockets/90396626cba6cbec37e32038e6c54e76 +0 -0
  79. data/test/dummy/tmp/cache/assets/development/sprockets/976b28910aa72c90a3b30c6e940f51df +0 -0
  80. data/test/dummy/tmp/cache/assets/development/sprockets/99e1bd7cbc437505bc8f07bc528c721c +0 -0
  81. data/test/dummy/tmp/cache/assets/development/sprockets/aaccf2c9ae2add0863c9a49e0042a097 +0 -0
  82. data/test/dummy/tmp/cache/assets/development/sprockets/ae4677d24a79d9411f2fced5011d5807 +0 -0
  83. data/test/dummy/tmp/cache/assets/development/sprockets/b2401118729720034b6f3eda0b4c5025 +0 -0
  84. data/test/dummy/tmp/cache/assets/development/sprockets/c649837df826fc310cb80f1adafd6b8d +0 -0
  85. data/test/dummy/tmp/cache/assets/development/sprockets/cac185d59612fae451a12df3fc21bb51 +0 -0
  86. data/test/dummy/tmp/cache/assets/development/sprockets/cb0065359d3b5b296f71d673f4b276e9 +0 -0
  87. data/test/dummy/tmp/cache/assets/development/sprockets/cee8c6b09c33d2b276753e959712724e +0 -0
  88. data/test/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  89. data/test/dummy/tmp/cache/assets/development/sprockets/d1f6e06bc2f112c4ec3a4c3f68351878 +0 -0
  90. data/test/dummy/tmp/cache/assets/development/sprockets/d20d83fd7ffa378b1b2b901786d640f3 +0 -0
  91. data/test/dummy/tmp/cache/assets/development/sprockets/d38c7c3aa1e72b55769ccb3607641ef4 +0 -0
  92. data/test/dummy/tmp/cache/assets/development/sprockets/d6b85d8b0b5c569388b89e56e9f6fed7 +0 -0
  93. data/test/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  94. data/test/dummy/tmp/cache/assets/development/sprockets/df048a8b0897b9c04acdf59c8f95b18f +0 -0
  95. data/test/dummy/tmp/cache/assets/development/sprockets/df600f50f002512c95d93bcfbab891ed +0 -0
  96. data/test/dummy/tmp/cache/assets/development/sprockets/e6d6b8bde546349764be7b44ffcf5807 +0 -0
  97. data/test/dummy/tmp/cache/assets/development/sprockets/eb25265794d2f7afd1684779d84efdac +0 -0
  98. data/test/dummy/tmp/cache/assets/development/sprockets/ee8826b12b7d9bfd717df950b58f82ab +0 -0
  99. data/test/dummy/tmp/cache/assets/development/sprockets/ef9824789c6ed3483590e0564a12e1d1 +0 -0
  100. data/test/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  101. data/test/dummy/tmp/cache/assets/development/sprockets/fc7201c6cbef32453aa4175c520c8eae +0 -0
  102. data/test/dummy/tmp/cache/assets/test/sprockets/17c571144b4e44da39bddb2d2c412414 +0 -0
  103. data/test/dummy/tmp/cache/assets/test/sprockets/36341e42f23669574fa1027d0958ff3e +0 -0
  104. data/test/dummy/tmp/cache/assets/test/sprockets/5ac98782fe3dfd0a766f75ce1801f0a0 +0 -0
  105. data/test/dummy/tmp/cache/assets/test/sprockets/680381170dc160e358fc28076ea6886c +0 -0
  106. data/test/dummy/tmp/cache/assets/test/sprockets/6e4d5b32cc444226f6597198994ccd5e +0 -0
  107. data/test/dummy/tmp/cache/assets/test/sprockets/8aa4c7aabff23c8089d41e9e54193483 +0 -0
  108. data/test/dummy/tmp/cache/assets/test/sprockets/b2401118729720034b6f3eda0b4c5025 +0 -0
  109. data/test/dummy/tmp/cache/assets/test/sprockets/d6b85d8b0b5c569388b89e56e9f6fed7 +0 -0
  110. data/test/dummy/tmp/cache/assets/test/sprockets/d982412def520c434e2240eae6d29cf2 +0 -0
  111. data/test/dummy/tmp/cache/assets/test/sprockets/df048a8b0897b9c04acdf59c8f95b18f +0 -0
  112. data/test/web_console/exception_extention_test.rb +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: afe33c91afb082074dd982930c4aef140c279c9e
4
- data.tar.gz: e77676a84dde11dae828446db54974a79fbe3896
3
+ metadata.gz: fc8e319e9b1f84cf82daa49aad866ae6c93c615a
4
+ data.tar.gz: 60bc79a8546eee3b05d9566c1a146267575fd2b6
5
5
  SHA512:
6
- metadata.gz: 8180671dcf6b9227a3f0c1d1ccf5397f8926734b91a2586bf83f4a2f06b9b1fd7de58f10a13731108493459111c4a522ffde51c14dd668aa2f90255c7e0c6ce1
7
- data.tar.gz: fbed5ea4aa571865488f344f94b35d05f81b39174f52ddab726f43cbb77274f91aedd1ef72d904a611848082d5f57f920b891614a5610a6755a498a319613eee
6
+ metadata.gz: a2b3ec02cc16ec9ac3ec0ea28ac408e481a31db218dccdd9da149f543052051312133afd6ca690cd1ce581d162c6bb9b3b91f7bd4a6ec058e5b5ba8964dd00bb
7
+ data.tar.gz: bbd5a609a1dcca7cfbf1d95c0ada4ce8cb697720669864996f26d29809ce36c23dca95b54ddb6a67ec422d4d3f533b4200c65fe10e2c6d04842c8d087c5f51f8
@@ -57,7 +57,7 @@ _Web Console_ has been tested on the following rubies.
57
57
  There is an experimental _JRuby_ 1.7 support. See Installation section for more
58
58
  information.
59
59
 
60
- _Rubunius_ in 1.9 mode may work, but it hasn't been explicitly tested.
60
+ _Rubinius_ in 1.9 mode may work, but it hasn't been explicitly tested.
61
61
 
62
62
  _Web Console_ is built explicitly for _Rails 4_. Check out the
63
63
  [web-console-rails3] project for a _Rails 3_ compatible build.
@@ -69,17 +69,7 @@ To install it in your current application, add the following to your `Gemfile`.
69
69
 
70
70
  ```ruby
71
71
  group :development do
72
- gem 'web-console', '2.0.0.beta2'
73
- end
74
- ```
75
-
76
- For _JRuby_ support, you need to add an unreleased version of
77
- `binding_of_caller`.
78
-
79
- ```ruby
80
- group :development do
81
- gem 'web-console', '2.0.0.beta2'
82
- gem 'binding_of_caller', github: 'banister/binding_of_caller'
72
+ gem 'web-console', '2.0.0.beta3'
83
73
  end
84
74
  ```
85
75
 
@@ -288,11 +278,18 @@ end
288
278
  You may also change the font, which is following the CSS font property syntax.
289
279
  By default it is `large DejaVu Sans Mono, Liberation Mono, monospace`.
290
280
 
291
- Shout-out
292
- ---------
281
+ Credits
282
+ -------
283
+
284
+ * Shoutout to [Charlie Somerville] for [better_errors]! Most of the exception
285
+ binding code is coming straight out of the [better_errors] project.
286
+
287
+ * _Web Console_ wouldn't be possible without the work [John Mair] put in
288
+ [binding_of_caller]. This is the technology that let us execute a console
289
+ right where an error occured.
293
290
 
294
- Great thanks to [Charlie Somerville] for [better_errors]! Most of the exception
295
- binding code is coming straight out of the [better_errors] project.
291
+ * Thanks to [Charles Oliver Nutter] for all the JRuby feedback and support he
292
+ has given us.
296
293
 
297
294
  FAQ
298
295
  ---
@@ -307,18 +304,6 @@ is even slower. Read more about the problem at the _JRuby_ [wiki].
307
304
 
308
305
  ### I'm running JRuby and there's no console on the default error page.
309
306
 
310
- _JRuby_ support in the default error page requires the latest is experimental
311
- and requires an unreleased version of `web-console` and `binding_of_caller`.
312
-
313
- To try it out, put this in your Gemfile.
314
-
315
- ```ruby
316
- group :development do
317
- gem 'web-console', github: 'rails/web-console'
318
- gem 'binding_of_caller', github: 'banister/binding_of_caller'
319
- end
320
- ```
321
-
322
307
  You would also have to run you Rails server in JRuby's interpreted mode. Enable
323
308
  it with code snippet below, then start your development Rails server with
324
309
  `rails server`, as usual.
@@ -330,9 +315,6 @@ export JRUBY_OPTS=-J-Djruby.compile.mode=OFF
330
315
  # export JRUBY_OPTS=--dev
331
316
  ```
332
317
 
333
- _(Please, note that we don't guarantee master to be stable and we
334
- will appreciate any issue reports!)_
335
-
336
318
  ### Changing the colors is broken.
337
319
 
338
320
  Some of the style sheets may be cached on the file system. Run
@@ -350,4 +332,7 @@ The interactive console executes Ruby code. Invoking `instance_variables` and
350
332
  [web-console-rails3]: https://github.com/gsamokovarov/web-console-rails3
351
333
  [wiki]: https://github.com/jruby/jruby/wiki/Improving-startup-time#avoid-spawning-sub-rubies
352
334
  [better_errors]: https://github.com/charliesome/better_errors
335
+ [binding_of_caller]: https://github.com/banister/binding_of_caller
353
336
  [Charlie Somerville]: https://github.com/charliesome
337
+ [John Mair]: https://github.com/banister
338
+ [Charles Oliver Nutter]: https://github.com/headius
@@ -17,6 +17,7 @@ var AJAXTransport = (function(WebConsole) {
17
17
  configuration: options.url
18
18
  } : options.url;
19
19
 
20
+ this.uid = options.uid;
20
21
  this.pendingInput = '';
21
22
 
22
23
  this.initializeEventHandlers();
@@ -38,8 +39,7 @@ var AJAXTransport = (function(WebConsole) {
38
39
  AJAXTransport.prototype.createRequest = function(method, url, options) {
39
40
  options || (options = {});
40
41
 
41
- var request = new XMLHttpRequest;
42
- request.open(method, url);
42
+ var params = '';
43
43
 
44
44
  if (typeof options.form === 'object') {
45
45
  var content = [], form = options.form;
@@ -49,15 +49,25 @@ var AJAXTransport = (function(WebConsole) {
49
49
  content.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
50
50
  }
51
51
 
52
+ params = content.join('&');
53
+ if (method === 'GET' ? '?' : '') params = '?' + params;
54
+ }
55
+
56
+ var request = new XMLHttpRequest;
57
+ request.open(method, method === 'GET' ? url + params : url);
58
+
59
+ if (params && method != 'GET') {
52
60
  request.setRequestHeader('Content-Type', FORM_MIME_TYPE);
53
- request.data = content.join('&');
61
+ request.data = params;
54
62
  }
55
63
 
56
64
  return request;
57
65
  };
58
66
 
59
67
  AJAXTransport.prototype.pollForPendingOutput = function() {
60
- var request = this.createRequest('GET', this.url.pendingOutput);
68
+ var request = this.createRequest('GET', this.url.pendingOutput, {
69
+ form: { uid: this.uid }
70
+ });
61
71
 
62
72
  var self = this;
63
73
  request.onreadystatechange = function() {
@@ -90,7 +100,7 @@ var AJAXTransport = (function(WebConsole) {
90
100
  this.sendingInput = true;
91
101
 
92
102
  var request = this.createRequest('PUT', this.url.input, {
93
- form: { input: this.pendingInput + input }
103
+ form: { input: this.pendingInput + input, uid: this.uid }
94
104
  });
95
105
 
96
106
  // Clear the pending input.
@@ -117,7 +127,7 @@ var AJAXTransport = (function(WebConsole) {
117
127
  if (this.disconnected) return;
118
128
 
119
129
  var request = this.createRequest('PUT', this.url.configuration, {
120
- form: { width: cols, height: rows }
130
+ form: { width: cols, height: rows, uid: this.uid }
121
131
  });
122
132
 
123
133
  // Just send the configuration and don't care about any output.
@@ -10,26 +10,30 @@ module WebConsole
10
10
  render json: exception, status: :unprocessable_entity
11
11
  end
12
12
 
13
+ rescue_from ConsoleSession::Unauthorized do |exception|
14
+ render json: exception, status: :unauthorized
15
+ end
16
+
13
17
  def index
14
18
  @console_session = ConsoleSession.create
15
19
  end
16
20
 
17
21
  def input
18
- @console_session = ConsoleSession.find(params[:id])
22
+ @console_session = ConsoleSession.find_by_pid_and_uid(params[:id], params[:uid])
19
23
  @console_session.send_input(console_session_params[:input])
20
24
 
21
25
  render nothing: true
22
26
  end
23
27
 
24
28
  def configuration
25
- @console_session = ConsoleSession.find(params[:id])
29
+ @console_session = ConsoleSession.find_by_pid_and_uid(params[:id], params[:uid])
26
30
  @console_session.configure(console_session_params)
27
31
 
28
32
  render nothing: true
29
33
  end
30
34
 
31
35
  def pending_output
32
- @console_session = ConsoleSession.find(params[:id])
36
+ @console_session = ConsoleSession.find_by_pid_and_uid(params[:id], params[:uid])
33
37
 
34
38
  render json: { output: @console_session.pending_output }
35
39
  end
@@ -37,7 +41,7 @@ module WebConsole
37
41
  private
38
42
 
39
43
  def console_session_params
40
- params.permit(:id, :input, :width, :height)
44
+ params.permit(:id, :uid, :input, :width, :height)
41
45
  end
42
46
  end
43
47
  end
@@ -24,6 +24,9 @@ module WebConsole
24
24
  # Raised when an operation transition to an invalid state.
25
25
  Invalid = Class.new(Error)
26
26
 
27
+ # Raised when a request doesn't know the slave process uid.
28
+ Unauthorized = Class.new(Error)
29
+
27
30
  class << self
28
31
  # Finds a session by its pid.
29
32
  #
@@ -32,6 +35,16 @@ module WebConsole
32
35
  INMEMORY_STORAGE[pid.to_i] or raise Unavailable, 'Session unavailable'
33
36
  end
34
37
 
38
+ # Finds a session by its pid.
39
+ #
40
+ # Raises WebConsole::ConsoleSession::Expired if there is no such session.
41
+ # Raises WebConsole::ConsoleSession::Unauthorized if uid doesn't match.
42
+ def find_by_pid_and_uid(pid, uid)
43
+ find(pid).tap do |console_session|
44
+ raise Unauthorized if console_session.uid != uid
45
+ end
46
+ end
47
+
35
48
  # Creates an already persisted consolse session.
36
49
  #
37
50
  # Use this method if you need to persist a session, without providing it
@@ -9,7 +9,9 @@
9
9
  input: "<%= web_console.input_console_session_path(@console_session) %>",
10
10
  pendingOutput: "<%= web_console.pending_output_console_session_path(@console_session) %>",
11
11
  configuration: "<%= web_console.configuration_console_session_path(@console_session) %>"
12
- }
12
+ },
13
+
14
+ uid: "<%= @console_session.uid %>"
13
15
  }
14
16
  };
15
17
  </script>
@@ -5,9 +5,9 @@ module ActionDispatch
5
5
  def call(env)
6
6
  request = Request.new(env)
7
7
 
8
- if request.put? && m = env["PATH_INFO"].match(%r{/repl_sessions/(?<id>.+?)\z})
8
+ if request.put? && request.xhr? && m = env["PATH_INFO"].match(%r{/repl_sessions/(?<id>.+?)\z})
9
9
  update_repl_session(m[:id], request.params[:input])
10
- elsif request.post? && m = env["PATH_INFO"].match(%r{/repl_sessions/(?<id>.+?)/trace\z})
10
+ elsif request.post? && request.xhr? && m = env["PATH_INFO"].match(%r{/repl_sessions/(?<id>.+?)/trace\z})
11
11
  change_stack_trace(m[:id], request.params[:frame_id])
12
12
  else
13
13
  middleware_call(env)
@@ -52,8 +52,8 @@ module ActionDispatch
52
52
  traces = traces_from_wrapper(wrapper)
53
53
  extract_sources = wrapper.extract_sources
54
54
  console_session = WebConsole::REPLSession.create(
55
- binding: binding_from_exception(exception),
56
- binding_stack: exception.__web_console_bindings_stack
55
+ binding: exception.bindings.first,
56
+ binding_stack: exception.bindings
57
57
  )
58
58
  log_error(env, wrapper)
59
59
 
@@ -107,9 +107,5 @@ module ActionDispatch
107
107
  full_trace: application_trace + framework_trace
108
108
  }
109
109
  end
110
-
111
- def binding_from_exception(exception)
112
- exception.__web_console_bindings_stack[0]
113
- end
114
110
  end
115
111
  end
@@ -10,7 +10,7 @@ module ActionDispatch
10
10
  file: file,
11
11
  line_number: line_number
12
12
  }
13
- end
13
+ end if exception.backtrace
14
14
  end
15
15
  end
16
16
  end
@@ -36,11 +36,12 @@
36
36
  // Add CSS styles dynamically. This probably doesnt work for IE <8.
37
37
  var style = document.createElement('style');
38
38
  style.type = 'text/css';
39
- style.innerHTML = "#console { position: fixed; bottom: 0; width: 100%; height: 150px; border: 1px solid; padding-bottom: 20px; } " +
40
- "#console div.console-inner { height: 100%; overflow: auto; background: #333; padding: 10px; } " +
41
- "#console div.console-prompt-box { color: #fff; } " +
42
- "#console div.console-message { color: #1ad027; } " +
43
- "#console div.console-focus span.console-cursor { background:#fefefe; color:#333; font-weight:bold; }";
39
+ style.innerHTML =
40
+ "#console { position: fixed; left: 0; bottom: 0; width: 100%; height: 150px; border: 1px solid; padding-bottom: 20px; } " +
41
+ "#console div.console-inner { font-family: monospace; font-size: 11px; height: 100%; overflow: auto; background: #333; padding: 10px; } " +
42
+ "#console div.console-prompt-box { color: #FFF; } " +
43
+ "#console div.console-message { color: #1AD027; } " +
44
+ "#console div.console-focus span.console-cursor { background: #FEFEFE; color: #333; font-weight: bold; }";
44
45
  document.getElementsByTagName('head')[0].appendChild(style);
45
46
 
46
47
  /**
@@ -361,16 +362,16 @@
361
362
  var _this = this;
362
363
  var xhr = new XMLHttpRequest();
363
364
  var url = consoleDiv.dataset.remotePath;
364
- var params = "input=" + line;
365
+ var params = "input=" + encodeURIComponent(line);
365
366
 
366
367
  xhr.open("PUT", url, true);
367
- xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
368
+ xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
369
+ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
368
370
  xhr.send(params);
369
371
 
370
372
  xhr.onreadystatechange = function() {
371
373
  if(xhr.readyState == 4 && xhr.status == 200) {
372
374
  var response = JSON.parse(xhr.responseText);
373
- console.log(response.output);
374
375
  _this.writeOutput(response.output);
375
376
  }
376
377
  }
@@ -0,0 +1,16 @@
1
+ <tr class='route_row' data-helper='path'>
2
+ <td data-route-name='<%= route[:name] %>'>
3
+ <% if route[:name].present? %>
4
+ <%= route[:name] %><span class='helper'>_path</span>
5
+ <% end %>
6
+ </td>
7
+ <td data-route-verb='<%= route[:verb] %>'>
8
+ <%= route[:verb] %>
9
+ </td>
10
+ <td data-route-path='<%= route[:path] %>' data-regexp='<%= route[:regexp] %>'>
11
+ <%= route[:path] %>
12
+ </td>
13
+ <td data-route-reqs='<%= route[:reqs] %>'>
14
+ <%= route[:reqs] %>
15
+ </td>
16
+ </tr>
@@ -0,0 +1,200 @@
1
+ <% content_for :style do %>
2
+ #route_table {
3
+ margin: 0 auto 0;
4
+ border-collapse: collapse;
5
+ }
6
+
7
+ #route_table thead tr {
8
+ border-bottom: 2px solid #ddd;
9
+ }
10
+
11
+ #route_table thead tr.bottom {
12
+ border-bottom: none;
13
+ }
14
+
15
+ #route_table thead tr.bottom th {
16
+ padding: 10px 0;
17
+ line-height: 15px;
18
+ }
19
+
20
+ #route_table tbody tr {
21
+ border-bottom: 1px solid #ddd;
22
+ }
23
+
24
+ #route_table tbody tr:nth-child(odd) {
25
+ background: #f2f2f2;
26
+ }
27
+
28
+ #route_table tbody.exact_matches,
29
+ #route_table tbody.fuzzy_matches {
30
+ background-color: LightGoldenRodYellow;
31
+ border-bottom: solid 2px SlateGrey;
32
+ }
33
+
34
+ #route_table tbody.exact_matches tr,
35
+ #route_table tbody.fuzzy_matches tr {
36
+ background: none;
37
+ border-bottom: none;
38
+ }
39
+
40
+ #route_table td {
41
+ padding: 4px 30px;
42
+ }
43
+
44
+ #path_search {
45
+ width: 80%;
46
+ font-size: inherit;
47
+ }
48
+ <% end %>
49
+
50
+ <table id='route_table' class='route_table'>
51
+ <thead>
52
+ <tr>
53
+ <th>Helper</th>
54
+ <th>HTTP Verb</th>
55
+ <th>Path</th>
56
+ <th>Controller#Action</th>
57
+ </tr>
58
+ <tr class='bottom'>
59
+ <th><%# Helper %>
60
+ <%= link_to "Path", "#", 'data-route-helper' => '_path',
61
+ title: "Returns a relative path (without the http or domain)" %> /
62
+ <%= link_to "Url", "#", 'data-route-helper' => '_url',
63
+ title: "Returns an absolute url (with the http and domain)" %>
64
+ </th>
65
+ <th><%# HTTP Verb %>
66
+ </th>
67
+ <th><%# Path %>
68
+ <%= search_field(:path, nil, id: 'search', placeholder: "Path Match") %>
69
+ </th>
70
+ <th><%# Controller#action %>
71
+ </th>
72
+ </tr>
73
+ </thead>
74
+ <tbody class='exact_matches' id='exact_matches'>
75
+ </tbody>
76
+ <tbody class='fuzzy_matches' id='fuzzy_matches'>
77
+ </tbody>
78
+ <tbody>
79
+ <%= yield %>
80
+ </tbody>
81
+ </table>
82
+
83
+ <script type='text/javascript'>
84
+ // Iterates each element through a function
85
+ function each(elems, func) {
86
+ if (!elems instanceof Array) { elems = [elems]; }
87
+ for (var i = 0, len = elems.length; i < len; i++) {
88
+ func(elems[i]);
89
+ }
90
+ }
91
+
92
+ // Sets innerHTML for an element
93
+ function setContent(elem, text) {
94
+ elem.innerHTML = text;
95
+ }
96
+
97
+ // Enables path search functionality
98
+ function setupMatchPaths() {
99
+ // Check if the user input (sanitized as a path) matches the regexp data attribute
100
+ function checkExactMatch(section, elem, value) {
101
+ var string = sanitizePath(value),
102
+ regexp = elem.getAttribute("data-regexp");
103
+
104
+ showMatch(string, regexp, section, elem);
105
+ }
106
+
107
+ // Check if the route path data attribute contains the user input
108
+ function checkFuzzyMatch(section, elem, value) {
109
+ var string = elem.getAttribute("data-route-path"),
110
+ regexp = value;
111
+
112
+ showMatch(string, regexp, section, elem);
113
+ }
114
+
115
+ // Display the parent <tr> element in the appropriate section when there's a match
116
+ function showMatch(string, regexp, section, elem) {
117
+ if(string.match(RegExp(regexp))) {
118
+ section.appendChild(elem.parentNode.cloneNode(true));
119
+ }
120
+ }
121
+
122
+ // Check if there are any matched results in a section
123
+ function checkNoMatch(section, defaultText, noMatchText) {
124
+ if (section.innerHTML === defaultText) {
125
+ setContent(section, defaultText + noMatchText);
126
+ }
127
+ }
128
+
129
+ // Ensure path always starts with a slash "/" and remove params or fragments
130
+ function sanitizePath(path) {
131
+ var path = path.charAt(0) == '/' ? path : "/" + path;
132
+ return path.replace(/\#.*|\?.*/, '');
133
+ }
134
+
135
+ var regexpElems = document.querySelectorAll('#route_table [data-regexp]'),
136
+ searchElem = document.querySelector('#search'),
137
+ exactMatches = document.querySelector('#exact_matches'),
138
+ fuzzyMatches = document.querySelector('#fuzzy_matches');
139
+
140
+ // Remove matches when no search value is present
141
+ searchElem.onblur = function(e) {
142
+ if (searchElem.value === "") {
143
+ setContent(exactMatches, "");
144
+ setContent(fuzzyMatches, "");
145
+ }
146
+ }
147
+
148
+ // On key press perform a search for matching paths
149
+ searchElem.onkeyup = function(e){
150
+ var userInput = searchElem.value,
151
+ defaultExactMatch = '<tr><th colspan="4">Paths Matching (' + escape(sanitizePath(userInput)) +'):</th></tr>',
152
+ defaultFuzzyMatch = '<tr><th colspan="4">Paths Containing (' + escape(userInput) +'):</th></tr>',
153
+ noExactMatch = '<tr><th colspan="4">No Exact Matches Found</th></tr>',
154
+ noFuzzyMatch = '<tr><th colspan="4">No Fuzzy Matches Found</th></tr>';
155
+
156
+ // Clear out results section
157
+ setContent(exactMatches, defaultExactMatch);
158
+ setContent(fuzzyMatches, defaultFuzzyMatch);
159
+
160
+ // Display exact matches and fuzzy matches
161
+ each(regexpElems, function(elem) {
162
+ checkExactMatch(exactMatches, elem, userInput);
163
+ checkFuzzyMatch(fuzzyMatches, elem, userInput);
164
+ })
165
+
166
+ // Display 'No Matches' message when no matches are found
167
+ checkNoMatch(exactMatches, defaultExactMatch, noExactMatch);
168
+ checkNoMatch(fuzzyMatches, defaultFuzzyMatch, noFuzzyMatch);
169
+ }
170
+ }
171
+
172
+ // Enables functionality to toggle between `_path` and `_url` helper suffixes
173
+ function setupRouteToggleHelperLinks() {
174
+
175
+ // Sets content for each element
176
+ function setValOn(elems, val) {
177
+ each(elems, function(elem) {
178
+ setContent(elem, val);
179
+ });
180
+ }
181
+
182
+ // Sets onClick event for each element
183
+ function onClick(elems, func) {
184
+ each(elems, function(elem) {
185
+ elem.onclick = func;
186
+ });
187
+ }
188
+
189
+ var toggleLinks = document.querySelectorAll('#route_table [data-route-helper]');
190
+ onClick(toggleLinks, function(){
191
+ var helperTxt = this.getAttribute("data-route-helper"),
192
+ helperElems = document.querySelectorAll('[data-route-name] span.helper');
193
+
194
+ setValOn(helperElems, helperTxt);
195
+ });
196
+ }
197
+
198
+ setupMatchPaths();
199
+ setupRouteToggleHelperLinks();
200
+ </script>