sarb 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ # Text-editor extra files
2
+ *.swp
3
+
4
+ # Version Manager files
5
+ .rvmrc
6
+
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rspec"
4
+ gem "em-websocket"
5
+
data/Gemfile.lock ADDED
@@ -0,0 +1,24 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.2.2)
5
+ em-websocket (0.5.0)
6
+ eventmachine (>= 0.12.9)
7
+ http_parser.rb (~> 0.5.3)
8
+ eventmachine (1.0.3)
9
+ http_parser.rb (0.5.3)
10
+ rspec (2.13.0)
11
+ rspec-core (~> 2.13.0)
12
+ rspec-expectations (~> 2.13.0)
13
+ rspec-mocks (~> 2.13.0)
14
+ rspec-core (2.13.1)
15
+ rspec-expectations (2.13.0)
16
+ diff-lcs (>= 1.1.3, < 2.0)
17
+ rspec-mocks (2.13.1)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ em-websocket
24
+ rspec
data/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # Socket Action Ruby (sarb)
2
+
3
+ Framework for em-websocket that uses actions and triggers for real-time communication with your app.
4
+
5
+ ## Example
6
+
7
+ ```ruby
8
+ require "sarb"
9
+
10
+ app = Sarb::Application.new
11
+ app.action(:foo) { |session, args| session.message(:action => :bar) }
12
+ app.run
13
+ ```
14
+
15
+ On client side:
16
+
17
+ ```javascript
18
+ var ws = new WebSocket("ws://127.0.0.1:8080/");
19
+ ws.onmessage = function(message) { console.log(message) };
20
+ ws.send(JSON.stringify({ action: "foo" }))
21
+ ```
22
+
23
+ ## License
24
+
25
+ The MIT License - Copyright (c) 2012-2013 Craig Jackson
26
+
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "rubygems"
2
+ require "rake"
3
+
4
+ require "rspec/core/rake_task"
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
8
+
@@ -0,0 +1,52 @@
1
+ module Sarb
2
+ class Application
3
+ DEFAULTS = {
4
+ :host => "127.0.0.1",
5
+ :port => 8080
6
+ }
7
+
8
+ def initialize
9
+ @actions = {}
10
+ @hooks = {
11
+ :connection_open => [method(:connection_open)],
12
+ :connection_close => [method(:connection_close)]
13
+ }
14
+ @connections = []
15
+ end
16
+
17
+ def action(name, &block)
18
+ @actions[name.to_sym] = block
19
+ end
20
+
21
+ def hook(name, &block)
22
+ @hooks[name.to_sym] = [] unless @hooks.has_key?(name.to_sym)
23
+ @hooks[name.to_sym] << block
24
+ end
25
+
26
+ def new_connection(ws)
27
+ Connection.setup(self, ws)
28
+ end
29
+
30
+ def connection_open(args)
31
+ @connections << args[:connection]
32
+ end
33
+
34
+ def connection_close(args)
35
+ @connections.delete(args[:connection])
36
+ end
37
+
38
+ def run(options = {})
39
+ EventMachine::WebSocket.start(DEFAULTS.merge(options), &method(:new_connection))
40
+ end
41
+
42
+ def invoke(connection, message)
43
+ data = JSON.parse(message)
44
+ @actions[data["action"].to_sym].call(connection, data["args"])
45
+ end
46
+
47
+ def trigger(name, args)
48
+ @hooks[name.to_sym].each { |block| block.call(args) }
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1,32 @@
1
+ module Sarb
2
+ class Connection
3
+ def initialize(app, ws)
4
+ @app = app
5
+ @ws = ws
6
+ end
7
+
8
+ def onopen(handshake)
9
+ @app.trigger :connection_open, :connection => self
10
+ end
11
+
12
+ def onmessage(message)
13
+ @app.invoke self, message
14
+ end
15
+
16
+ def onclose(event)
17
+ @app.trigger :connection_close, :connection => self
18
+ end
19
+
20
+ def message(message)
21
+ @ws.send(message.to_json)
22
+ end
23
+
24
+ def self.setup(app, ws)
25
+ connection = Connection.new(app, ws)
26
+ ws.onopen &connection.method(:onopen)
27
+ ws.onmessage &connection.method(:onmessage)
28
+ ws.onclose &connection.method(:onclose)
29
+ end
30
+ end
31
+ end
32
+
@@ -0,0 +1,8 @@
1
+ module Sarb
2
+ module VERSION
3
+ MAJOR = 0
4
+ MINOR = 1
5
+ TINY = 0
6
+ end
7
+ end
8
+
data/lib/sarb.rb ADDED
@@ -0,0 +1,10 @@
1
+ require "em-websocket"
2
+ require "json"
3
+
4
+ require "sarb/application"
5
+ require "sarb/connection"
6
+ require "sarb/version"
7
+
8
+ module Sarb
9
+ end
10
+
data/sarb.gemspec ADDED
@@ -0,0 +1,17 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "sarb"
3
+ s.version = "0.1.0"
4
+ s.summary = "Socket Action Ruby"
5
+ s.description = "Framework for em-websocket that uses actions and triggers for real-time communication with your app."
6
+ s.authors = ["Craig Jackson"]
7
+ s.email = "tapocol@gmail.com"
8
+ s.homepage = "https://github.com/craigjackson/sarb"
9
+
10
+ s.files = `git ls-files`.split("\n")
11
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
12
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
13
+ s.require_paths = ["lib"]
14
+
15
+ s.add_dependency("em-websocket", ">= 0.5.0")
16
+ end
17
+
@@ -0,0 +1,139 @@
1
+ require "spec_helper"
2
+
3
+ describe Sarb::Application do
4
+ before do
5
+ @app = Sarb::Application.new
6
+ end
7
+
8
+ context "initialize" do
9
+ it "should set @actions @hooks @connections" do
10
+ @app.instance_variable_get(:@actions).should == {}
11
+ @app.instance_variable_get(:@hooks).should == {
12
+ :connection_open => [@app.method(:connection_open)],
13
+ :connection_close => [@app.method(:connection_close)]
14
+ }
15
+ @app.instance_variable_get(:@connections).should == []
16
+ end
17
+ end
18
+
19
+ context "action" do
20
+ it "should add an action" do
21
+ block = Proc.new {}
22
+ @app.action :foo, &block
23
+ expected = {:foo => block}
24
+ @app.instance_variable_get(:@actions).should == expected
25
+ end
26
+
27
+ it "should add an action and convert name to sym" do
28
+ block = Proc.new {}
29
+ @app.action "foo", &block
30
+ expected = {:foo => block}
31
+ @app.instance_variable_get(:@actions).should == expected
32
+ end
33
+ end
34
+
35
+ context "hook" do
36
+ before do
37
+ @app.instance_variable_set(:@hooks, {})
38
+ end
39
+
40
+ it "should add a new hook" do
41
+ block = Proc.new {}
42
+ @app.hook :foo, &block
43
+ expected = {:foo => [block]}
44
+ @app.instance_variable_get(:@hooks).should == expected
45
+ end
46
+
47
+ it "should add a new hook and convert name to sym" do
48
+ block = Proc.new {}
49
+ @app.hook "foo", &block
50
+ expected = {:foo => [block]}
51
+ @app.instance_variable_get(:@hooks).should == expected
52
+ end
53
+
54
+ it "should add a new hook to the existing hooks" do
55
+ block1 = Proc.new { "block1" }
56
+ @app.instance_variable_set(:@hooks, {:foo => [block1]})
57
+ block2 = Proc.new { "block2" }
58
+ @app.hook :foo, &block2
59
+ expected = {:foo => [block1, block2]}
60
+ @app.instance_variable_get(:@hooks).should == expected
61
+ end
62
+ end
63
+
64
+ context "new_connection" do
65
+ it "should pass along the websocket to the Connection and set onmessage event" do
66
+ @connection = Sarb::Connection.new(@app, "ws")
67
+ Sarb::Connection.should_receive(:setup).with(@app, "ws").and_return(@connection)
68
+ @app.new_connection("ws").should === @connection
69
+ end
70
+ end
71
+
72
+ context "connection_open" do
73
+ it "should add to @connections" do
74
+ connection = "connection"
75
+ @app.connection_open({:connection => connection})
76
+ @app.instance_variable_get(:@connections).should == [connection]
77
+ end
78
+ end
79
+
80
+ context "connection_close" do
81
+ it "should remove from @connections" do
82
+ connection1 = "connection1"
83
+ connection2 = "connection2"
84
+ @app.instance_variable_set(:@connections, [connection1, connection2])
85
+ @app.connection_close({:connection => connection1})
86
+ @app.instance_variable_get(:@connections).should == [connection2]
87
+ end
88
+ end
89
+
90
+ context "run" do
91
+ it "should start an EventMachine::WebSocket with defaults" do
92
+ method = Proc.new {}
93
+ @app.stub(:method => method)
94
+ # TODO: Not really sure how to test &method is passed. "with" does not actually test &method.
95
+ EventMachine::WebSocket.should_receive(:start).with(Sarb::Application::DEFAULTS, &method)
96
+ @app.run
97
+ end
98
+
99
+ it "should start an EventMachine::WebSocket with given host and default port" do
100
+ method = Proc.new {}
101
+ @app.stub(:method => method)
102
+ # TODO: Not really sure how to test &method is passed. "with" does not actually test &method.
103
+ EventMachine::WebSocket.should_receive(:start).with(:host => "testhost", :port => Sarb::Application::DEFAULTS[:port], &method)
104
+ @app.run :host => "testhost"
105
+ end
106
+
107
+ it "should start an EventMachine::WebSocket with default host and given port" do
108
+ method = Proc.new {}
109
+ @app.stub(:method => method)
110
+ # TODO: Not really sure how to test &method is passed. "with" does not actually test &method.
111
+ EventMachine::WebSocket.should_receive(:start).with(:host => Sarb::Application::DEFAULTS[:host], :port => "testport", &method)
112
+ @app.run :port => "testport"
113
+ end
114
+ end
115
+
116
+ context "invoke" do
117
+ it "should call action's method" do
118
+ @ws = "ws"
119
+ connection = Sarb::Connection.new(@app, @ws)
120
+ block = Proc.new {}
121
+ @app.instance_variable_set(:@actions, {:action => block})
122
+ JSON.should_receive(:parse).with("message").and_return({"action" => "action", "args" => {"foo" => "bar"}})
123
+ block.should_receive(:call).with(connection, {"foo" => "bar"})
124
+ @app.invoke(connection, "message")
125
+ end
126
+ end
127
+
128
+ context "trigger" do
129
+ it "should call all hooks' methods" do
130
+ block1 = Proc.new { "block1" }
131
+ block2 = Proc.new { "block2" }
132
+ @app.instance_variable_set(:@hooks, {:foo => [block1, block2]})
133
+ block1.should_receive(:call).with({:foo => :bar})
134
+ block2.should_receive(:call).with({:foo => :bar})
135
+ @app.trigger "foo", {:foo => :bar}
136
+ end
137
+ end
138
+ end
139
+
@@ -0,0 +1,62 @@
1
+ require "spec_helper"
2
+
3
+ describe Sarb::Connection do
4
+ before do
5
+ @app = Sarb::Application.new
6
+ @ws = EventMachine::WebSocket::Connection.new("asdf1234", {})
7
+ @connection = Sarb::Connection.new(@app, @ws)
8
+ end
9
+
10
+ context "initialize" do
11
+ it "should set app and ws" do
12
+ @connection.instance_variable_get(:@app).should === @app
13
+ @connection.instance_variable_get(:@ws).should === @ws
14
+ end
15
+ end
16
+
17
+ context "onopen" do
18
+ before do
19
+ @handshake = EventMachine::WebSocket::Handshake.new("asdf1234")
20
+ end
21
+
22
+ it "should trigger app :connection_open" do
23
+ @app.should_receive(:trigger).with(:connection_open, {:connection => @connection})
24
+ @connection.onopen(@handshake)
25
+ end
26
+ end
27
+
28
+ context "onmessage" do
29
+ it "should use the app's handler" do
30
+ @app.should_receive(:invoke).with(@connection, "message")
31
+ @connection.onmessage("message")
32
+ end
33
+ end
34
+
35
+ context "onclose" do
36
+ it "should trigger app :connection_close" do
37
+ @app.should_receive(:trigger).with(:connection_close, {:connection => @connection})
38
+ @connection.onclose({})
39
+ end
40
+ end
41
+
42
+ context "message" do
43
+ it "should send through ws" do
44
+ message = "message"
45
+ message.should_receive(:to_json).and_return("message_str")
46
+ @ws.should_receive(:send).with("message_str")
47
+ @connection.message(message)
48
+ end
49
+ end
50
+
51
+ context "setup" do
52
+ it "should create new Connection and add 'on' events" do
53
+ Sarb::Connection.should_receive(:new).with(@app, @ws).and_return(@connection)
54
+ # TODO: Putting the intended blocks in the 'with' method on the following stubs causes an error.
55
+ @ws.should_receive(:onopen)
56
+ @ws.should_receive(:onmessage)
57
+ @ws.should_receive(:onclose)
58
+ Sarb::Connection.setup(@app, @ws)
59
+ end
60
+ end
61
+ end
62
+
@@ -0,0 +1,5 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+
4
+ require "sarb"
5
+
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sarb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Craig Jackson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: em-websocket
16
+ requirement: &7758080 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.5.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *7758080
25
+ description: Framework for em-websocket that uses actions and triggers for real-time
26
+ communication with your app.
27
+ email: tapocol@gmail.com
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - .gitignore
33
+ - .rspec
34
+ - Gemfile
35
+ - Gemfile.lock
36
+ - README.md
37
+ - Rakefile
38
+ - lib/sarb.rb
39
+ - lib/sarb/application.rb
40
+ - lib/sarb/connection.rb
41
+ - lib/sarb/version.rb
42
+ - sarb.gemspec
43
+ - spec/lib/sarb/application_spec.rb
44
+ - spec/lib/sarb/connection_spec.rb
45
+ - spec/spec_helper.rb
46
+ homepage: https://github.com/craigjackson/sarb
47
+ licenses: []
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ requirements: []
65
+ rubyforge_project:
66
+ rubygems_version: 1.8.10
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: Socket Action Ruby
70
+ test_files: []