apn_on_rails 0.2.0 → 0.2.2

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/README CHANGED
@@ -94,10 +94,15 @@ That's it, now you're ready to start creating notifications.
94
94
  >> notification.sound = true
95
95
  >> notification.alert = "foobar"
96
96
  >> notification.save
97
- >> APN::Notification.send_notifications
98
97
 
99
- You can also run the following Rake task to send your notifications:
98
+ You can use the following Rake task to deliver your notifications:
100
99
 
101
100
  $ rake apn:notifications:deliver
102
101
 
102
+ The Rake task will find any unsent notifications in the database. If there aren't any notifications
103
+ it will simply do nothing. If there are notifications waiting to be delivered it will open a single connection
104
+ to Apple and push all the notifications through that one connection. Apple does not like people opening/closing
105
+ connections constantly, so it's pretty important that you are careful about batching up your notifications so
106
+ Apple doesn't shut you down.
107
+
103
108
  Released under the MIT license.
@@ -4,10 +4,22 @@ class ApnMigrationsGenerator < Rails::Generator::Base
4
4
 
5
5
  def manifest # :nodoc:
6
6
  record do |m|
7
- [:create_apn_devices, :create_apn_notifications].each do |f|
8
- m.migration_template(File.join('apn_migrations', "#{f}.rb"), "db/migrate", {:migration_file_name => f, :collision => :skip})
7
+ timestamp = Time.now.utc.strftime("%Y%m%d%H%M%S")
8
+ db_migrate_path = File.join('db', 'migrate')
9
+
10
+ m.directory(db_migrate_path)
11
+
12
+ ['001_create_apn_devices', '002_create_apn_notifications'].each_with_index do |f, i|
13
+ timestamp = timestamp.succ
14
+ if Dir.glob(File.join(db_migrate_path, "*_#{f}.rb")).empty?
15
+ m.file(File.join('apn_migrations', "#{f}.rb"),
16
+ File.join(db_migrate_path, "#{timestamp}_#{f}.rb"),
17
+ {:collision => :skip})
18
+ end
9
19
  end
10
- end
11
- end
20
+
21
+ end # record
22
+
23
+ end # manifest
12
24
 
13
- end
25
+ end # ApnMigrationsGenerator
@@ -14,12 +14,22 @@ end
14
14
 
15
15
  configatron.apn.set_default(:passphrase, '')
16
16
  configatron.apn.set_default(:port, 2195)
17
- configatron.apn.set_default(:host, 'gateway.sandbox.push.apple.com')
18
- configatron.apn.set_default(:cert, File.join(rails_root, 'config', 'apple_push_notification_development.pem'))
17
+
18
+ configatron.apn.feedback.set_default(:passphrase, configatron.apn.passphrase)
19
+ configatron.apn.feedback.set_default(:port, 2196)
19
20
 
20
21
  if rails_env == 'production'
21
22
  configatron.apn.set_default(:host, 'gateway.push.apple.com')
22
23
  configatron.apn.set_default(:cert, File.join(rails_root, 'config', 'apple_push_notification_production.pem'))
24
+
25
+ configatron.apn.feedback.set_default(:host, 'feedback.push.apple.com')
26
+ configatron.apn.feedback.set_default(:cert, configatron.apn.cert)
27
+ else
28
+ configatron.apn.set_default(:host, 'gateway.sandbox.push.apple.com')
29
+ configatron.apn.set_default(:cert, File.join(rails_root, 'config', 'apple_push_notification_development.pem'))
30
+
31
+ configatron.apn.feedback.set_default(:host, 'feedback.sandbox.push.apple.com')
32
+ configatron.apn.feedback.set_default(:cert, configatron.apn.cert)
23
33
  end
24
34
 
25
35
  module APN # :nodoc:
