docdown 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +38 -0
- data/README.md +126 -0
- data/Rakefile +16 -0
- data/bin/docdown +47 -0
- data/docdown.gemspec +28 -0
- data/lib/docdown.rb +37 -0
- data/lib/docdown/code_command.rb +37 -0
- data/lib/docdown/code_commands/bash.rb +23 -0
- data/lib/docdown/code_commands/no_such_command.rb +6 -0
- data/lib/docdown/code_commands/repl.rb +38 -0
- data/lib/docdown/code_commands/write.rb +27 -0
- data/lib/docdown/parser.rb +138 -0
- data/lib/docdown/version.rb +3 -0
- data/test/docdown/parser_test.rb +104 -0
- data/test/docdown/regex_test.rb +200 -0
- data/test/docdown/test_parse_java.rb +8 -0
- data/test/fixtures/README.md +905 -0
- data/test/fixtures/docdown.rb +8 -0
- data/test/fixtures/java_websockets.md +225 -0
- data/test/test_helper.rb +15 -0
- data/tmp.file +0 -0
- metadata +131 -0
@@ -0,0 +1,8 @@
|
|
1
|
+
puts "========================"
|
2
|
+
|
3
|
+
ReplRunner.register_commands(:play) do |config|
|
4
|
+
config.terminate_command "exit" # the command you use to end the 'rails console'
|
5
|
+
config.startup_timeout 60 # seconds to boot
|
6
|
+
config.return_char "\n" # the character that submits the command
|
7
|
+
# config.sync_stdout "STDOUT.sync = true" # force REPL to not buffer standard out
|
8
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
This quickstart will get you going with a Java and Play Framework application that uses a WebSocket, deployed to Heroku. For general information on how to develop and architect apps for use on Heroku, see [Architecting Applications for Heroku](https://devcenter.heroku.com/articles/architecting-apps).
|
2
|
+
|
3
|
+
>note
|
4
|
+
> Sample code for the [demo application](https://github.com/heroku/play-ws-test) is available on GitHub. Edits and enhancements are welcome. Just fork the repository, make your changes and send us a pull request.
|
5
|
+
|
6
|
+
## Prerequisites
|
7
|
+
|
8
|
+
* Java, Play Framework 2.x, Git, and the Heroku client (as described in the [basic Java quickstart](java))
|
9
|
+
* A Heroku user account. [Signup is free and instant](https://api.heroku.com/signup/devcenter).
|
10
|
+
|
11
|
+
## Create a Play Framework Java app that uses a WebSocket
|
12
|
+
|
13
|
+
The sample application provides a simple example of using a WebSocket with Java and Play. You can clone the sample and follow along with the code as you read. If you'd rather write the app yourself you can add the sample code to a new Play app as you go.
|
14
|
+
|
15
|
+
### Option 1. Clone the sample app
|
16
|
+
|
17
|
+
If you want to get going more quickly you can just clone the sample app:
|
18
|
+
|
19
|
+
```term
|
20
|
+
$ git clone git@github.com:heroku/play-ws-test.git
|
21
|
+
Cloning into 'play-ws-test'...
|
22
|
+
remote: Counting objects: 31, done.
|
23
|
+
remote: Compressing objects: 100% (24/24), done.
|
24
|
+
remote: Total 31 (delta 0), reused 31 (delta 0)
|
25
|
+
Receiving objects: 100% (31/31), 38.33 KiB | 0 bytes/s, done.
|
26
|
+
Checking connectivity... done
|
27
|
+
```
|
28
|
+
|
29
|
+
### Option 2. Create a new Play app
|
30
|
+
|
31
|
+
```term
|
32
|
+
:::- $ play help
|
33
|
+
:::= repl play new play22test
|
34
|
+
mywebsocketapp
|
35
|
+
2
|
36
|
+
```
|
37
|
+
|
38
|
+
Choose an application name and Java as the language.
|
39
|
+
|
40
|
+
## The sample application
|
41
|
+
|
42
|
+
The sample application renders a simple web page that will open a WebSocket to the backend. The server will send a payload containing the time over the WebSocket once a second. That time will be displayed on the page.
|
43
|
+
|
44
|
+
There are 3 important pieces to the interaction that takes place here: a controller method that returns a WebSocket object, a JavaScript method that opens that WebSocket, and an Akka actor that sends the payload across that WebSocket every second. Let's explore each.
|
45
|
+
|
46
|
+
### Returning a WebSocket from a controller method
|
47
|
+
|
48
|
+
You can [return a WebSocket](http://www.playframework.com/documentation/2.2.x/JavaWebSockets) from a Play controller method.
|
49
|
+
|
50
|
+
There is an example in `Application.java` in the sample application:
|
51
|
+
|
52
|
+
```java
|
53
|
+
:::= write play22test/app/controllers/Application.java
|
54
|
+
package controllers;
|
55
|
+
|
56
|
+
import static java.util.concurrent.TimeUnit.SECONDS;
|
57
|
+
import models.Pinger;
|
58
|
+
import play.libs.Akka;
|
59
|
+
import play.libs.F.Callback0;
|
60
|
+
import play.mvc.Controller;
|
61
|
+
import play.mvc.Result;
|
62
|
+
import play.mvc.WebSocket;
|
63
|
+
import scala.concurrent.duration.Duration;
|
64
|
+
import views.html.index;
|
65
|
+
import akka.actor.ActorRef;
|
66
|
+
import akka.actor.Cancellable;
|
67
|
+
import akka.actor.Props;
|
68
|
+
|
69
|
+
public class Application extends Controller {
|
70
|
+
public static WebSocket<String> pingWs() {
|
71
|
+
return new WebSocket<String>() {
|
72
|
+
public void onReady(WebSocket.In<String> in, WebSocket.Out<String> out) {
|
73
|
+
final ActorRef pingActor = Akka.system().actorOf(Props.create(Pinger.class, in, out));
|
74
|
+
final Cancellable cancellable = Akka.system().scheduler().schedule(Duration.create(1, SECONDS),
|
75
|
+
Duration.create(1, SECONDS),
|
76
|
+
pingActor,
|
77
|
+
"Tick",
|
78
|
+
Akka.system().dispatcher(),
|
79
|
+
null
|
80
|
+
);
|
81
|
+
|
82
|
+
in.onClose(new Callback0() {
|
83
|
+
@Override
|
84
|
+
public void invoke() throws Throwable {
|
85
|
+
cancellable.cancel();
|
86
|
+
}
|
87
|
+
});
|
88
|
+
}
|
89
|
+
|
90
|
+
};
|
91
|
+
}
|
92
|
+
|
93
|
+
public static Result pingJs() {
|
94
|
+
return ok(views.js.ping.render());
|
95
|
+
}
|
96
|
+
|
97
|
+
public static Result index() {
|
98
|
+
return ok(index.render());
|
99
|
+
}
|
100
|
+
}
|
101
|
+
```
|
102
|
+
|
103
|
+
This method returns a new [WebSocket](http://www.playframework.com/documentation/2.0/api/java/play/mvc/WebSocket.html) object that has a String as its payload. In the WebSocket object we define the onReady method to talk to an actor via the Akka scheduler. The work of sending data over the socket will occur in that actor.
|
104
|
+
|
105
|
+
The other methods will render our `js` and `html` templates.
|
106
|
+
|
107
|
+
|
108
|
+
We'll also need a route to be set up for these methods in our `routes` file:
|
109
|
+
|
110
|
+
```
|
111
|
+
:::= write play22test/conf/routes
|
112
|
+
# Home page
|
113
|
+
GET / controllers.Application.index()
|
114
|
+
GET /pingWs controllers.Application.pingWs()
|
115
|
+
GET /assets/javascripts/ping.js controllers.Application.pingJs()
|
116
|
+
|
117
|
+
# Map static resources from the /public folder to the /assets URL path
|
118
|
+
GET /assets/*file controllers.Assets.at(path="/public", file)
|
119
|
+
```
|
120
|
+
|
121
|
+
### Sending data over a WebSocket
|
122
|
+
|
123
|
+
In the controller example you'll notice that we pass around the `in` and `out` streams of the WebSocket. In our actor we're able to read from and write to these streams just like any other IO stream. Here's the code for the `Pinger` actor:
|
124
|
+
|
125
|
+
```java
|
126
|
+
:::= write play22test/app/models/Pinger.java
|
127
|
+
package models;
|
128
|
+
|
129
|
+
import play.*;
|
130
|
+
import play.mvc.*;
|
131
|
+
import play.libs.*;
|
132
|
+
|
133
|
+
import scala.concurrent.duration.Duration;
|
134
|
+
import java.util.concurrent.TimeUnit;
|
135
|
+
import akka.actor.UntypedActor;
|
136
|
+
import java.util.Calendar;
|
137
|
+
import java.text.SimpleDateFormat;
|
138
|
+
|
139
|
+
public class Pinger extends UntypedActor {
|
140
|
+
WebSocket.In<String> in;
|
141
|
+
WebSocket.Out<String> out;
|
142
|
+
|
143
|
+
public Pinger(WebSocket.In<String> in, WebSocket.Out<String> out) {
|
144
|
+
this.in = in;
|
145
|
+
this.out = out;
|
146
|
+
}
|
147
|
+
|
148
|
+
@Override
|
149
|
+
public void onReceive(Object message) {
|
150
|
+
if (message.equals("Tick")) {
|
151
|
+
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
152
|
+
Calendar cal = Calendar.getInstance();
|
153
|
+
out.write(sdf.format(cal.getTime()));
|
154
|
+
} else {
|
155
|
+
unhandled(message);
|
156
|
+
}
|
157
|
+
}
|
158
|
+
}
|
159
|
+
```
|
160
|
+
|
161
|
+
You'll notice that this actor counts on the schedule defined in the controller method to send it a "Tick" message every second. When that happens it sends the current date and time over the WebSocket.
|
162
|
+
|
163
|
+
### Connecting to a WebSocket
|
164
|
+
|
165
|
+
The final piece is the client code that will call the WebSocket. For this our sample application uses Scala js and HTML templates called `ping.scala.js` and `index.scala.js` respectively.
|
166
|
+
|
167
|
+
`index.scala.js` provides a `div` to display the data in and references the JavaScript:
|
168
|
+
|
169
|
+
```java
|
170
|
+
:::= write play22test/app/views/index.scala.html
|
171
|
+
@main("Welcome to Play") {
|
172
|
+
|
173
|
+
<strong>Stats</strong><br>
|
174
|
+
<div id="ping"></div>
|
175
|
+
|
176
|
+
<script type="text/javascript" charset="utf-8" src="@routes.Application.pingJs()"></script>
|
177
|
+
}
|
178
|
+
```
|
179
|
+
|
180
|
+
`ping.scala.js` connects to our WebSocket and defines the `receiveEvent` method to populate the dates into the displayed `div` as they come across:
|
181
|
+
|
182
|
+
```javascript
|
183
|
+
:::= write play22test/app/views/ping.scala.js
|
184
|
+
$(function() {
|
185
|
+
var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket
|
186
|
+
var dateSocket = new WS("@routes.Application.pingWs().webSocketURL(request)")
|
187
|
+
|
188
|
+
var receiveEvent = function(event) {
|
189
|
+
$("#ping").html("Last ping: "+event.data);
|
190
|
+
}
|
191
|
+
|
192
|
+
dateSocket.onmessage = receiveEvent
|
193
|
+
})
|
194
|
+
```
|
195
|
+
|
196
|
+
## Deploy the application to Heroku
|
197
|
+
|
198
|
+
### Store your app in Git
|
199
|
+
|
200
|
+
If you haven't done so already put your application into a git repository:
|
201
|
+
|
202
|
+
```term
|
203
|
+
::: $ cd play22test && git init
|
204
|
+
::: $ cd play22test && git add .
|
205
|
+
::: $ cd play22test && git commit -m "Ready to deploy"
|
206
|
+
|
207
|
+
```
|
208
|
+
|
209
|
+
### Create the app
|
210
|
+
|
211
|
+
```term
|
212
|
+
:::= $ cd play22test && heroku create
|
213
|
+
```
|
214
|
+
|
215
|
+
### Deploy your code
|
216
|
+
|
217
|
+
```term
|
218
|
+
:::= $ cd play22test && git push heroku master
|
219
|
+
:::- $ cd play22test && heroku labs:enable websockets
|
220
|
+
:::- $ cd play22test && heroku restart
|
221
|
+
```
|
222
|
+
|
223
|
+
Congratulations! Your web app should now be up and running on Heroku.
|
224
|
+
|
225
|
+
|
data/test/test_helper.rb
ADDED
data/tmp.file
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: docdown
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Richard Schneeman
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-10-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: repl_runner
|
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'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mocha
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: docdown turns docs to runable code
|
70
|
+
email:
|
71
|
+
- richard.schneeman+rubygems@gmail.com
|
72
|
+
executables:
|
73
|
+
- docdown
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- .gitignore
|
78
|
+
- Gemfile
|
79
|
+
- Gemfile.lock
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- bin/docdown
|
83
|
+
- docdown.gemspec
|
84
|
+
- lib/docdown.rb
|
85
|
+
- lib/docdown/code_command.rb
|
86
|
+
- lib/docdown/code_commands/bash.rb
|
87
|
+
- lib/docdown/code_commands/no_such_command.rb
|
88
|
+
- lib/docdown/code_commands/repl.rb
|
89
|
+
- lib/docdown/code_commands/write.rb
|
90
|
+
- lib/docdown/parser.rb
|
91
|
+
- lib/docdown/version.rb
|
92
|
+
- test/docdown/parser_test.rb
|
93
|
+
- test/docdown/regex_test.rb
|
94
|
+
- test/docdown/test_parse_java.rb
|
95
|
+
- test/fixtures/README.md
|
96
|
+
- test/fixtures/docdown.rb
|
97
|
+
- test/fixtures/java_websockets.md
|
98
|
+
- test/test_helper.rb
|
99
|
+
- tmp.file
|
100
|
+
homepage: https://github.com/schneems/docdown
|
101
|
+
licenses:
|
102
|
+
- MIT
|
103
|
+
metadata: {}
|
104
|
+
post_install_message:
|
105
|
+
rdoc_options: []
|
106
|
+
require_paths:
|
107
|
+
- lib
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
requirements: []
|
119
|
+
rubyforge_project:
|
120
|
+
rubygems_version: 2.0.3
|
121
|
+
signing_key:
|
122
|
+
specification_version: 4
|
123
|
+
summary: docdown generates runable code from docs
|
124
|
+
test_files:
|
125
|
+
- test/docdown/parser_test.rb
|
126
|
+
- test/docdown/regex_test.rb
|
127
|
+
- test/docdown/test_parse_java.rb
|
128
|
+
- test/fixtures/README.md
|
129
|
+
- test/fixtures/docdown.rb
|
130
|
+
- test/fixtures/java_websockets.md
|
131
|
+
- test/test_helper.rb
|