rapns 2.0.1 → 2.0.3
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/CHANGELOG.md +8 -0
- data/README.md +6 -4
- data/bin/rapns +1 -1
- data/lib/rapns/app.rb +2 -0
- data/lib/rapns/daemon/database_reconnectable.rb +4 -1
- data/lib/rapns/daemon.rb +2 -1
- data/lib/rapns/feedback.rb +2 -0
- data/lib/rapns/notification.rb +25 -6
- data/lib/rapns/version.rb +1 -1
- data/spec/rapns/daemon/database_reconnectable_spec.rb +2 -0
- data/spec/rapns/daemon_spec.rb +11 -11
- data/spec/rapns/notification_spec.rb +34 -0
- data/spec/spec_helper.rb +23 -3
- metadata +5 -5
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## 2.0.3 (July 26, 2012) ##
|
2
|
+
* JRuby support.
|
3
|
+
* Explicitly list all attributes instead of calling column_names (#53).
|
4
|
+
|
5
|
+
## 2.0.2 (July 25, 2012) ##
|
6
|
+
* Support MultiJson < 1.3.0.
|
7
|
+
* Make all model attributes accessible.
|
8
|
+
|
1
9
|
## 2.0.1 (July 7, 2012) ##
|
2
10
|
* Fix delivery when using Ruby 1.8.
|
3
11
|
* MultiJson support.
|
data/README.md
CHANGED
@@ -24,7 +24,7 @@
|
|
24
24
|
Add rapns to your Gemfile:
|
25
25
|
|
26
26
|
gem 'rapns'
|
27
|
-
|
27
|
+
|
28
28
|
Generate the migration, rapns.yml and migrate:
|
29
29
|
|
30
30
|
rails g rapns
|
@@ -62,7 +62,7 @@ Generate the migration, rapns.yml and migrate:
|
|
62
62
|
|
63
63
|
cd /path/to/rails/app
|
64
64
|
bundle exec rapns <Rails environment> [options]
|
65
|
-
|
65
|
+
|
66
66
|
### Options
|
67
67
|
|
68
68
|
* `-f` `--foreground` Prevent rapns from forking into a daemon.
|
@@ -125,7 +125,7 @@ Although rapns makes such errors highly unlikely due to validation, the APNs rep
|
|
125
125
|
`error` is set to Apple's code for the error.
|
126
126
|
`error_description` is set to a (somewhat brief) description of the error.
|
127
127
|
|
128
|
-
rapns will not attempt to deliver the notification again.
|
128
|
+
rapns will not attempt to deliver the notification again.
|
129
129
|
|
130
130
|
### Via the Feedback Service.
|
131
131
|
|
@@ -141,6 +141,7 @@ After updating you should run `rails g rapns` to check for any new migrations.
|
|
141
141
|
|
142
142
|
## Wiki
|
143
143
|
|
144
|
+
* [Deploying to Heroku](https://github.com/ileitch/rapns/wiki/Heroku)
|
144
145
|
* [Why open multiple connections to the APNs?](https://github.com/ileitch/rapns/wiki/Why-open-multiple-connections-to-the-APNs%3F)
|
145
146
|
|
146
147
|
## Contributing to rapns
|
@@ -162,4 +163,5 @@ Thank you to the following wonderful people for contributing to rapns:
|
|
162
163
|
* [@taybenlor](https://github.com/taybenlor)
|
163
164
|
* [@tompesman](https://github.com/tompesman)
|
164
165
|
* [@EpicDraws](https://github.com/EpicDraws)
|
165
|
-
* [@dei79](https://github.com/dei79)
|
166
|
+
* [@dei79](https://github.com/dei79)
|
167
|
+
* [@adorr](https://github.com/adorr)
|
data/bin/rapns
CHANGED
data/lib/rapns/app.rb
CHANGED
@@ -2,6 +2,8 @@ module Rapns
|
|
2
2
|
class App < ActiveRecord::Base
|
3
3
|
self.table_name = 'rapns_apps'
|
4
4
|
|
5
|
+
attr_accessible :key, :environment, :certificate, :password, :connections
|
6
|
+
|
5
7
|
validates :key, :presence => true, :uniqueness => true
|
6
8
|
validates :environment, :presence => true, :inclusion => { :in => %w(development production) }
|
7
9
|
validates :certificate, :presence => true
|
@@ -1,11 +1,14 @@
|
|
1
1
|
class PGError < StandardError; end if !defined?(PGError)
|
2
2
|
class Mysql; class Error < StandardError; end; end if !defined?(Mysql)
|
3
3
|
module Mysql2; class Error < StandardError; end; end if !defined?(Mysql2)
|
4
|
+
module ActiveRecord; end
|
5
|
+
class ActiveRecord::JDBCError < StandardError; end if !defined?(ActiveRecord::JDBCError)
|
4
6
|
|
5
7
|
module Rapns
|
6
8
|
module Daemon
|
7
9
|
module DatabaseReconnectable
|
8
|
-
ADAPTER_ERRORS = [ActiveRecord::StatementInvalid, PGError, Mysql::Error,
|
10
|
+
ADAPTER_ERRORS = [ActiveRecord::StatementInvalid, PGError, Mysql::Error,
|
11
|
+
Mysql2::Error, ActiveRecord::JDBCError]
|
9
12
|
|
10
13
|
def with_database_reconnect_and_retry
|
11
14
|
begin
|
data/lib/rapns/daemon.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'thread'
|
2
2
|
require 'socket'
|
3
3
|
require 'pathname'
|
4
|
+
require 'openssl'
|
4
5
|
|
5
6
|
require 'rapns/daemon/interruptible_sleep'
|
6
7
|
require 'rapns/daemon/delivery_error'
|
@@ -23,7 +24,7 @@ module Rapns
|
|
23
24
|
attr_accessor :logger, :config
|
24
25
|
end
|
25
26
|
|
26
|
-
def self.start(
|
27
|
+
def self.start(config)
|
27
28
|
self.config = config
|
28
29
|
self.logger = Logger.new(:foreground => config.foreground, :airbrake_notify => config.airbrake_notify)
|
29
30
|
setup_signal_hooks
|
data/lib/rapns/feedback.rb
CHANGED
data/lib/rapns/notification.rb
CHANGED
@@ -2,6 +2,9 @@ module Rapns
|
|
2
2
|
class Notification < ActiveRecord::Base
|
3
3
|
self.table_name = 'rapns_notifications'
|
4
4
|
|
5
|
+
attr_accessible :badge, :device_token, :sound, :alert, :attributes_for_device, :expiry,:delivered,
|
6
|
+
:delivered_at, :failed, :failed_at, :error_code, :error_description, :deliver_after, :alert_is_json, :app
|
7
|
+
|
5
8
|
validates :app, :presence => true
|
6
9
|
validates :device_token, :presence => true
|
7
10
|
validates :badge, :numericality => true, :allow_nil => true
|
@@ -18,7 +21,7 @@ module Rapns
|
|
18
21
|
|
19
22
|
def alert=(alert)
|
20
23
|
if alert.is_a?(Hash)
|
21
|
-
write_attribute(:alert,
|
24
|
+
write_attribute(:alert, multi_json_dump(alert))
|
22
25
|
self.alert_is_json = true if has_attribute?(:alert_is_json)
|
23
26
|
else
|
24
27
|
write_attribute(:alert, alert)
|
@@ -31,22 +34,22 @@ module Rapns
|
|
31
34
|
|
32
35
|
if has_attribute?(:alert_is_json)
|
33
36
|
if alert_is_json?
|
34
|
-
|
37
|
+
multi_json_load(string_or_json)
|
35
38
|
else
|
36
39
|
string_or_json
|
37
40
|
end
|
38
41
|
else
|
39
|
-
|
42
|
+
multi_json_load(string_or_json) rescue string_or_json
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
43
46
|
def attributes_for_device=(attrs)
|
44
47
|
raise ArgumentError, "attributes_for_device must be a Hash" if !attrs.is_a?(Hash)
|
45
|
-
write_attribute(:attributes_for_device,
|
48
|
+
write_attribute(:attributes_for_device, multi_json_dump(attrs))
|
46
49
|
end
|
47
50
|
|
48
51
|
def attributes_for_device
|
49
|
-
|
52
|
+
multi_json_load(read_attribute(:attributes_for_device)) if read_attribute(:attributes_for_device)
|
50
53
|
end
|
51
54
|
|
52
55
|
MDM_OVERIDE_KEY = '__rapns_mdm__'
|
@@ -71,7 +74,7 @@ module Rapns
|
|
71
74
|
end
|
72
75
|
|
73
76
|
def payload
|
74
|
-
|
77
|
+
multi_json_dump(as_json)
|
75
78
|
end
|
76
79
|
|
77
80
|
def payload_size
|
@@ -84,5 +87,21 @@ module Rapns
|
|
84
87
|
id_for_pack = options[:for_validation] ? 0 : id
|
85
88
|
[1, id_for_pack, expiry, 0, 32, device_token, payload_size, payload].pack("cNNccH*na*")
|
86
89
|
end
|
90
|
+
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def multi_json_load(string, options = {})
|
95
|
+
# Calling load on multi_json less than v1.3.0 attempts to load a file from disk. Check the version explicitly.
|
96
|
+
if Gem.loaded_specs['multi_json'].version >= Gem::Version.create('1.3.0')
|
97
|
+
MultiJson.load(string, options)
|
98
|
+
else
|
99
|
+
MultiJson.decode(string, options)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def multi_json_dump(string, options = {})
|
104
|
+
MultiJson.respond_to?(:dump) ? MultiJson.dump(string, options) : MultiJson.encode(string, options)
|
105
|
+
end
|
87
106
|
end
|
88
107
|
end
|
data/lib/rapns/version.rb
CHANGED
data/spec/rapns/daemon_spec.rb
CHANGED
@@ -21,45 +21,45 @@ describe Rapns::Daemon, "when starting" do
|
|
21
21
|
config.stub(:foreground => false)
|
22
22
|
ActiveRecord::Base.stub(:establish_connection)
|
23
23
|
Rapns::Daemon.should_receive(:daemonize)
|
24
|
-
Rapns::Daemon.start(
|
24
|
+
Rapns::Daemon.start(config)
|
25
25
|
end
|
26
26
|
|
27
27
|
it "does not fork into a daemon if the foreground option is true" do
|
28
28
|
config.stub(:foreground => true)
|
29
29
|
Rapns::Daemon.should_not_receive(:daemonize)
|
30
|
-
Rapns::Daemon.start(
|
30
|
+
Rapns::Daemon.start(config)
|
31
31
|
end
|
32
32
|
|
33
33
|
it "writes the process ID to the PID file" do
|
34
34
|
Rapns::Daemon.should_receive(:write_pid_file)
|
35
|
-
Rapns::Daemon.start(
|
35
|
+
Rapns::Daemon.start(config)
|
36
36
|
end
|
37
37
|
|
38
38
|
it "logs an error if the PID file could not be written" do
|
39
39
|
config.stub(:pid_file => '/rails_root/rapns.pid')
|
40
40
|
File.stub(:open).and_raise(Errno::ENOENT)
|
41
41
|
logger.should_receive(:error).with("Failed to write PID to '/rails_root/rapns.pid': #<Errno::ENOENT: No such file or directory>")
|
42
|
-
Rapns::Daemon.start(
|
42
|
+
Rapns::Daemon.start(config)
|
43
43
|
end
|
44
44
|
|
45
45
|
it "starts the feeder" do
|
46
46
|
Rapns::Daemon::Feeder.should_receive(:start).with(2)
|
47
|
-
Rapns::Daemon.start(
|
47
|
+
Rapns::Daemon.start(config)
|
48
48
|
end
|
49
49
|
|
50
50
|
it "syncs apps" do
|
51
51
|
Rapns::Daemon::AppRunner.should_receive(:sync)
|
52
|
-
Rapns::Daemon.start(
|
52
|
+
Rapns::Daemon.start(config)
|
53
53
|
end
|
54
54
|
|
55
55
|
it "sets up the logger" do
|
56
56
|
config.stub(:airbrake_notify => true)
|
57
57
|
Rapns::Daemon::Logger.should_receive(:new).with(:foreground => true, :airbrake_notify => true)
|
58
|
-
Rapns::Daemon.start(
|
58
|
+
Rapns::Daemon.start(config)
|
59
59
|
end
|
60
60
|
|
61
61
|
it "makes the logger accessible" do
|
62
|
-
Rapns::Daemon.start(
|
62
|
+
Rapns::Daemon.start(config)
|
63
63
|
Rapns::Daemon.logger.should == logger
|
64
64
|
end
|
65
65
|
|
@@ -67,20 +67,20 @@ describe Rapns::Daemon, "when starting" do
|
|
67
67
|
Rapns::App.stub(:count => 0)
|
68
68
|
Rapns::Daemon.should_receive(:puts).any_number_of_times
|
69
69
|
Rapns::Daemon.should_receive(:exit).with(1)
|
70
|
-
Rapns::Daemon.start(
|
70
|
+
Rapns::Daemon.start(config)
|
71
71
|
end
|
72
72
|
|
73
73
|
it 'prints a warning exists if rapns has not been upgraded' do
|
74
74
|
Rapns::App.stub(:count).and_raise(ActiveRecord::StatementInvalid)
|
75
75
|
Rapns::Daemon.should_receive(:puts).any_number_of_times
|
76
76
|
Rapns::Daemon.should_receive(:exit).with(1)
|
77
|
-
Rapns::Daemon.start(
|
77
|
+
Rapns::Daemon.start(config)
|
78
78
|
end
|
79
79
|
|
80
80
|
it 'warns if rapns.yml still exists' do
|
81
81
|
File.should_receive(:exists?).with('/rails_root/config/rapns/rapns.yml').and_return(true)
|
82
82
|
logger.should_receive(:warn).with("Since 2.0.0 rapns uses command-line options instead of a configuration file. Please remove config/rapns/rapns.yml.")
|
83
|
-
Rapns::Daemon.start(
|
83
|
+
Rapns::Daemon.start(config)
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
@@ -161,4 +161,38 @@ describe Rapns::Notification, "bug #35" do
|
|
161
161
|
notification.payload_size.should < 256
|
162
162
|
notification.should be_valid
|
163
163
|
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe Rapns::Notification, "multi_json usage" do
|
167
|
+
describe Rapns::Notification, "alert" do
|
168
|
+
it "should call MultiJson.load when multi_json version is 1.3.0" do
|
169
|
+
notification = Rapns::Notification.new(:alert => { :a => 1 }, :alert_is_json => true)
|
170
|
+
Gem.stub(:loaded_specs).and_return( { 'multi_json' => Gem::Specification.new('multi_json', '1.3.0') } )
|
171
|
+
MultiJson.should_receive(:load).with(any_args())
|
172
|
+
notification.alert
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should call MultiJson.decode when multi_json version is 1.2.9" do
|
176
|
+
notification = Rapns::Notification.new(:alert => { :a => 1 }, :alert_is_json => true)
|
177
|
+
Gem.stub(:loaded_specs).and_return( { 'multi_json' => Gem::Specification.new('multi_json', '1.2.9') } )
|
178
|
+
MultiJson.should_receive(:decode).with(any_args())
|
179
|
+
notification.alert
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe Rapns::Notification, "attributes_for_device=" do
|
184
|
+
it "should call MultiJson.dump when multi_json responds to :dump" do
|
185
|
+
notification = Rapns::Notification.new
|
186
|
+
MultiJson.stub(:respond_to?).with(:dump).and_return(true)
|
187
|
+
MultiJson.should_receive(:dump).with(any_args())
|
188
|
+
notification.attributes_for_device = { :pirates => 1 }
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should call MultiJson.encode when multi_json does not respond to :dump" do
|
192
|
+
notification = Rapns::Notification.new
|
193
|
+
MultiJson.stub(:respond_to?).with(:dump).and_return(false)
|
194
|
+
MultiJson.should_receive(:encode).with(any_args())
|
195
|
+
notification.attributes_for_device = { :ninjas => 1 }
|
196
|
+
end
|
197
|
+
end
|
164
198
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -10,8 +10,28 @@ rescue LoadError
|
|
10
10
|
end
|
11
11
|
|
12
12
|
require 'active_record'
|
13
|
-
adapters = ['mysql', 'mysql2', 'postgresql']
|
14
|
-
|
13
|
+
adapters = ['mysql', 'mysql2', 'postgresql', 'jdbcpostgresql']
|
14
|
+
|
15
|
+
jruby = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
16
|
+
|
17
|
+
$adapter = if ENV['ADAPTER']
|
18
|
+
ENV['ADAPTER']
|
19
|
+
elsif jruby
|
20
|
+
'jdbcpostgresql'
|
21
|
+
else
|
22
|
+
'postgresql'
|
23
|
+
end
|
24
|
+
|
25
|
+
if jruby
|
26
|
+
if ENV['TRAVIS']
|
27
|
+
username = 'postgres'
|
28
|
+
else
|
29
|
+
require 'etc'
|
30
|
+
username = Etc.getlogin
|
31
|
+
end
|
32
|
+
else
|
33
|
+
username = nil
|
34
|
+
end
|
15
35
|
|
16
36
|
if !adapters.include?($adapter)
|
17
37
|
puts "No such adapter '#{$adapter}'. Valid adapters are #{adapters.join(', ')}."
|
@@ -20,7 +40,7 @@ end
|
|
20
40
|
|
21
41
|
puts "Using #{$adapter} adapter."
|
22
42
|
|
23
|
-
ActiveRecord::Base.establish_connection('adapter' => $adapter, 'database' => 'rapns_test')
|
43
|
+
ActiveRecord::Base.establish_connection('username' => username, 'adapter' => $adapter, 'database' => 'rapns_test')
|
24
44
|
require 'generators/templates/create_rapns_notifications'
|
25
45
|
require 'generators/templates/create_rapns_feedback'
|
26
46
|
require 'generators/templates/add_alert_is_json_to_rapns_notifications'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rapns
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: multi_json
|
@@ -27,8 +27,7 @@ dependencies:
|
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '1.0'
|
30
|
-
description: Easy to use
|
31
|
-
3
|
30
|
+
description: Easy to use, full featured APNs daemon for Rails 3
|
32
31
|
email:
|
33
32
|
- port001@gmail.com
|
34
33
|
executables:
|
@@ -109,7 +108,7 @@ rubyforge_project:
|
|
109
108
|
rubygems_version: 1.8.23
|
110
109
|
signing_key:
|
111
110
|
specification_version: 3
|
112
|
-
summary: Easy to use
|
111
|
+
summary: Easy to use, full featured APNs daemon for Rails 3
|
113
112
|
test_files:
|
114
113
|
- spec/rapns/daemon/app_runner_spec.rb
|
115
114
|
- spec/rapns/daemon/connection_spec.rb
|
@@ -126,3 +125,4 @@ test_files:
|
|
126
125
|
- spec/rapns/feedback_spec.rb
|
127
126
|
- spec/rapns/notification_spec.rb
|
128
127
|
- spec/spec_helper.rb
|
128
|
+
has_rdoc:
|