-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.html
240 lines (182 loc) · 15.6 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link href='https://fonts.googleapis.com/css?family=Architects+Daughter' rel='stylesheet' type='text/css'>
<link rel="stylesheet" type="text/css" href="stylesheets/stylesheet.css" media="screen" />
<link rel="stylesheet" type="text/css" href="stylesheets/pygment_trac.css" media="screen" />
<link rel="stylesheet" type="text/css" href="stylesheets/print.css" media="print" />
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<title>websocket-rails by DanKnox</title>
</head>
<body>
<header>
<div class="inner">
<h1>websocket-rails</h1>
<h2>Plug and play WebSocket support for ruby on rails.</h2>
<a href="https://github.com/websocket-rails/websocket-rails" class="button"><small>View project on</small>GitHub</a>
</div>
</header>
<div id="content-wrapper">
<div class="inner clearfix">
<section id="main-content">
<h1>Websocket-Rails</h1>
<p><a href="https://travis-ci.org/websocket-rails/websocket-rails"><img src="https://travis-ci.org/websocket-rails/websocket-rails.png?branch=master" alt="Build Status"></a></p>
<p><strong>Now with streaming HTTP support for improved browser compatibility</strong></p>
<h2>The Present</h2>
<p>Start treating client side events as first class citizens inside your Rails application with a built in WebSocket server. Sure, WebSockets aren't quite universal yet. That's why we also support streaming HTTP. Oh, and if you don't mind running a separate process, you can support just about any browser through Flash sockets without changing a line of code.</p>
<h2>The Future</h2>
<p>The long term goal for this project is simple. Reduce the need to move application logic on to the client while still providing the same level of interaction and responsiveness users have grown to expect from a modern web application. We hope to isolate the responsibility of JavaScript to the presentation layer and keep business logic nicely organized on the server.</p>
<h2>Installation and Usage Guides</h2>
<ul>
<li><a href="https://github.com/websocket-rails/websocket-rails/wiki/Installation-and-Setup">Installation
Guide</a></li>
<li><a href="https://github.com/websocket-rails/websocket-rails/wiki/The-Event-Router">Event
Router</a></li>
<li><a href="https://github.com/websocket-rails/websocket-rails/wiki/WebsocketRails%20Controllers">WebsocketRails Controllers</a></li>
<li><a href="https://github.com/websocket-rails/websocket-rails/wiki/Using-the-JavaScript-Client">Using the JavaScript
Client</a></li>
<li><a href="https://github.com/websocket-rails/websocket-rails/wiki/Working-with-Channels">Using
Channels</a></li>
<li><a href="https://github.com/websocket-rails/websocket-rails/wiki/Using-the-DataStore">The
DataStore</a></li>
<li><a href="https://github.com/websocket-rails/websocket-rails/wiki/Multiple-Servers-and-Background-Jobs">Multiple Servers and Background Jobs</a></li>
<li><a href="https://github.com/websocket-rails/websocket-rails/wiki/Standalone-Server-Mode">Standalone Server Mode</a></li>
</ul><h2>A Brief Tour</h2>
<p>Map events to controller actions using an Event Router.</p>
<div class="highlight"><pre><span class="no">WebsocketRails</span><span class="o">::</span><span class="no">EventMap</span><span class="o">.</span><span class="n">describe</span> <span class="k">do</span>
<span class="n">namespace</span> <span class="ss">:tasks</span> <span class="k">do</span>
<span class="n">subscribe</span> <span class="ss">:create</span><span class="p">,</span> <span class="ss">:to</span> <span class="o">=></span> <span class="no">TaskController</span><span class="p">,</span> <span class="ss">:with_method</span> <span class="o">=></span> <span class="ss">:create</span>
<span class="k">end</span>
<span class="k">end</span>
</pre></div>
<p>Trigger events using our JavaScript client.</p>
<div class="highlight"><pre><span class="kd">var</span> <span class="nx">task</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">name</span><span class="o">:</span> <span class="s1">'Start taking advantage of WebSockets'</span><span class="p">,</span>
<span class="nx">completed</span><span class="o">:</span> <span class="kc">false</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">dispatcher</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">WebSocketRails</span><span class="p">(</span><span class="s1">'localhost:3000/websocket'</span><span class="p">);</span>
<span class="nx">dispatcher</span><span class="p">.</span><span class="nx">trigger</span><span class="p">(</span><span class="s1">'tasks.create'</span><span class="p">,</span> <span class="nx">task</span><span class="p">);</span>
</pre></div>
<p>Handle events in your controller.</p>
<div class="highlight"><pre><span class="k">class</span> <span class="nc">TaskController</span> <span class="o"><</span> <span class="no">WebsocketRails</span><span class="o">::</span><span class="no">BaseController</span>
<span class="k">def</span> <span class="nf">create</span>
<span class="c1"># The `message` method contains the data received</span>
<span class="n">task</span> <span class="o">=</span> <span class="no">Task</span><span class="o">.</span><span class="n">new</span> <span class="n">message</span>
<span class="k">if</span> <span class="n">task</span><span class="o">.</span><span class="n">save</span>
<span class="n">send_message</span> <span class="ss">:create_success</span><span class="p">,</span> <span class="n">task</span><span class="p">,</span> <span class="ss">:namespace</span> <span class="o">=></span> <span class="ss">:tasks</span>
<span class="k">else</span>
<span class="n">send_message</span> <span class="ss">:create_fail</span><span class="p">,</span> <span class="n">task</span><span class="p">,</span> <span class="ss">:namespace</span> <span class="o">=></span> <span class="ss">:tasks</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</pre></div>
<p>Receive the response in the client.</p>
<div class="highlight"><pre><span class="nx">dispatcher</span><span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="s1">'tasks.create_success'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">task</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">'successfully created '</span> <span class="o">+</span> <span class="nx">task</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
<span class="p">});</span>
</pre></div>
<p>Or just attach success and failure callbacks to your client events.</p>
<div class="highlight"><pre><span class="kd">var</span> <span class="nx">success</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">task</span><span class="p">)</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Created: "</span> <span class="o">+</span> <span class="nx">task</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span> <span class="p">}</span>
<span class="kd">var</span> <span class="nx">failure</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">task</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Failed to create Product: "</span> <span class="o">+</span> <span class="nx">product</span><span class="p">.</span><span class="nx">name</span><span class="p">)</span>
<span class="p">}</span>
<span class="nx">dispatcher</span><span class="p">.</span><span class="nx">trigger</span><span class="p">(</span><span class="s1">'products.create'</span><span class="p">,</span> <span class="nx">success</span><span class="p">,</span> <span class="nx">failure</span><span class="p">);</span>
</pre></div>
<p>Then trigger them in your controller:</p>
<div class="highlight"><pre><span class="k">def</span> <span class="nf">create</span>
<span class="n">task</span> <span class="o">=</span> <span class="no">Task</span><span class="o">.</span><span class="n">create</span> <span class="n">message</span>
<span class="k">if</span> <span class="n">task</span><span class="o">.</span><span class="n">save</span>
<span class="n">trigger_success</span> <span class="n">task</span>
<span class="k">else</span>
<span class="n">trigger_failure</span> <span class="n">task</span>
<span class="k">end</span>
<span class="k">end</span>
</pre></div>
<p>If you're feeling truly lazy, just trigger the failure callback with an
exception.</p>
<div class="highlight"><pre><span class="k">def</span> <span class="nf">create</span>
<span class="n">task</span> <span class="o">=</span> <span class="no">Task</span><span class="o">.</span><span class="n">create!</span> <span class="n">message</span>
<span class="n">trigger_success</span> <span class="n">task</span> <span class="c1"># trigger success if the save went alright</span>
<span class="k">end</span>
</pre></div>
<p>That controller is starting to look pretty clean.</p>
<p>Now in the failure callback on the client we have access to the record
and the errors.</p>
<div class="highlight"><pre><span class="kd">var</span> <span class="nx">failureCallback</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">task</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span> <span class="nx">task</span><span class="p">.</span><span class="nx">name</span> <span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span> <span class="nx">task</span><span class="p">.</span><span class="nx">errors</span> <span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span> <span class="s2">"You have "</span> <span class="o">+</span> <span class="nx">task</span><span class="p">.</span><span class="nx">errors</span><span class="p">.</span><span class="nx">length</span> <span class="o">+</span> <span class="s2">" errors."</span> <span class="p">);</span>
<span class="p">}</span>
</pre></div>
<h2>Channel Support</h2>
<p>Keep your users up to date without waiting for them to refresh the page.
Subscribe them to a channel and update it from wherever you please.</p>
<p>Tune in on the client side.</p>
<div class="highlight"><pre><span class="nx">channel</span> <span class="o">=</span> <span class="nx">dispatcher</span><span class="p">.</span><span class="nx">subscribe</span><span class="p">(</span><span class="s1">'posts'</span><span class="p">);</span>
<span class="nx">channel</span><span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="s1">'new'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">post</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">'a new post about '</span><span class="o">+</span><span class="nx">post</span><span class="p">.</span><span class="nx">title</span><span class="o">+</span><span class="s1">' arrived!'</span><span class="p">);</span>
<span class="p">});</span>
</pre></div>
<p>Broadcast to the channel from anywhere inside your Rails application. An
existing controller, a model, a background job, or a new WebsocketRails
controller.</p>
<div class="highlight"><pre><span class="n">latest_post</span> <span class="o">=</span> <span class="no">Post</span><span class="o">.</span><span class="n">latest</span>
<span class="no">WebsocketRails</span><span class="o">[</span><span class="ss">:posts</span><span class="o">].</span><span class="n">trigger</span> <span class="s1">'new'</span><span class="p">,</span> <span class="n">latest_post</span>
</pre></div>
<h2>Private Channel Support</h2>
<p>Need to restrict access to a particular channel? No problem. We've got
that. </p>
<p>Private channels give you the ability to authorize a user's
subscription using the authorization mechanism of your choice.</p>
<p>Just tell WebsocketRails which channels you would like to make private and how you want to handle channel authorization in the
event router by subscribing to the <code>websocket_rails.subscribe_private</code>
event.</p>
<div class="highlight"><pre><span class="no">WebsocketRails</span><span class="o">::</span><span class="no">EventMap</span><span class="o">.</span><span class="n">describe</span> <span class="k">do</span>
<span class="n">private_channel</span> <span class="ss">:secret_posts</span>
<span class="n">namespace</span> <span class="ss">:websocket_rails</span>
<span class="n">subscribe</span> <span class="ss">:subscribe_private</span><span class="p">,</span> <span class="ss">:to</span> <span class="o">=></span> <span class="no">AuthenticationController</span><span class="p">,</span> <span class="ss">:with_method</span> <span class="o">=></span> <span class="ss">:authorize_channels</span>
<span class="k">end</span>
</pre></div>
<p>Or you can always mark any channel as private later on.</p>
<div class="highlight"><pre><span class="no">WebsocketRails</span><span class="o">[</span><span class="ss">:secret_posts</span><span class="o">].</span><span class="n">make_private</span>
</pre></div>
<p>On the client side, you can use the <code>dispatcher.subscribe_private()</code>
method to subscribe to a private channel.</p>
<p>Read the <a href="https://github.com/websocket-rails/websocket-rails/wiki/Using-Private-Channels">Private Channel Wiki</a> for more information on dealing with
private channels.</p>
<h2>Development</h2>
<p>This gem is created and maintained by Dan Knox and Kyle Whalen under the MIT License.</p>
<p>Brought to you by:</p>
<p>Three Dot Loft LLC</p>
</section>
<aside id="sidebar">
<a href="https://github.com/websocket-rails/websocket-rails/zipball/master" class="button">
<small>Download</small>
.zip file
</a>
<a href="https://github.com/websocket-rails/websocket-rails/tarball/master" class="button">
<small>Download</small>
.tar.gz file
</a>
<p class="repo-owner"><a href="https://github.com/websocket-rails/websocket-rails"></a> is maintained by <a href="https://github.com/DanKnox">DanKnox</a>.</p>
<p>This page was generated by <a href="pages.github.com">GitHub Pages</a> using the Architect theme by <a href="http://twitter.com/jasonlong">Jason Long</a>.</p>
</aside>
</div>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-27751069-2");
pageTracker._trackPageview();
} catch(err) {}
</script>
</body>
</html>