active_model_pusher 0.0.1
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 +18 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +210 -0
- data/Rakefile +2 -0
- data/active_model_pusher.gemspec +21 -0
- data/lib/active_model/pusher.rb +71 -0
- data/lib/active_model/pusher/events.rb +45 -0
- data/lib/active_model/pusher/record_channel.rb +30 -0
- data/lib/active_model/pusher/record_event_recognizer.rb +41 -0
- data/lib/active_model/pusher/record_serializer.rb +41 -0
- data/lib/active_model/pusher/version.rb +5 -0
- data/lib/active_model_pusher.rb +9 -0
- data/lib/generators/pusher/USAGE +8 -0
- data/lib/generators/pusher/pusher_generator.rb +10 -0
- data/lib/generators/pusher/templates/pusher.rb +5 -0
- data/spec/active_model_pusher/events_spec.rb +44 -0
- data/spec/active_model_pusher/pusher_spec.rb +64 -0
- data/spec/active_model_pusher/record_channel_spec.rb +30 -0
- data/spec/active_model_pusher/record_event_recognizer.rb +23 -0
- data/spec/active_model_pusher/record_serializer.rb +35 -0
- data/spec/spec_helper.rb +62 -0
- metadata +108 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 TODO: Write your name
|
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,210 @@
|
|
1
|
+
# Active Model Pusher
|
2
|
+
|
3
|
+
`ActiveModel::Pusher` makes using [Pusher](https://github.com/pusher/pusher-gem) in your app much easier.
|
4
|
+
The purpose of this gem is to use the convention over configuration principle to reduce amount of code needed to interact with Pusher.
|
5
|
+
|
6
|
+
## Basic Usage
|
7
|
+
```ruby
|
8
|
+
@post = Post.create
|
9
|
+
|
10
|
+
PostPusher.new(@post).push!
|
11
|
+
```
|
12
|
+
|
13
|
+
This will push the following json to Pusher:
|
14
|
+
|
15
|
+
```
|
16
|
+
channel: 'posts',
|
17
|
+
event: 'created',
|
18
|
+
data: { id: 1 }
|
19
|
+
```
|
20
|
+
The original Pusher gem needs 4 things to be triggered: `channel`, `event`, `data` and optional `params`. They will be discussed below.
|
21
|
+
|
22
|
+
## Channels
|
23
|
+
A `channel` value for a `Post` model will be one of the following:
|
24
|
+
|
25
|
+
1. `posts` when a record has just been created
|
26
|
+
2. `posts-1` for any other event: `updated`, `destroyed`, etc
|
27
|
+
|
28
|
+
### Customizing channels
|
29
|
+
Sometimes you might want to have a general channel name - like `dashboard` - to which you will be pushing several models.
|
30
|
+
|
31
|
+
There are two ways to do that.
|
32
|
+
|
33
|
+
* Define a `channel` method in your model:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
class Post
|
37
|
+
def channel
|
38
|
+
"dashboard"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
* Define a `channel` method in your pusher:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
class PostPusher < ActiveModel::Pusher
|
47
|
+
def channel(event)
|
48
|
+
"dashboard"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
## Events
|
54
|
+
A newly generated pusher will look like this:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
# app/pushers/post_pusher.rb
|
58
|
+
class PostPusher < ActiveModel::Pusher
|
59
|
+
events :created, :updated, :destroyed
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
The `events` method is a whitelist of events. If you try to push a non-whitelisted event, an exception will be raised:
|
64
|
+
```ruby
|
65
|
+
def publish
|
66
|
+
@post = Post.find(1).publish!
|
67
|
+
PostPusher.new(@post).push! :published
|
68
|
+
end
|
69
|
+
```
|
70
|
+
will result in `InvalidEventError: 'Event :published is not allowed'`.
|
71
|
+
|
72
|
+
|
73
|
+
The three default events can be guessed by the gem automatically, you don't actually have to specify them:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
def create
|
77
|
+
@post = Post.create
|
78
|
+
PostPusher.new(@post).push!
|
79
|
+
end
|
80
|
+
```
|
81
|
+
The gem will recognize that the record was just created and will set the event to `:created`
|
82
|
+
|
83
|
+
If you have custom actions in your controller - like `publish` - then you should specify the event manually:
|
84
|
+
```ruby
|
85
|
+
def publish
|
86
|
+
@post = Post.find(1).publish!
|
87
|
+
|
88
|
+
PostPusher.new(@post).push! :published
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
This will produce the following (given you whitelisted the `published` event in your pusher):
|
93
|
+
```
|
94
|
+
channel: 'posts-1',
|
95
|
+
event: 'published',
|
96
|
+
data: { id: 1 }
|
97
|
+
```
|
98
|
+
|
99
|
+
### Customizing events
|
100
|
+
|
101
|
+
Customizing event names may be useful when you are using a general purpose channel.
|
102
|
+
|
103
|
+
Using the example from the `Customizing channels` section:
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
class PostPusher < ActiveModel::Pusher
|
107
|
+
def channel(event)
|
108
|
+
"dashboard"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
class CommentPusher < ActiveModel::Pusher
|
112
|
+
def channel(event)
|
113
|
+
"dashboard"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
We then push two different models into the general `dashboard` channel:
|
119
|
+
```ruby
|
120
|
+
@post = Post.create
|
121
|
+
@comment = Comment.create
|
122
|
+
|
123
|
+
PostPusher.new(@post).push!
|
124
|
+
CommentPusher.new(@comment).push!
|
125
|
+
```
|
126
|
+
|
127
|
+
They both will be pushed with the same event `created`. Depending on your client-side architecture it might be fine, but sometimes you might want to have namespaced events: `post-created`, `comment-created`, etc.
|
128
|
+
|
129
|
+
You can achieve this by overriding the `event(event)` method in your pusher:
|
130
|
+
|
131
|
+
```ruby
|
132
|
+
class PostPusher < ActiveModel::Pusher
|
133
|
+
def event(event)
|
134
|
+
"post-#{event.underscore.dasherize}"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
```
|
138
|
+
|
139
|
+
## Data
|
140
|
+
The `data` method simply serializes your record.
|
141
|
+
|
142
|
+
By default, it will try to serialize the record with the `active_model_serializers` gem.
|
143
|
+
|
144
|
+
If `active_model_serializers` is not used in your application, it will fallback to the `as_json` method on your record.
|
145
|
+
|
146
|
+
But seriously, just use `active_model_serializers`.
|
147
|
+
|
148
|
+
## Params
|
149
|
+
You can specify the params when calling the `push!` method:
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
def create
|
153
|
+
@post = Post.create
|
154
|
+
PostPusher.new(@post).push! { socket_id: params[:socket_id] }
|
155
|
+
end
|
156
|
+
```
|
157
|
+
|
158
|
+
If you need to specify an event as well, it should go first:
|
159
|
+
```ruby
|
160
|
+
def publish
|
161
|
+
@post = Post.publish!
|
162
|
+
PostPusher.new(@post).push! :published, { socket_id: params[:socket_id] }
|
163
|
+
end
|
164
|
+
```
|
165
|
+
A more fancier way of doing the same:
|
166
|
+
```ruby
|
167
|
+
def publish
|
168
|
+
@post = Post.publish!
|
169
|
+
PostPusher.new(@post).push! :published, params.slice(:socket_id)
|
170
|
+
end
|
171
|
+
```
|
172
|
+
|
173
|
+
## Creating a new pusher
|
174
|
+
```
|
175
|
+
rails generate pusher Post created published
|
176
|
+
```
|
177
|
+
|
178
|
+
Will result in:
|
179
|
+
|
180
|
+
```ruby
|
181
|
+
# app/pushers/post_pusher.rb
|
182
|
+
class PostPusher < ActiveModel::Pusher
|
183
|
+
events :created, :published
|
184
|
+
end
|
185
|
+
```
|
186
|
+
|
187
|
+
## Notice
|
188
|
+
This is sort of an alpha version, so things may break. If you have any ideas on improving the gem, you are very welcome to contribute.
|
189
|
+
|
190
|
+
## Installation
|
191
|
+
|
192
|
+
Add this line to your application's Gemfile:
|
193
|
+
|
194
|
+
gem 'active_model_pusher'
|
195
|
+
|
196
|
+
And then execute:
|
197
|
+
|
198
|
+
$ bundle
|
199
|
+
|
200
|
+
Or install it yourself as:
|
201
|
+
|
202
|
+
$ gem install active_model_pusher
|
203
|
+
|
204
|
+
## Contributing
|
205
|
+
|
206
|
+
1. Fork it
|
207
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
208
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
209
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
210
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/active_model/pusher/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Alexander Zaytsev"]
|
6
|
+
gem.email = ["alexander@say26.com"]
|
7
|
+
gem.description = %q{Making it easy to use Pusher with your models}
|
8
|
+
gem.summary = %q{Push your models with Pusher easily}
|
9
|
+
gem.homepage = "https://github.com/AlexanderZaytsev/active_model_pusher"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "active_model_pusher"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = ActiveModel::Pusher::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency 'activemodel', '>= 3.0'
|
19
|
+
gem.add_dependency 'pusher'
|
20
|
+
gem.add_development_dependency "rspec"
|
21
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
class Pusher
|
3
|
+
|
4
|
+
class_attribute :_events
|
5
|
+
self._events = nil
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def events(*events)
|
9
|
+
self._events = events
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(record)
|
14
|
+
@record = record
|
15
|
+
end
|
16
|
+
|
17
|
+
def push!(event_or_params = nil, params = {})
|
18
|
+
event, params = parse_push_params(event_or_params, params)
|
19
|
+
|
20
|
+
event ||= RecordEventRecognizer.new(record).event
|
21
|
+
|
22
|
+
events.validate! event
|
23
|
+
|
24
|
+
::Pusher.trigger channel(event), event(event), data, params
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def events
|
29
|
+
@events ||= Events.new self._events
|
30
|
+
end
|
31
|
+
|
32
|
+
def record
|
33
|
+
@record
|
34
|
+
end
|
35
|
+
|
36
|
+
def channel(event)
|
37
|
+
@channel ||= RecordChannel.new(record, event).channel
|
38
|
+
end
|
39
|
+
|
40
|
+
def event(event)
|
41
|
+
event.to_s.underscore.dasherize
|
42
|
+
end
|
43
|
+
|
44
|
+
def data
|
45
|
+
@data ||= RecordSerializer.new(record).serialize!
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_push_params(event_or_params = nil, params = {})
|
49
|
+
# Tell me if there is a better way of doing this
|
50
|
+
|
51
|
+
if event_or_params && params
|
52
|
+
event = event_or_params
|
53
|
+
params = params
|
54
|
+
end
|
55
|
+
|
56
|
+
if event_or_params && params.none?
|
57
|
+
if events.validate(event_or_params)
|
58
|
+
event = event_or_params
|
59
|
+
params = {}
|
60
|
+
else
|
61
|
+
event = nil
|
62
|
+
params = event_or_params
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
[event, params]
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
class Pusher
|
3
|
+
class Events
|
4
|
+
class InvalidEventError < StandardError
|
5
|
+
attr_reader :event
|
6
|
+
|
7
|
+
def initialize(event)
|
8
|
+
@event = event
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"Event `#{@event}` is not allowed. Add it into your pusher's `events` class attribute"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def initialize(*events)
|
18
|
+
@events = Array(events).flatten
|
19
|
+
end
|
20
|
+
|
21
|
+
def validate(event)
|
22
|
+
# Allow strings and symbols only
|
23
|
+
# Return true if there are no whitelisted events
|
24
|
+
|
25
|
+
return false unless event.respond_to? :to_sym
|
26
|
+
|
27
|
+
return true unless @events.any?
|
28
|
+
|
29
|
+
@events.include?(event)
|
30
|
+
end
|
31
|
+
|
32
|
+
def any?
|
33
|
+
@events.any?
|
34
|
+
end
|
35
|
+
|
36
|
+
def validate!(event)
|
37
|
+
if validate(event) == false
|
38
|
+
raise InvalidEventError.new(event)
|
39
|
+
else
|
40
|
+
true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
class Pusher
|
3
|
+
class RecordChannel
|
4
|
+
CHANNEL_COLUMN = :channel
|
5
|
+
|
6
|
+
def initialize(record, event)
|
7
|
+
@record = record
|
8
|
+
@event = event
|
9
|
+
end
|
10
|
+
|
11
|
+
def channel
|
12
|
+
from_record_channel_column || from_record_class_name
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def from_record_channel_column
|
17
|
+
@record.send(CHANNEL_COLUMN) if @record.respond_to?(CHANNEL_COLUMN)
|
18
|
+
end
|
19
|
+
|
20
|
+
def from_record_class_name
|
21
|
+
if @event == :created
|
22
|
+
@record.class.name.pluralize.underscore.dasherize
|
23
|
+
else
|
24
|
+
[@record.class.name.pluralize.underscore.dasherize, @record.id].join('-')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
class Pusher
|
3
|
+
class RecordEventRecognizer
|
4
|
+
def initialize(record)
|
5
|
+
@record = record
|
6
|
+
end
|
7
|
+
|
8
|
+
def event
|
9
|
+
return nil unless can_be_recognized?
|
10
|
+
|
11
|
+
if created?
|
12
|
+
:created
|
13
|
+
elsif updated?
|
14
|
+
:updated
|
15
|
+
elsif destroyed?
|
16
|
+
:destroyed
|
17
|
+
else
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def can_be_recognized?
|
24
|
+
@record.respond_to? :previous_changes
|
25
|
+
end
|
26
|
+
|
27
|
+
def created?
|
28
|
+
@record.previous_changes.include? 'id'
|
29
|
+
end
|
30
|
+
|
31
|
+
def updated?
|
32
|
+
@record.previous_changes.any?
|
33
|
+
end
|
34
|
+
|
35
|
+
def destroyed?
|
36
|
+
@record.destroyed?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
class Pusher
|
3
|
+
class RecordSerializer
|
4
|
+
class RecordCannotBeSerializedError < StandardError
|
5
|
+
attr_reader :record
|
6
|
+
|
7
|
+
def initialize(record)
|
8
|
+
@record = record
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"#{@record} cannot be serialized."
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(record)
|
17
|
+
@record = record
|
18
|
+
end
|
19
|
+
|
20
|
+
def serialize!
|
21
|
+
raise RecordCannotBeSerializedError.new(@record) unless can_be_serialized?
|
22
|
+
|
23
|
+
serializer.as_json
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def serializer
|
28
|
+
if @record.respond_to?(:active_model_serializer)
|
29
|
+
serializer = @record.active_model_serializer
|
30
|
+
serializer.new @record
|
31
|
+
elsif @record.respond_to?(:as_json)
|
32
|
+
@record
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def can_be_serialized?
|
37
|
+
@record.respond_to?(:active_model_serializer) || @record.respond_to?(:as_json)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require "active_support/core_ext/string/inflections"
|
2
|
+
require "active_support/core_ext/class/attribute"
|
3
|
+
require "active_support/core_ext/object/try"
|
4
|
+
require "active_model/pusher"
|
5
|
+
require "active_model/pusher/record_channel"
|
6
|
+
require "active_model/pusher/record_event_recognizer"
|
7
|
+
require "active_model/pusher/record_serializer"
|
8
|
+
require "active_model/pusher/events"
|
9
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class PusherGenerator < Rails::Generators::NamedBase
|
2
|
+
source_root File.expand_path('../templates', __FILE__)
|
3
|
+
check_class_collision suffix: "Pusher"
|
4
|
+
argument :events, type: :array, default: [:created, :updated, :destroyed], banner: "event event"
|
5
|
+
|
6
|
+
|
7
|
+
def create_pusher_file
|
8
|
+
template 'pusher.rb', File.join('app/pushers', class_path, "#{file_name}_pusher.rb")
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveModel::Pusher::Events do
|
4
|
+
|
5
|
+
it 'accepts nothing' do
|
6
|
+
expect { ActiveModel::Pusher::Events.new }.to_not raise_error
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'accepts individual events' do
|
10
|
+
events = ActiveModel::Pusher::Events.new :created
|
11
|
+
|
12
|
+
events.validate!(:created).should be_true
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
it 'accepts array' do
|
17
|
+
events = ActiveModel::Pusher::Events.new [:created, :updated]
|
18
|
+
|
19
|
+
events.validate!(:updated).should be_true
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
it 'accepts indefinite params' do
|
24
|
+
events = ActiveModel::Pusher::Events.new :created, :updated
|
25
|
+
|
26
|
+
events.validate!(:updated).should be_true
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
describe '#validate!' do
|
31
|
+
it 'returns true if event is valid' do
|
32
|
+
ActiveModel::Pusher::Events.new([:created, :updated]).validate!(:created).should be_true
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'always returns true when there are no whitelisted events' do
|
36
|
+
ActiveModel::Pusher::Events.new.validate!(:created).should be_true
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'raises an exception if event is invalid' do
|
40
|
+
events = ActiveModel::Pusher::Events.new(:created)
|
41
|
+
expect { events.validate!(:updated) }.to raise_error(ActiveModel::Pusher::Events::InvalidEventError)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveModel::Pusher do
|
4
|
+
|
5
|
+
|
6
|
+
describe '#parse_push_params' do
|
7
|
+
before do
|
8
|
+
@pusher = AlienPusher.new(Class.new)
|
9
|
+
@event = :created
|
10
|
+
@params = { socket_id: 1234 }
|
11
|
+
end
|
12
|
+
|
13
|
+
it { @pusher.send(:parse_push_params, @event).should eq([@event, {}]) }
|
14
|
+
it { @pusher.send(:parse_push_params, @event, @params).should eq([@event, @params]) }
|
15
|
+
it { @pusher.send(:parse_push_params, @params).should eq([nil, @params]) }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#push!' do
|
19
|
+
it 'can be called with the event and params' do
|
20
|
+
alien = Alien.new
|
21
|
+
pusher = AlienPusher.new(alien)
|
22
|
+
params = { socket_id: 1234 }
|
23
|
+
Pusher.should_receive(:trigger).with('aliens', 'created', alien.as_json, params)
|
24
|
+
|
25
|
+
pusher.push!(:created, params)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'can be called without the event' do
|
29
|
+
alien = CreatedAlien.new
|
30
|
+
pusher = AlienPusher.new(alien)
|
31
|
+
|
32
|
+
Pusher.should_receive(:trigger).with('created-aliens', 'created', alien.as_json, {})
|
33
|
+
|
34
|
+
pusher.push!
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'can be called with params only' do
|
38
|
+
alien = CreatedAlien.new
|
39
|
+
pusher = AlienPusher.new(alien)
|
40
|
+
params = { socket_id: 1234 }
|
41
|
+
|
42
|
+
Pusher.should_receive(:trigger).with('created-aliens', 'created', alien.as_json, params)
|
43
|
+
|
44
|
+
pusher.push! params
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'allows overriding the `event` and `channel` method' do
|
48
|
+
alien = Alien.new
|
49
|
+
pusher = Class.new(AlienPusher) do
|
50
|
+
def event(event)
|
51
|
+
"custom-#{event}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def channel(event)
|
55
|
+
"custom-channel"
|
56
|
+
end
|
57
|
+
end.new(alien)
|
58
|
+
|
59
|
+
Pusher.should_receive(:trigger).with('custom-channel', 'custom-created', alien.as_json, {})
|
60
|
+
|
61
|
+
pusher.push! :created
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveModel::Pusher::RecordChannel do
|
4
|
+
describe '#channel' do
|
5
|
+
it "gets channel from record's channel column" do
|
6
|
+
|
7
|
+
record = Class.new do
|
8
|
+
def channel
|
9
|
+
'custom-channel'
|
10
|
+
end
|
11
|
+
end.new
|
12
|
+
|
13
|
+
record_channel = ActiveModel::Pusher::RecordChannel.new(record, nil)
|
14
|
+
record_channel.channel.should == 'custom-channel'
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'defaults to class name and record id if the record has no channel column' do
|
18
|
+
record = Alien.new
|
19
|
+
record_channel = ActiveModel::Pusher::RecordChannel.new(record, :updated)
|
20
|
+
record_channel.channel.should == 'aliens-1'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'defaults to pluralized class name if the record was just created and has no channel column' do
|
24
|
+
record = Alien.new
|
25
|
+
record_channel = ActiveModel::Pusher::RecordChannel.new(record, :created)
|
26
|
+
|
27
|
+
record_channel.channel.should == 'aliens'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveModel::Pusher::RecordEventRecognizer do
|
4
|
+
before do
|
5
|
+
@recognizer = ActiveModel::Pusher::RecordEventRecognizer
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'recognizes :created event' do
|
9
|
+
@recognizer.new(CreatedAlien.new).event.should == :created
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'recognizes :updated event' do
|
13
|
+
@recognizer.new(UpdatedAlien.new).event.should == :updated
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'recognizes :destroyed event' do
|
17
|
+
@recognizer.new(DestroyedAlien.new).event.should == :destroyed
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns nil when event cannot be recognized' do
|
21
|
+
@recognizer.new(Class.new).event.should be_nil
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveModel::Pusher::RecordSerializer do
|
4
|
+
before do
|
5
|
+
@serializer = ActiveModel::Pusher::RecordSerializer
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'serializes record with active_model_serializers gem' do
|
9
|
+
record = ActiveModelAlienWithSerializer.new
|
10
|
+
|
11
|
+
@serializer.new(record).serialize!.should eq({ id: 2 })
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'serializes record by calling as_json on it' do
|
15
|
+
record = Alien.new
|
16
|
+
|
17
|
+
@serializer.new(record).serialize!.should eq({ id: 1 })
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'prefers active_model_serializer to as_json' do
|
21
|
+
record = Class.new(ActiveModelAlienWithSerializer) do
|
22
|
+
def as_json
|
23
|
+
{ id: 1 }
|
24
|
+
end
|
25
|
+
end.new
|
26
|
+
|
27
|
+
@serializer.new(record).serialize!.should eq({ id: 2 })
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'raises an exception when record cannot be serialized' do
|
31
|
+
expect { @serializer.new(Class.new).serialize! }.to raise_error(ActiveModel::Pusher::RecordSerializer::RecordCannotBeSerializedError)
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'active_model_pusher'
|
2
|
+
|
3
|
+
class Pusher
|
4
|
+
def self.trigger(channel, event, json, params = {})
|
5
|
+
true
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class AlienPusher < ActiveModel::Pusher
|
10
|
+
events :created
|
11
|
+
end
|
12
|
+
|
13
|
+
class Alien
|
14
|
+
def id
|
15
|
+
1
|
16
|
+
end
|
17
|
+
|
18
|
+
def as_json
|
19
|
+
{ id: 1 }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class ActiveModelAlien < Alien
|
24
|
+
def previous_changes
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
class ActiveModelAlienWithSerializer < ActiveModelAlien
|
32
|
+
class ActiveModelSerializer
|
33
|
+
def initialize(record)
|
34
|
+
end
|
35
|
+
def as_json
|
36
|
+
{ id: 2 }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def active_model_serializer
|
41
|
+
ActiveModelSerializer
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
class CreatedAlien < ActiveModelAlien
|
47
|
+
def previous_changes
|
48
|
+
{ 'id' => [nil, 1] }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class UpdatedAlien < ActiveModelAlien
|
53
|
+
def previous_changes
|
54
|
+
{ 'planet_id' => [1, 2] }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class DestroyedAlien < ActiveModelAlien
|
59
|
+
def destroyed?
|
60
|
+
true
|
61
|
+
end
|
62
|
+
end
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active_model_pusher
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alexander Zaytsev
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-26 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activemodel
|
16
|
+
requirement: &2152717000 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2152717000
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: pusher
|
27
|
+
requirement: &2152716580 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2152716580
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec
|
38
|
+
requirement: &2152716120 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2152716120
|
47
|
+
description: Making it easy to use Pusher with your models
|
48
|
+
email:
|
49
|
+
- alexander@say26.com
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- .gitignore
|
55
|
+
- .rspec
|
56
|
+
- CHANGELOG.md
|
57
|
+
- Gemfile
|
58
|
+
- LICENSE
|
59
|
+
- README.md
|
60
|
+
- Rakefile
|
61
|
+
- active_model_pusher.gemspec
|
62
|
+
- lib/active_model/pusher.rb
|
63
|
+
- lib/active_model/pusher/events.rb
|
64
|
+
- lib/active_model/pusher/record_channel.rb
|
65
|
+
- lib/active_model/pusher/record_event_recognizer.rb
|
66
|
+
- lib/active_model/pusher/record_serializer.rb
|
67
|
+
- lib/active_model/pusher/version.rb
|
68
|
+
- lib/active_model_pusher.rb
|
69
|
+
- lib/generators/pusher/USAGE
|
70
|
+
- lib/generators/pusher/pusher_generator.rb
|
71
|
+
- lib/generators/pusher/templates/pusher.rb
|
72
|
+
- spec/active_model_pusher/events_spec.rb
|
73
|
+
- spec/active_model_pusher/pusher_spec.rb
|
74
|
+
- spec/active_model_pusher/record_channel_spec.rb
|
75
|
+
- spec/active_model_pusher/record_event_recognizer.rb
|
76
|
+
- spec/active_model_pusher/record_serializer.rb
|
77
|
+
- spec/spec_helper.rb
|
78
|
+
homepage: https://github.com/AlexanderZaytsev/active_model_pusher
|
79
|
+
licenses: []
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 1.8.15
|
99
|
+
signing_key:
|
100
|
+
specification_version: 3
|
101
|
+
summary: Push your models with Pusher easily
|
102
|
+
test_files:
|
103
|
+
- spec/active_model_pusher/events_spec.rb
|
104
|
+
- spec/active_model_pusher/pusher_spec.rb
|
105
|
+
- spec/active_model_pusher/record_channel_spec.rb
|
106
|
+
- spec/active_model_pusher/record_event_recognizer.rb
|
107
|
+
- spec/active_model_pusher/record_serializer.rb
|
108
|
+
- spec/spec_helper.rb
|