puller 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +4 -0
- data/README.md +85 -15
- data/Rakefile +13 -0
- data/app/assets/javascripts/puller.js +72 -0
- data/lib/generators/puller/install_generator.rb +16 -0
- data/lib/generators/puller/templates/.gitkeep +0 -0
- data/lib/puller/engine.rb +19 -0
- data/lib/puller/version.rb +1 -1
- data/lib/puller/view_helpers.rb +18 -0
- data/lib/puller.rb +30 -1
- data/puller.gemspec +6 -0
- data/spec/javascripts/puller_spec.js +109 -0
- data/spec/javascripts/support/jasmine.yml +74 -0
- data/spec/javascripts/support/jasmine_config.rb +24 -0
- data/spec/javascripts/support/jasmine_runner.rb +33 -0
- data/spec/puller_spec.rb +8 -0
- data/spec/spec_helper.rb +9 -0
- metadata +61 -2
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -1,29 +1,99 @@
|
|
1
1
|
# Puller
|
2
2
|
|
3
|
-
|
3
|
+
Puller is a Ruby gem for use with Rails to publish and subscribe to messages through [Pusher](http://pusher.com/). It allows you to easily provide real-time updates through an open socket without tying up a Rails process.
|
4
4
|
|
5
|
-
|
5
|
+
Its code and API design is heavily inspired by Ryan Bates' [PrivatePub](http://github.com/ryanb/private_pub).
|
6
6
|
|
7
|
-
Add this line to your application's Gemfile:
|
8
7
|
|
9
|
-
|
8
|
+
## Setup
|
10
9
|
|
11
|
-
|
10
|
+
Add the gem to the Gemfile of your Rails application and run the `bundle` command to install it.
|
12
11
|
|
13
|
-
|
12
|
+
```ruby
|
13
|
+
gem "puller"
|
14
|
+
```
|
14
15
|
|
15
|
-
Or install it yourself as:
|
16
16
|
|
17
|
-
|
17
|
+
**In Rails 3.1** add the JavaScript file to your application.js file manifest.
|
18
|
+
|
19
|
+
```javascript
|
20
|
+
//= require puller
|
21
|
+
```
|
22
|
+
|
23
|
+
|
24
|
+
**In Rails 3.0** run the generator to create the initial files
|
25
|
+
|
26
|
+
```
|
27
|
+
rails g puller:install
|
28
|
+
```
|
29
|
+
|
30
|
+
and add the generated puller.js file to your layout.
|
31
|
+
|
32
|
+
```rhtml
|
33
|
+
<%= javascript_include_tag "puller" %>
|
34
|
+
```
|
35
|
+
|
36
|
+
|
37
|
+
It's not necessary to include pusher.js since that will be handled automatically for you.
|
38
|
+
|
39
|
+
Configure your Pusher credentials in an initializer file.
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
Pusher.app_id = 'my_pusher_app_id'
|
43
|
+
Pusher.key = 'my_pusher_api_key'
|
44
|
+
Pusher.secret = 'my_pusher_secret'
|
45
|
+
```
|
46
|
+
|
47
|
+
Note: You can skip this step if you are on Heroku and have activated the Pusher addon for your app.
|
48
|
+
|
18
49
|
|
19
50
|
## Usage
|
20
51
|
|
21
|
-
|
52
|
+
Use the `subscribe_to` helper method on any page to subscribe to a channel/event.
|
53
|
+
|
54
|
+
```rhtml
|
55
|
+
<%= subscribe_to "new-message" %>
|
56
|
+
```
|
57
|
+
|
58
|
+
The above method subscribes to the "new-message" event in the default channel. The default channel name is
|
59
|
+
the parameterized form of your Rails' application name. To use a different channel, prepend your custom
|
60
|
+
channel name to the argument followed by a colon:
|
61
|
+
|
62
|
+
```rhtml
|
63
|
+
<%= subscribe_to "my-channel:new-message" %>
|
64
|
+
```
|
65
|
+
|
66
|
+
Use the `publish_to` helper method to send JavaScript to that channel/event. This is usually done in a JavaScript AJAX template (such as a create.js.erb file).
|
67
|
+
|
68
|
+
```rhtml
|
69
|
+
<% publish_to "new-message" do %>
|
70
|
+
$("#chat").append("<%= j render(@message) %>");
|
71
|
+
<% end %>
|
72
|
+
```
|
73
|
+
|
74
|
+
This JavaScript will be immediately evaluated on all clients who have subscribed to that channel. In this example they will see the new chat message appear in real-time without reloading the browser.
|
75
|
+
|
76
|
+
|
77
|
+
## Alternative Usage
|
78
|
+
|
79
|
+
If you prefer to work through JSON instead of `.js.erb` templates, you can pass a hash to `publish_to` instead of a block and it will be converted `to_json` behind the scenes. This can be done anywhere (such as the controller).
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
Puller.publish_to "new-message", :chat_message => "Hello, world!"
|
83
|
+
```
|
84
|
+
|
85
|
+
And then handle this through JavaScript on the client side.
|
86
|
+
|
87
|
+
```javascript
|
88
|
+
Puller.subscribe("new-message", function(data, channel) {
|
89
|
+
$("#chat").append(data.chat_message);
|
90
|
+
});
|
91
|
+
```
|
92
|
+
|
93
|
+
The Ruby `subscribe_to` helper call is still necessary with this approach to grant the user access to the channel. The JavaScript is just a callback for any custom behavior.
|
94
|
+
|
95
|
+
|
96
|
+
## Development & Feedback
|
22
97
|
|
23
|
-
|
98
|
+
Questions or comments? Please use the [issue tracker](https://github.com/natekross/puller/issues). Tests can be run with `bundle` and `rake` commands.
|
24
99
|
|
25
|
-
1. Fork it
|
26
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
-
3. Commit your changes (`git commit -am 'Added some feature'`)
|
28
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
-
5. Create new Pull Request
|
data/Rakefile
CHANGED
@@ -1,3 +1,16 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
2
|
require "bundler/gem_tasks"
|
3
3
|
|
4
|
+
require "rubygems"
|
5
|
+
require "rake"
|
6
|
+
require "rspec/core/rake_task"
|
7
|
+
require "jasmine"
|
8
|
+
load "jasmine/tasks/jasmine.rake"
|
9
|
+
|
10
|
+
desc "Run RSpec"
|
11
|
+
RSpec::Core::RakeTask.new do |t|
|
12
|
+
t.verbose = false
|
13
|
+
end
|
14
|
+
|
15
|
+
task :default => [:spec, "jasmine:ci"]
|
16
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
function buildPuller(doc) {
|
2
|
+
var self = {
|
3
|
+
connecting: false,
|
4
|
+
pusher: null,
|
5
|
+
initCallbacks: [],
|
6
|
+
subscriptions: {},
|
7
|
+
subscriptionCallbacks: {},
|
8
|
+
channels: {},
|
9
|
+
|
10
|
+
fetchPusher: function(callback) {
|
11
|
+
if (self.pusher) {
|
12
|
+
callback(self.pusher);
|
13
|
+
} else {
|
14
|
+
self.initCallbacks.push(callback);
|
15
|
+
|
16
|
+
if (self.subscriptions.apiKey && !self.connecting) {
|
17
|
+
self.connecting = true;
|
18
|
+
|
19
|
+
var script = doc.createElement("script");
|
20
|
+
script.type = "text/javascript";
|
21
|
+
script.src = "http://js.pusher.com/1.11/pusher.min.js";
|
22
|
+
script.onload = self.connectToPusher;
|
23
|
+
|
24
|
+
doc.documentElement.appendChild(script);
|
25
|
+
}
|
26
|
+
}
|
27
|
+
},
|
28
|
+
|
29
|
+
connectToPusher: function() {
|
30
|
+
self.pusher = new Pusher(self.subscriptions.apiKey);
|
31
|
+
|
32
|
+
for (var i = 0, ii = self.initCallbacks.length; i < ii; i++) {
|
33
|
+
self.initCallbacks[i](self.pusher);
|
34
|
+
};
|
35
|
+
},
|
36
|
+
|
37
|
+
sign: function(options) {
|
38
|
+
if (!self.subscriptions.apiKey) {
|
39
|
+
self.subscriptions.apiKey = options.apiKey;
|
40
|
+
}
|
41
|
+
|
42
|
+
self.subscriptions[options.channel + ":" + options.event] = options;
|
43
|
+
|
44
|
+
self.fetchPusher(function(pusher) {
|
45
|
+
if (!self.channels[options.channel]) {
|
46
|
+
self.channels[options.channel] = pusher.subscribe(options.channel);
|
47
|
+
}
|
48
|
+
|
49
|
+
self.channels[options.channel].bind(options.event, self.handleResponse);
|
50
|
+
});
|
51
|
+
},
|
52
|
+
|
53
|
+
handleResponse: function(message) {
|
54
|
+
if (message.eval) {
|
55
|
+
eval(message.eval);
|
56
|
+
}
|
57
|
+
|
58
|
+
if (callback = self.subscriptionCallbacks[message.channel + ":" + message.event]) {
|
59
|
+
callback(message.data, message.channel, message.event);
|
60
|
+
}
|
61
|
+
},
|
62
|
+
|
63
|
+
subscribe: function(channel_event, callback) {
|
64
|
+
self.subscriptionCallbacks[channel_event] = callback;
|
65
|
+
}
|
66
|
+
};
|
67
|
+
|
68
|
+
return self;
|
69
|
+
}
|
70
|
+
|
71
|
+
var Puller = buildPuller(document);
|
72
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Puller
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
def self.source_root
|
5
|
+
File.dirname(__FILE__) + "/templates"
|
6
|
+
end
|
7
|
+
|
8
|
+
def copy_files
|
9
|
+
if ::Rails.version < "3.1"
|
10
|
+
copy_file "../../../../app/assets/javascripts/puller.js", "public/javascripts/puller.js"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
File without changes
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "puller/view_helpers"
|
2
|
+
|
3
|
+
module Puller
|
4
|
+
class Engine < Rails::Engine
|
5
|
+
# Adds the ViewHelpers into ActionView::Base and sets
|
6
|
+
# Pusher's logger to Rails' logger.
|
7
|
+
initializer "puller.init" do
|
8
|
+
ActionView::Base.send :include, ViewHelpers
|
9
|
+
Pusher.logger = Rails.logger
|
10
|
+
|
11
|
+
Puller.default_channel = begin
|
12
|
+
app_name = Rails.application.class.name
|
13
|
+
app_name = app_name.split('::').first
|
14
|
+
app_name.parameterize
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
data/lib/puller/version.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Puller
|
2
|
+
module ViewHelpers
|
3
|
+
def publish_to(channel_event, data = nil, &block)
|
4
|
+
Puller.publish_to channel_event, data || capture(&block)
|
5
|
+
end
|
6
|
+
|
7
|
+
def subscribe_to(channel_event)
|
8
|
+
channel, event = Puller.channel_and_event_for(channel_event)
|
9
|
+
|
10
|
+
options = { :channel => channel, :event => event, :apiKey => Pusher.key }
|
11
|
+
|
12
|
+
content_tag "script", :type => "text/javascript" do
|
13
|
+
raw "Puller.sign(#{options.to_json});"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
data/lib/puller.rb
CHANGED
@@ -1,6 +1,35 @@
|
|
1
|
+
require "pusher"
|
2
|
+
|
1
3
|
require "puller/version"
|
4
|
+
require "puller/engine" if defined? Rails
|
2
5
|
|
3
6
|
module Puller
|
4
|
-
|
7
|
+
class << self
|
8
|
+
attr_writer :default_channel
|
9
|
+
|
10
|
+
def default_channel
|
11
|
+
@default_channel ||= "default"
|
12
|
+
end
|
13
|
+
|
14
|
+
def publish_to(channel_event, data)
|
15
|
+
channel, event = channel_and_event_for(channel_event)
|
16
|
+
|
17
|
+
message = { :channel => channel, :event => event }
|
18
|
+
message[data.kind_of?(String) ? :eval : :data] = data
|
19
|
+
|
20
|
+
Pusher[channel].trigger event, message
|
21
|
+
end
|
22
|
+
|
23
|
+
def channel_and_event_for(text)
|
24
|
+
channel, event = text.split(':', 1)
|
25
|
+
|
26
|
+
if event.nil?
|
27
|
+
event = channel
|
28
|
+
channel = default_channel
|
29
|
+
end
|
30
|
+
|
31
|
+
[channel, event]
|
32
|
+
end
|
33
|
+
end
|
5
34
|
end
|
6
35
|
|
data/puller.gemspec
CHANGED
@@ -17,5 +17,11 @@ Gem::Specification.new do |gem|
|
|
17
17
|
|
18
18
|
gem.rubyforge_project = gem.name
|
19
19
|
gem.required_rubygems_version = ">= 1.3.4"
|
20
|
+
|
21
|
+
gem.add_dependency "pusher", "~> 0.8.5"
|
22
|
+
|
23
|
+
gem.add_development_dependency "rake"
|
24
|
+
gem.add_development_dependency "rspec", "~> 2.8.0"
|
25
|
+
gem.add_development_dependency "jasmine", ">= 1.1.1"
|
20
26
|
end
|
21
27
|
|
@@ -0,0 +1,109 @@
|
|
1
|
+
describe("Puller", function() {
|
2
|
+
var puller, doc;
|
3
|
+
|
4
|
+
beforeEach(function() {
|
5
|
+
Pusher = {}; // To simulate global Pusher object
|
6
|
+
doc = {};
|
7
|
+
puller = buildPuller(doc);
|
8
|
+
});
|
9
|
+
|
10
|
+
it("adds a subscription callback", function() {
|
11
|
+
puller.subscribe("hello", "callback");
|
12
|
+
expect(puller.subscriptionCallbacks["hello"]).toEqual("callback");
|
13
|
+
});
|
14
|
+
|
15
|
+
it("evaluates javascript in message response", function() {
|
16
|
+
puller.handleResponse({eval: 'self.subscriptions.foo = "bar"'});
|
17
|
+
expect(puller.subscriptions.foo).toEqual("bar");
|
18
|
+
});
|
19
|
+
|
20
|
+
it("triggers callback matching message channel in response", function() {
|
21
|
+
var called = false;
|
22
|
+
puller.subscribe("chan:test", function(data, channel, event) {
|
23
|
+
expect(data).toEqual("abcd");
|
24
|
+
expect(channel).toEqual("chan");
|
25
|
+
expect(event).toEqual("test");
|
26
|
+
called = true;
|
27
|
+
});
|
28
|
+
puller.handleResponse({channel: "chan", event: "test", data: "abcd"});
|
29
|
+
expect(called).toBeTruthy();
|
30
|
+
});
|
31
|
+
|
32
|
+
it("adds a pusher subscription with response handler when signing", function() {
|
33
|
+
var subscribeCalled = false,
|
34
|
+
bindCalled = false,
|
35
|
+
channel = {
|
36
|
+
bind: function(event, callback) {
|
37
|
+
expect(event).toEqual("someevent");
|
38
|
+
expect(callback).toEqual(puller.handleResponse);
|
39
|
+
bindCalled = true;
|
40
|
+
}
|
41
|
+
},
|
42
|
+
pusher = {
|
43
|
+
subscribe: function(channelName) {
|
44
|
+
expect(channelName).toEqual("somechannel");
|
45
|
+
subscribeCalled = true;
|
46
|
+
|
47
|
+
return channel;
|
48
|
+
}
|
49
|
+
};
|
50
|
+
|
51
|
+
spyOn(puller, 'fetchPusher').andCallFake(function(callback) {
|
52
|
+
callback(pusher);
|
53
|
+
});
|
54
|
+
|
55
|
+
var options = {apiKey: "someapikey", channel: "somechannel", event: "someevent"};
|
56
|
+
puller.sign(options);
|
57
|
+
|
58
|
+
expect(puller.subscriptions.apiKey).toEqual("someapikey");
|
59
|
+
expect(puller.subscriptions["somechannel:someevent"]).toEqual(options);
|
60
|
+
|
61
|
+
expect(subscribeCalled).toBeTruthy();
|
62
|
+
expect(bindCalled).toBeTruthy();
|
63
|
+
|
64
|
+
expect(puller.channels["somechannel"]).toEqual(channel);
|
65
|
+
});
|
66
|
+
|
67
|
+
it("triggers pusher callback function immediately when pusher is available", function() {
|
68
|
+
var called = false;
|
69
|
+
puller.pusher = "pusher";
|
70
|
+
puller.fetchPusher(function(pusher) {
|
71
|
+
expect(pusher).toEqual("pusher");
|
72
|
+
called = true;
|
73
|
+
});
|
74
|
+
expect(called).toBeTruthy();
|
75
|
+
});
|
76
|
+
|
77
|
+
it("adds initCallback when client and server aren't available", function() {
|
78
|
+
puller.fetchPusher("callback");
|
79
|
+
expect(puller.initCallbacks[0]).toEqual("callback");
|
80
|
+
});
|
81
|
+
|
82
|
+
it("adds a script tag loading pusher js when the server is present", function() {
|
83
|
+
script = {};
|
84
|
+
doc.createElement = function() { return script; };
|
85
|
+
doc.documentElement = {appendChild: jasmine.createSpy()};
|
86
|
+
puller.subscriptions.apiKey = "someapikey";
|
87
|
+
puller.fetchPusher("callback");
|
88
|
+
expect(puller.initCallbacks[0]).toEqual("callback");
|
89
|
+
expect(script.type).toEqual("text/javascript");
|
90
|
+
expect(script.src).toEqual("http://js.pusher.com/1.11/pusher.min.js");
|
91
|
+
expect(script.onload).toEqual(puller.connectToPusher);
|
92
|
+
expect(doc.documentElement.appendChild).toHaveBeenCalledWith(script);
|
93
|
+
});
|
94
|
+
|
95
|
+
it("connects to pusher server and executes callbacks", function() {
|
96
|
+
callback = jasmine.createSpy();
|
97
|
+
client = { foo: "bar" };
|
98
|
+
Pusher = function(key) {
|
99
|
+
expect(key).toEqual("key")
|
100
|
+
return client;
|
101
|
+
};
|
102
|
+
puller.subscriptions.apiKey = "key";
|
103
|
+
puller.initCallbacks.push(callback);
|
104
|
+
puller.connectToPusher();
|
105
|
+
expect(puller.pusher).toEqual(client);
|
106
|
+
expect(callback).toHaveBeenCalledWith(client);
|
107
|
+
});
|
108
|
+
});
|
109
|
+
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# src_files
|
2
|
+
#
|
3
|
+
# Return an array of filepaths relative to src_dir to include before jasmine specs.
|
4
|
+
# Default: []
|
5
|
+
#
|
6
|
+
# EXAMPLE:
|
7
|
+
#
|
8
|
+
# src_files:
|
9
|
+
# - lib/source1.js
|
10
|
+
# - lib/source2.js
|
11
|
+
# - dist/**/*.js
|
12
|
+
#
|
13
|
+
src_files:
|
14
|
+
- app/assets/javascripts/puller.js
|
15
|
+
|
16
|
+
# stylesheets
|
17
|
+
#
|
18
|
+
# Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs.
|
19
|
+
# Default: []
|
20
|
+
#
|
21
|
+
# EXAMPLE:
|
22
|
+
#
|
23
|
+
# stylesheets:
|
24
|
+
# - css/style.css
|
25
|
+
# - stylesheets/*.css
|
26
|
+
#
|
27
|
+
stylesheets:
|
28
|
+
|
29
|
+
# helpers
|
30
|
+
#
|
31
|
+
# Return an array of filepaths relative to spec_dir to include before jasmine specs.
|
32
|
+
# Default: ["helpers/**/*.js"]
|
33
|
+
#
|
34
|
+
# EXAMPLE:
|
35
|
+
#
|
36
|
+
# helpers:
|
37
|
+
# - helpers/**/*.js
|
38
|
+
#
|
39
|
+
helpers:
|
40
|
+
|
41
|
+
# spec_files
|
42
|
+
#
|
43
|
+
# Return an array of filepaths relative to spec_dir to include.
|
44
|
+
# Default: ["**/*[sS]pec.js"]
|
45
|
+
#
|
46
|
+
# EXAMPLE:
|
47
|
+
#
|
48
|
+
# spec_files:
|
49
|
+
# - **/*[sS]pec.js
|
50
|
+
#
|
51
|
+
spec_files:
|
52
|
+
|
53
|
+
# src_dir
|
54
|
+
#
|
55
|
+
# Source directory path. Your src_files must be returned relative to this path. Will use root if left blank.
|
56
|
+
# Default: project root
|
57
|
+
#
|
58
|
+
# EXAMPLE:
|
59
|
+
#
|
60
|
+
# src_dir: public
|
61
|
+
#
|
62
|
+
src_dir:
|
63
|
+
|
64
|
+
# spec_dir
|
65
|
+
#
|
66
|
+
# Spec directory path. Your spec_files must be returned relative to this path.
|
67
|
+
# Default: spec/javascripts
|
68
|
+
#
|
69
|
+
# EXAMPLE:
|
70
|
+
#
|
71
|
+
# spec_dir: spec/javascripts
|
72
|
+
#
|
73
|
+
spec_dir:
|
74
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Jasmine
|
2
|
+
class Config
|
3
|
+
|
4
|
+
# Add your overrides or custom config code here
|
5
|
+
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
# Note - this is necessary for rspec2, which has removed the backtrace
|
11
|
+
module Jasmine
|
12
|
+
class SpecBuilder
|
13
|
+
def declare_spec(parent, spec)
|
14
|
+
me = self
|
15
|
+
example_name = spec["name"]
|
16
|
+
@spec_ids << spec["id"]
|
17
|
+
backtrace = @example_locations[parent.description + " " + example_name]
|
18
|
+
parent.it example_name, {} do
|
19
|
+
me.report_spec(spec["id"])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
$:.unshift(ENV['JASMINE_GEM_PATH']) if ENV['JASMINE_GEM_PATH'] # for gem testing purposes
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'jasmine'
|
5
|
+
jasmine_config_overrides = File.expand_path(File.join(File.dirname(__FILE__), 'jasmine_config.rb'))
|
6
|
+
require jasmine_config_overrides if File.exist?(jasmine_config_overrides)
|
7
|
+
if Jasmine::Dependencies.rspec2?
|
8
|
+
require 'rspec'
|
9
|
+
else
|
10
|
+
require 'spec'
|
11
|
+
end
|
12
|
+
|
13
|
+
jasmine_config = Jasmine::Config.new
|
14
|
+
spec_builder = Jasmine::SpecBuilder.new(jasmine_config)
|
15
|
+
|
16
|
+
should_stop = false
|
17
|
+
|
18
|
+
if Jasmine::Dependencies.rspec2?
|
19
|
+
RSpec.configuration.after(:suite) do
|
20
|
+
spec_builder.stop if should_stop
|
21
|
+
end
|
22
|
+
else
|
23
|
+
Spec::Runner.configure do |config|
|
24
|
+
config.after(:suite) do
|
25
|
+
spec_builder.stop if should_stop
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
spec_builder.start
|
31
|
+
should_stop = true
|
32
|
+
spec_builder.declare_suites
|
33
|
+
|
data/spec/puller_spec.rb
ADDED
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puller
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,51 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
date: 2012-01-19 00:00:00.000000000Z
|
13
|
-
dependencies:
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: pusher
|
16
|
+
requirement: &25369220 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.8.5
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *25369220
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
requirement: &25368580 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *25368580
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec
|
38
|
+
requirement: &25367700 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.8.0
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *25367700
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: jasmine
|
49
|
+
requirement: &25365580 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.1.1
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *25365580
|
14
58
|
description: -- gem description --
|
15
59
|
email: natekross@gmail.com
|
16
60
|
executables: []
|
@@ -18,13 +62,25 @@ extensions: []
|
|
18
62
|
extra_rdoc_files: []
|
19
63
|
files:
|
20
64
|
- .gitignore
|
65
|
+
- CHANGELOG.md
|
21
66
|
- Gemfile
|
22
67
|
- LICENSE
|
23
68
|
- README.md
|
24
69
|
- Rakefile
|
70
|
+
- app/assets/javascripts/puller.js
|
71
|
+
- lib/generators/puller/install_generator.rb
|
72
|
+
- lib/generators/puller/templates/.gitkeep
|
25
73
|
- lib/puller.rb
|
74
|
+
- lib/puller/engine.rb
|
26
75
|
- lib/puller/version.rb
|
76
|
+
- lib/puller/view_helpers.rb
|
27
77
|
- puller.gemspec
|
78
|
+
- spec/javascripts/puller_spec.js
|
79
|
+
- spec/javascripts/support/jasmine.yml
|
80
|
+
- spec/javascripts/support/jasmine_config.rb
|
81
|
+
- spec/javascripts/support/jasmine_runner.rb
|
82
|
+
- spec/puller_spec.rb
|
83
|
+
- spec/spec_helper.rb
|
28
84
|
homepage: http://github.com/natekross/puller
|
29
85
|
licenses: []
|
30
86
|
post_install_message:
|
@@ -37,6 +93,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
37
93
|
- - ! '>='
|
38
94
|
- !ruby/object:Gem::Version
|
39
95
|
version: '0'
|
96
|
+
segments:
|
97
|
+
- 0
|
98
|
+
hash: 3142173162834286048
|
40
99
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
100
|
none: false
|
42
101
|
requirements:
|