@@ -0,0 +1,65 @@
1
+ module APN
2
+ module Connection
3
+
4
+ class << self
5
+
6
+ # Yields up an SSL socket to write notifications to.
7
+ # The connections are close automatically.
8
+ #
9
+ # Example:
10
+ # APN::Configuration.open_for_delivery do |conn|
11
+ # conn.write('my cool notification')
12
+ # end
13
+ #
14
+ # Configuration parameters are:
15
+ #
16
+ # configatron.apn.passphrase = ''
17
+ # configatron.apn.port = 2195
18
+ # configatron.apn.host = 'gateway.sandbox.push.apple.com' # Development
19
+ # configatron.apn.host = 'gateway.push.apple.com' # Production
20
+ # configatron.apn.cert = File.join(rails_root, 'config', 'apple_push_notification_development.pem')) # Development
21
+ # configatron.apn.cert = File.join(rails_root, 'config', 'apple_push_notification_production.pem')) # Production
22
+ def open_for_delivery(options = {}, &block)
23
+ open(options, &block)
24
+ end
25
+
26
+ # Yields up an SSL socket to receive feedback from.
27
+ # The connections are close automatically.
28
+ # Configuration parameters are:
29
+ #
30
+ # configatron.apn.feedback.passphrase = ''
31
+ # configatron.apn.feedback.port = 2196
32
+ # configatron.apn.feedback.host = 'feedback.sandbox.push.apple.com' # Development
33
+ # configatron.apn.feedback.host = 'feedback.push.apple.com' # Production
34
+ # configatron.apn.feedback.cert = File.join(rails_root, 'config', 'apple_push_notification_development.pem')) # Development
35
+ # configatron.apn.feedback.cert = File.join(rails_root, 'config', 'apple_push_notification_production.pem')) # Production
36
+ def open_for_feedback(options = {}, &block) # :nodoc:
37
+
38
+ end
39
+
40
+ private
41
+ def open(options = {}, &block) # :nodoc:
42
+ options = {:cert => configatron.apn.cert,
43
+ :passphrase => configatron.apn.passphrase,
44
+ :host => configatron.apn.host,
45
+ :port => configatron.apn.port}.merge(options)
46
+ cert = File.read(options[:cert])
47
+ ctx = OpenSSL::SSL::SSLContext.new
48
+ ctx.key = OpenSSL::PKey::RSA.new(cert, options[:passphrase])
49
+ ctx.cert = OpenSSL::X509::Certificate.new(cert)
50
+
51
+ s = TCPSocket.new(options[:host], options[:port])
52
+ ssl = OpenSSL::SSL::SSLSocket.new(s, ctx)
53
+ ssl.sync = true
54
+ ssl.connect
55
+
56
+ yield ssl if block_given?
57
+
58
+ ssl.close
59
+ s.close
60
+ end
61
+
62
+ end
63
+
64
+ end # Connection
65
+ end # APN
@@ -86,25 +86,15 @@ class APN::Notification < ActiveRecord::Base
86
86
  # so as to not be sent again.
87
87
  def send_notifications(notifications = APN::Notification.all(:conditions => {:sent_at => nil}))
88
88
  unless notifications.nil? || notifications.empty?
89
- logger.info "APN: Attempting to deliver #{pluralize(notifications.size, 'notification')}."
90
- cert = File.read(configatron.apn.cert)
91
- ctx = OpenSSL::SSL::SSLContext.new
92
- ctx.key = OpenSSL::PKey::RSA.new(cert, configatron.apn.passphrase)
93
- ctx.cert = OpenSSL::X509::Certificate.new(cert)
94
-
95
- s = TCPSocket.new(configatron.apn.host, configatron.apn.port)
96
- ssl = OpenSSL::SSL::SSLSocket.new(s, ctx)
97
- ssl.sync = true
98
- ssl.connect
99
-
100
- notifications.each do |noty|
101
- ssl.write(noty.message_for_sending)
102
- noty.sent_at = Time.now
103
- noty.save
89
+
90
+ APN::Connection.open_for_delivery do |conn|
91
+ notifications.each do |noty|
92
+ conn.write(noty.message_for_sending)
93
+ noty.sent_at = Time.now
94
+ noty.save
95
+ end
104
96
  end
105
-
106
- ssl.close
107
- s.close
97
+
108
98
  end
109
99
  end
110
100
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apn_on_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - markbates
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-26 00:00:00 -04:00
12
+ date: 2009-07-30 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -33,6 +33,7 @@ extra_rdoc_files:
33
33
  - LICENSE
34
34
  files:
35
35
  - lib/apn_on_rails/apn_on_rails.rb
36
+ - lib/apn_on_rails/app/models/apn/connection.rb
36
37
  - lib/apn_on_rails/app/models/apn/device.rb
37
38
  - lib/apn_on_rails/app/models/apn/notification.rb
38
39
  - lib/apn_on_rails/tasks/apn.rake
@@ -42,8 +43,8 @@ files:
42
43
  - README
43
44
  - LICENSE
44
45
  - generators/apn_migrations_generator.rb
45
- - generators/templates/apn_migrations/create_apn_devices.rb
46
- - generators/templates/apn_migrations/create_apn_notifications.rb
46
+ - generators/templates/apn_migrations/001_create_apn_devices.rb
47
+ - generators/templates/apn_migrations/002_create_apn_notifications.rb
47
48
  has_rdoc: true
48
49
  homepage: http://www.metabates.com
49
50
  licenses: []