padrino-websockets 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 29fa2c66e13018259a69e4c31ae06bd65c6e636b
4
+ data.tar.gz: 65df06207d203791552bf15743e380a7236dd110
5
+ SHA512:
6
+ metadata.gz: ad15ee0928289ec7ddb10c7d2f079ef42de8d43ac2935d8855d9e52c0e539d5ce31b4538037892020d1861a4c9c625e6778249211ba7199017c208fdcb5a978c
7
+ data.tar.gz: 7846d58a63850da913458687f0d2535d529d83b57ca39a986df9a5ed4325c4cd2549fcdf9d1cdef9080c4d878bd3c3c1ef6d5460741671dabae3ad663e032fa4
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in padrino-websockets.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Darío Javier Cravero (dario@uxtemple.com)
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # Padrino Websockets
2
+
3
+ A WebSockets abstraction for the Padrino Ruby Web Framework to manage
4
+ channels, users and events regardless of the underlying WebSockets implementation.
5
+
6
+ ## Current support
7
+
8
+ The current version supports [SpiderGazelle](https://github.com/cotag/spider-gazelle) as its
9
+ backend working with LibUV.
10
+
11
+ Feel free to implement your own backend using, say, EventMachine and submit it! :)
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's `Gemfile`:
16
+
17
+ ```
18
+ # It only works with SpiderGazelle for now, so this dependency is a must at the moment.
19
+ gem 'spider-gazelle', github: 'cotag/spider-gazelle'
20
+ gem 'uv-rays', github: 'cotag/uv-rays'
21
+
22
+ gem 'padrino-websockets'
23
+ ```
24
+
25
+ And then execute:
26
+
27
+ ```
28
+ $ bundle
29
+ ```
30
+
31
+ Or install it yourself as:
32
+
33
+ ```
34
+ $ gem install padrino-websockets
35
+ ```
36
+
37
+ ## Usage
38
+
39
+ Add this line to your main application's file (`app/app.rb`):
40
+
41
+ ```
42
+ register Padrino::WebSockets
43
+ ```
44
+
45
+ Then in any controller or in the app itself, define a WebSocket channel:
46
+
47
+ ```
48
+ websocket :channel do
49
+ event :ping do |context, message|
50
+ send_message({pong: true, data: message})
51
+ end
52
+ end
53
+ ```
54
+
55
+ How to use it on a browser?
56
+
57
+ ```
58
+ var connection = new WebSocket('ws://localhost:3000/channel');
59
+
60
+ connection.onopen = function(message) {
61
+ console.log('connected to channel');
62
+ connection.send(JSON.stringify({event: 'ping', some: 'data'}));
63
+ }
64
+
65
+ connection.onmessage = function(message) {
66
+ console.log('message', JSON.parse(message.data));
67
+ }
68
+
69
+ // TODO Implement on the backend
70
+ connection.onerror = function(message) {
71
+ console.error('channel', JSON.parse(message.data));
72
+ }
73
+
74
+ ```
75
+
76
+ ## Contributing
77
+
78
+ 1. Fork it ( http://github.com/<my-github-username>/padrino-websockets/fork )
79
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
80
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
81
+ 4. Push to the branch (`git push origin my-new-feature`)
82
+ 5. Create new Pull Request
83
+
84
+
85
+ ## Contributors
86
+
87
+ Made with <3 by @dariocravero at [UXtemple](http://uxtemple.com).
88
+
89
+ Heavily inspired by @stakach's [example](https://github.com/cotag/spider-gazelle/issues/4).
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,9 @@
1
+ ---
2
+ :orm: none
3
+ :test: none
4
+ :mock: none
5
+ :script: none
6
+ :renderer: slim
7
+ :stylesheet: none
8
+ :namespace: PadrinoWebsocketsDemo
9
+ :migration_format: number
@@ -0,0 +1,9 @@
1
+ .DS_Store
2
+ log/**/*
3
+ tmp/**/*
4
+ bin/*
5
+ vendor/gems/*
6
+ !vendor/gems/cache/
7
+ .sass-cache/*
8
+ db/*.db
9
+ .*.sw*
@@ -0,0 +1,34 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Distribute your app as a gem
4
+ # gemspec
5
+
6
+ # Server requirements
7
+ # gem 'thin' # or mongrel
8
+ # gem 'trinidad', :platform => 'jruby'
9
+ gem 'spider-gazelle', github: 'cotag/spider-gazelle'
10
+
11
+ # Optional JSON codec (faster performance)
12
+ gem 'oj'
13
+
14
+ # Project requirements
15
+ gem 'rake'
16
+ gem 'uv-rays', github: 'cotag/uv-rays'
17
+ gem 'padrino-websockets', path: '../..'
18
+ # gem 'padrino-websockets', github: 'dariocravero/padrino-websockets'
19
+
20
+ # Component requirements
21
+ gem 'slim'
22
+
23
+ # Test requirements
24
+
25
+ # Padrino Stable Gem
26
+ # gem 'padrino', '0.12.0.rc3'
27
+
28
+ # Or Padrino Edge
29
+ gem 'padrino', :github => 'padrino/padrino-framework'
30
+
31
+ # Or Individual Gems
32
+ # %w(core gen helpers cache mailer admin).each do |g|
33
+ # gem 'padrino-' + g, '0.12.0.rc3'
34
+ # end
@@ -0,0 +1,4 @@
1
+ require 'bundler/setup'
2
+ require 'padrino-core/cli/rake'
3
+
4
+ PadrinoTasks.init
@@ -0,0 +1,19 @@
1
+ module PadrinoWebsocketsDemo
2
+ class App < Padrino::Application
3
+ register Padrino::Rendering
4
+ register Padrino::WebSockets
5
+
6
+ enable :sessions
7
+
8
+ get :index do
9
+ render :index
10
+ end
11
+
12
+ websocket :channel do
13
+ event :test do |context, message|
14
+ "test on channel"
15
+ send_message message
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ h1 Padrino WebSockets demo
2
+
3
+ p Watch out your developer's console. There's a <strong>connection</strong> variable ready to use.
4
+
5
+ javascript:
6
+ !function(window) {
7
+ 'use strict';
8
+
9
+ window.connection = new WebSocket('ws://localhost:3000/channel');
10
+
11
+ connection.onopen = function(message) {
12
+ console.log('connected to channel');
13
+ connection.send(JSON.stringify({event: 'test', some: 'data'}));
14
+ }
15
+
16
+ connection.onmessage = function(message) {
17
+ console.log('message', JSON.parse(message.data));
18
+ }
19
+ }(window);
@@ -0,0 +1,36 @@
1
+ ##
2
+ # This file mounts each app in the Padrino project to a specified sub-uri.
3
+ # You can mount additional applications using any of these commands below:
4
+ #
5
+ # Padrino.mount('blog').to('/blog')
6
+ # Padrino.mount('blog', :app_class => 'BlogApp').to('/blog')
7
+ # Padrino.mount('blog', :app_file => 'path/to/blog/app.rb').to('/blog')
8
+ #
9
+ # You can also map apps to a specified host:
10
+ #
11
+ # Padrino.mount('Admin').host('admin.example.org')
12
+ # Padrino.mount('WebSite').host(/.*\.?example.org/)
13
+ # Padrino.mount('Foo').to('/foo').host('bar.example.org')
14
+ #
15
+ # Note 1: Mounted apps (by default) should be placed into the project root at '/app_name'.
16
+ # Note 2: If you use the host matching remember to respect the order of the rules.
17
+ #
18
+ # By default, this file mounts the primary app which was generated with this project.
19
+ # However, the mounted app can be modified as needed:
20
+ #
21
+ # Padrino.mount('AppName', :app_file => 'path/to/file', :app_class => 'BlogApp').to('/')
22
+ #
23
+
24
+ ##
25
+ # Setup global project settings for your apps. These settings are inherited by every subapp. You can
26
+ # override these settings in the subapps as needed.
27
+ #
28
+ Padrino.configure_apps do
29
+ # enable :sessions
30
+ set :session_secret, '439d7a65623d358416f31a49fadefb9f449b6c5f472c887166c04365f2fe6534'
31
+ set :protection, :except => :path_traversal
32
+ set :protect_from_csrf, true
33
+ end
34
+
35
+ # Mounts the core application for this project
36
+ Padrino.mount('PadrinoWebsocketsDemo::App', :app_file => Padrino.root('app/app.rb')).to('/')
@@ -0,0 +1,46 @@
1
+ # Defines our constants
2
+ RACK_ENV = ENV['RACK_ENV'] ||= 'development' unless defined?(RACK_ENV)
3
+ PADRINO_ROOT = File.expand_path('../..', __FILE__) unless defined?(PADRINO_ROOT)
4
+
5
+ # Load our dependencies
6
+ require 'rubygems' unless defined?(Gem)
7
+ require 'bundler/setup'
8
+ Bundler.require(:default, RACK_ENV)
9
+
10
+ ##
11
+ # ## Enable devel logging
12
+ #
13
+ # Padrino::Logger::Config[:development][:log_level] = :devel
14
+ # Padrino::Logger::Config[:development][:log_static] = true
15
+ #
16
+ # ## Configure your I18n
17
+ #
18
+ # I18n.default_locale = :en
19
+ # I18n.enforce_available_locales = false
20
+ #
21
+ # ## Configure your HTML5 data helpers
22
+ #
23
+ # Padrino::Helpers::TagHelpers::DATA_ATTRIBUTES.push(:dialog)
24
+ # text_field :foo, :dialog => true
25
+ # Generates: <input type="text" data-dialog="true" name="foo" />
26
+ #
27
+ # ## Add helpers to mailer
28
+ #
29
+ # Mail::Message.class_eval do
30
+ # include Padrino::Helpers::NumberHelpers
31
+ # include Padrino::Helpers::TranslationHelpers
32
+ # end
33
+
34
+ ##
35
+ # Add your before (RE)load hooks here
36
+ #
37
+ Padrino.before_load do
38
+ end
39
+
40
+ ##
41
+ # Add your after (RE)load hooks here
42
+ #
43
+ Padrino.after_load do
44
+ end
45
+
46
+ Padrino.load!
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rackup
2
+ # encoding: utf-8
3
+
4
+ # This file can be used to start Padrino,
5
+ # just execute it from the command line.
6
+
7
+ require File.expand_path("../config/boot.rb", __FILE__)
8
+
9
+ run Padrino.application
@@ -0,0 +1,187 @@
1
+ module Padrino
2
+ module WebSockets
3
+ class BaseEventManager
4
+ require 'oj'
5
+
6
+ ERRORS = {
7
+ parse_message: "Can't parse the WebSocket's message",
8
+ message_format: "Wrong message format. Expected: {event: 'ev', p1: 'p1', ...}",
9
+ unsupported_event: "The event you requested isn't supported",
10
+ runtime: "Error while running the event handler"
11
+ }
12
+
13
+ ##
14
+ # Creates a new WebSocket manager for a specific connection with a user on a channel.
15
+ #
16
+ # It will listen for specific events and run their blocks whenever a WebSocket call on
17
+ # that channel comes through.
18
+ #
19
+ # == Params
20
+ # * `channel`: The name of the channel
21
+ # * `user`: Unique string to ID the user. See the `set_websocket_user` helper.
22
+ # * `ws`: The WebSocket promise/reactor/etc - whatever keeps it alive for this user.
23
+ # * `event_context`: The Padrino application controller's context so that it can access the
24
+ # helpers, mailers, settings, etc. Making it a first-class citizen as a regular HTTP
25
+ # action is. TODO Review it though, it's probably wrong.
26
+ # * `&block`: A block with supported events to manage.
27
+ #
28
+ def initialize(channel, user, ws, event_context, &block)
29
+ @channel = channel
30
+ @user = user
31
+ @ws = ws
32
+ @@connections ||= {}
33
+ @@connections[@channel] ||= {}
34
+ @@connections[@channel][@user] = @ws
35
+
36
+ @events = {}
37
+
38
+ @event_context = event_context
39
+
40
+ instance_eval &block if block_given?
41
+ end
42
+
43
+ ##
44
+ # DSL for adding events from the events block
45
+ #
46
+ def event(name, &block)
47
+ @events[name.to_sym] = block if block_given?
48
+ end
49
+
50
+ ##
51
+ # Message receiver
52
+ #
53
+ def on_message(data, ws)
54
+ # TODO Detect external ws hijack and drop it
55
+ begin
56
+ # Parse the message
57
+ message = ::Oj.load data
58
+
59
+ # Check if we have well formed message, i.e., it includes at least an event name.
60
+ event = message.delete 'event'
61
+
62
+ if event.nil?
63
+ logger.error ERRORS[:message_format]
64
+ logger.error e.message
65
+ logger.error e.backtrace.join("\n")
66
+
67
+ return send_message({error: {
68
+ name: :message_format,
69
+ message: ERRORS[:message_format]
70
+ }})
71
+ end
72
+
73
+ event = event.to_sym
74
+
75
+ # Check if it's a valid event
76
+ unless @events.include?(event)
77
+ logger.error ERRORS[:unsupported_event]
78
+ logger.error e.message
79
+ logger.error e.backtrace.join("\n")
80
+
81
+ return send_message({error: {
82
+ name: :unsupported_event,
83
+ message: ERRORS[:unsupported_event],
84
+ event: event
85
+ }})
86
+ end
87
+
88
+ # Call it
89
+ # TODO Run the event in the context of the app
90
+ # @events[event].bind(@event_context).call
91
+ # TODO Make the params (message) available through the params variable as we do
92
+ # in normal actions.
93
+ logger.debug "Calling event: #{event} as user: #{@user} on channel #{@channel}."
94
+ logger.debug message.inspect
95
+ @events[event].call(@event_context, message)
96
+ rescue Oj::ParseError => e
97
+ logger.error ERRORS[:parse_message]
98
+ logger.error e.message
99
+ logger.error e.backtrace.join("\n")
100
+
101
+ send_message({error: {
102
+ name: :parse_message,
103
+ message: ERRORS[:parse_message]
104
+ }})
105
+ rescue => e
106
+ logger.error ERRORS[:runtime]
107
+ logger.error e.message
108
+ logger.error e.backtrace.join("\n")
109
+
110
+ send_message({error: {
111
+ name: :runtime,
112
+ message: ERRORS[:runtime],
113
+ event: event,
114
+ exception: {
115
+ message: e.message,
116
+ backtrace: e.backtrace
117
+ }
118
+ }})
119
+ end
120
+ end
121
+
122
+ ##
123
+ # Manage the WebSocket's connection being closed.
124
+ #
125
+ def on_shutdown
126
+ logger.debug "Disconnecting user: #{@user} from channel: #{@channel}."
127
+ @@connections[@channel].delete(@ws)
128
+ end
129
+
130
+ ##
131
+ # Broadcast a message to the whole channel
132
+ #
133
+ def broadcast(message, except=[])
134
+ self.class.broadcast @channel, message, except
135
+ end
136
+
137
+ ##
138
+ # Send a message to a user on the channel
139
+ #
140
+ def send_message(message, user=@user)
141
+ self.class.send_message @channel, user, message
142
+ end
143
+
144
+ class << self
145
+ ##
146
+ # Broadcast a message to the whole channel.
147
+ # Can be used to access it outside the router's scope, for instance, in a background process.
148
+ #
149
+ def broadcast(channel, message, except=[])
150
+ logger.debug "Broadcasting message on channel: #{channel}. Message:"
151
+ logger.debug message
152
+ @@connections[channel].each do |user, ws|
153
+ next if except.include?(user)
154
+ write message, ws
155
+ end
156
+ end
157
+
158
+ ##
159
+ # Send a message to a user on the channel
160
+ # Can be used to access it outside the router's scope, for instance, in a background process.
161
+ #
162
+ def send_message(channel, user, message)
163
+ logger.debug "Sending message: #{message} to user: #{user} on channel: #{channel}. Message"
164
+ write message, @@connections[channel][user]
165
+ end
166
+
167
+ ##
168
+ # Write a message to the WebSocket.
169
+ #
170
+ # It's a wrapper around the different WS implementations.
171
+ # This has to be implemented for each backend.
172
+ def write(message, ws)
173
+ logger.error "Override the write method on the WebSocket-specific backend."
174
+ raise NotImplementedError
175
+ end
176
+ end
177
+
178
+ protected
179
+ ##
180
+ # Maintain the connection if ping frames are supported
181
+ #
182
+ def on_open(event)
183
+ logger.debug "Connection openned as user: #{@user} on channel: #{@channel}."
184
+ end
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,50 @@
1
+ module Padrino
2
+ module WebSockets
3
+ module SpiderGazelle
4
+ class EventManager < BaseEventManager
5
+ def initialize(channel, user, ws, event_context, &block)
6
+ ws.progress method(:on_message)
7
+ ws.finally method(:on_shutdown)
8
+ ws.on_open method(:on_open)
9
+
10
+ super channel, user, ws, event_context, &block
11
+ end
12
+
13
+ ##
14
+ # Manage the WebSocket's connection being closed.
15
+ #
16
+ def on_shutdown
17
+ @pinger.cancel if @pinger
18
+ super
19
+ end
20
+
21
+ ##
22
+ # Write a message to the WebSocket.
23
+ #
24
+ def self.write(message, ws)
25
+ ws.text ::Oj.dump(message)
26
+ end
27
+
28
+ protected
29
+ ##
30
+ # Maintain the connection if ping frames are supported
31
+ #
32
+ def on_open(event)
33
+ super event
34
+
35
+ if @ws.ping('pong')
36
+ variation = 1 + rand(20000)
37
+ @pinger = @ws.loop.scheduler.every 40000 + variation, method(:do_ping)
38
+ end
39
+ end
40
+
41
+ ##
42
+ # Ping the WebSocket connection
43
+ #
44
+ def do_ping(time1, time2)
45
+ @ws.ping 'pong'
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,14 @@
1
+ module Padrino
2
+ module WebSockets
3
+ module SpiderGazelle
4
+ module Helpers
5
+ def send_message(channel, user, message)
6
+ Padrino::WebSockets::SpiderGazelle::EventManager.send_message channel, user, message
7
+ end
8
+ def broadcast(channel, message)
9
+ Padrino::WebSockets::SpiderGazelle::EventManager.broadcast channel, message
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,36 @@
1
+ module Padrino
2
+ module WebSockets
3
+ module SpiderGazelle
4
+ module Routing
5
+ require 'spider-gazelle/upgrades/websocket'
6
+
7
+ ##
8
+ # Creates a WebSocket endpoint using SpiderGazelle + libuv.
9
+ #
10
+ # It handles upgrading the HTTP connection for you.
11
+ # You can nest this inside controllers as you would do with regular actions in Padrino.
12
+ #
13
+ def websocket(channel, *args, &block)
14
+ get channel, *args do
15
+ # Let some other action try to handle the request if it's not a WebSocket.
16
+ throw :pass unless request.env['rack.hijack']
17
+
18
+ event_context = self
19
+
20
+ # It's a WebSocket. Get the libuv promise and manage its events
21
+ request.env['rack.hijack'].call.then do |hijacked|
22
+ ws = ::SpiderGazelle::Websocket.new hijacked.socket, hijacked.env
23
+
24
+ set_websocket_user
25
+
26
+ Padrino::WebSockets::SpiderGazelle::EventManager.new(
27
+ channel, session['websocket_user'], ws, event_context, &block)
28
+ ws.start
29
+ end
30
+ end
31
+ end
32
+ alias :ws :websocket
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,9 @@
1
+ module Padrino
2
+ module WebSockets
3
+ module SpiderGazelle
4
+ require 'padrino-websockets/spider-gazelle/helpers'
5
+ require 'padrino-websockets/spider-gazelle/routing'
6
+ require 'padrino-websockets/spider-gazelle/event-manager'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ module Padrino
2
+ module Websockets
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,31 @@
1
+ module Padrino
2
+ module WebSockets
3
+ module Helpers
4
+ require 'securerandom'
5
+
6
+ def set_websocket_user
7
+ session['websocket_user'] ||= SecureRandom.uuid
8
+ end
9
+ end
10
+ class << self
11
+ ##
12
+ # Main class that register this extension.
13
+ #
14
+ def registered(app)
15
+ require 'padrino-websockets/base-event-manager'
16
+
17
+ if defined?(::SpiderGazelle)
18
+ require 'padrino-websockets/spider-gazelle'
19
+ app.helpers Padrino::WebSockets::SpiderGazelle::Helpers
20
+ app.extend Padrino::WebSockets::SpiderGazelle::Routing
21
+ else
22
+ logger.error "Can't find a WebSockets backend. At the moment we only support SpiderGazelle."
23
+ raise NotImplementedError
24
+ end
25
+
26
+ app.helpers Padrino::WebSockets::Helpers
27
+ end
28
+ alias :included :registered
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'padrino-websockets/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "padrino-websockets"
8
+ spec.version = Padrino::Websockets::VERSION
9
+ spec.authors = ["Darío Javier Cravero"]
10
+ spec.email = ["dario@uxtemple.com"]
11
+ spec.summary = %q{A WebSockets abstraction for Padrino}
12
+ spec.description = %q{A WebSockets abstraction for the Padrino Ruby Web Framework to manage
13
+ channels, users and events regardless of the underlying WebSockets implementation.}
14
+ spec.homepage = "https://github.com/dariocravero/padrino-websockets"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.5"
23
+ spec.add_development_dependency "rake"
24
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: padrino-websockets
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Darío Javier Cravero
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: |-
42
+ A WebSockets abstraction for the Padrino Ruby Web Framework to manage
43
+ channels, users and events regardless of the underlying WebSockets implementation.
44
+ email:
45
+ - dario@uxtemple.com
46
+ executables: []
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - ".gitignore"
51
+ - Gemfile
52
+ - LICENSE.txt
53
+ - README.md
54
+ - Rakefile
55
+ - examples/padrino-app/.components
56
+ - examples/padrino-app/.gitignore
57
+ - examples/padrino-app/Gemfile
58
+ - examples/padrino-app/Rakefile
59
+ - examples/padrino-app/app/app.rb
60
+ - examples/padrino-app/app/views/index.slim
61
+ - examples/padrino-app/config.ru
62
+ - examples/padrino-app/config/apps.rb
63
+ - examples/padrino-app/config/boot.rb
64
+ - examples/padrino-app/public/favicon.ico
65
+ - lib/padrino-websockets.rb
66
+ - lib/padrino-websockets/base-event-manager.rb
67
+ - lib/padrino-websockets/spider-gazelle.rb
68
+ - lib/padrino-websockets/spider-gazelle/event-manager.rb
69
+ - lib/padrino-websockets/spider-gazelle/helpers.rb
70
+ - lib/padrino-websockets/spider-gazelle/routing.rb
71
+ - lib/padrino-websockets/version.rb
72
+ - padrino-websockets.gemspec
73
+ homepage: https://github.com/dariocravero/padrino-websockets
74
+ licenses:
75
+ - MIT
76
+ metadata: {}
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 2.2.0
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: A WebSockets abstraction for Padrino
97
+ test_files: []