rapns 2.0.1 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -43,4 +43,4 @@ if config.pid_file && !Pathname.new(config.pid_file).absolute?
43
43
  config.pid_file = File.join(Rails.root, config.pid_file)
44
44
  end
45
45
 
46
- Rapns::Daemon.start(environment, config)
46
+ Rapns::Daemon.start(config)
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, Mysql2::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(environment, config)
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
@@ -2,6 +2,8 @@ module Rapns
2
2
  class Feedback < ActiveRecord::Base
3
3
  self.table_name = 'rapns_feedback'
4
4
 
5
+ attr_accessible :device_token, :failed_at, :app
6
+
5
7
  validates :device_token, :presence => true
6
8
  validates :failed_at, :presence => true
7
9
 
@@ -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, MultiJson.dump(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
- MultiJson.load(string_or_json)
37
+ multi_json_load(string_or_json)
35
38
  else
36
39
  string_or_json
37
40
  end
38
41
  else
39
- MultiJson.load(string_or_json) rescue string_or_json
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, MultiJson.dump(attrs))
48
+ write_attribute(:attributes_for_device, multi_json_dump(attrs))
46
49
  end
47
50
 
48
51
  def attributes_for_device
49
- MultiJson.load(read_attribute(:attributes_for_device)) if read_attribute(:attributes_for_device)
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
- MultiJson.dump(as_json)
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
@@ -1,3 +1,3 @@
1
1
  module Rapns
2
- VERSION = '2.0.1'
2
+ VERSION = '2.0.3'
3
3
  end
@@ -29,6 +29,8 @@ describe Rapns::Daemon::DatabaseReconnectable do
29
29
  Mysql::Error
30
30
  when 'mysql2'
31
31
  Mysql2::Error
32
+ when 'jdbcpostgresql'
33
+ ActiveRecord::JDBCError
32
34
  else
33
35
  raise "Please update #{__FILE__} for adapter #{$adapter}"
34
36
  end
@@ -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("development", config)
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("development", config)
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("development", config)
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("development", config)
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("development", config)
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("development", config)
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("development", config)
58
+ Rapns::Daemon.start(config)
59
59
  end
60
60
 
61
61
  it "makes the logger accessible" do
62
- Rapns::Daemon.start("development", config)
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("development", config)
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("development", config)
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("development", config)
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
- $adapter = ENV['ADAPTER'] || 'postgresql'
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.1
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-08 00:00:00.000000000 Z
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 library for Apple's Push Notification Service with Rails
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 library for Apple's Push Notification Service with Rails 3
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: