Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Fix send message #47

Open
wants to merge 12 commits into from

1 participant

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 27, 2012
  1. @niku

    training whitespace

    niku authored
  2. @niku

    fix "RangeError: 256 out of char range", because Integer#chr handles …

    niku authored
    …255 at most, but the value to be 256.
  3. @niku
  4. @niku

    fix spec checking condition

    niku authored
  5. @niku

    training whitespace

    niku authored
  6. @niku

    fix "RangeError: 256 out of char range", because Integer#chr handles …

    niku authored
    …255 at most, but the value to be 256.
  7. @niku
  8. @niku

    fix spec checking condition

    niku authored
  9. @niku

    training whitespace

    niku authored
  10. @niku

    fix working on ruby19

    niku authored
  11. @niku
  12. @niku
This page is out of date. Refresh to see the latest.
View
36 lib/apn_on_rails/app/models/apn/group_notification.rb
@@ -2,19 +2,19 @@ class APN::GroupNotification < APN::Base
include ::ActionView::Helpers::TextHelper
extend ::ActionView::Helpers::TextHelper
serialize :custom_properties
-
+
belongs_to :group, :class_name => 'APN::Group'
has_one :app, :class_name => 'APN::App', :through => :group
has_many :device_groupings, :through => :group
-
+
validates_presence_of :group_id
-
+
def devices
self.group.devices
end
-
+
# Stores the text alert message you want to send to the device.
- #
+ #
# If the message is over 150 characters long it will get truncated
# to 150 characters with a <tt>...</tt>
def alert=(message)
@@ -23,9 +23,9 @@ def alert=(message)
end
write_attribute('alert', message)
end
-
+
# Creates a Hash that will be the payload of an APN.
- #
+ #
# Example:
# apn = APN::GroupNotification.new
# apn.badge = 5
@@ -33,7 +33,7 @@ def alert=(message)
# apn.alert = 'Hello!'
# apn.apple_hash # => {"aps" => {"badge" => 5, "sound" => "my_sound.aiff", "alert" => "Hello!"}}
#
- # Example 2:
+ # Example 2:
# apn = APN::GroupNotification.new
# apn.badge = 0
# apn.sound = true
@@ -55,9 +55,9 @@ def apple_hash
end
result
end
-
+
# Creates the JSON string required for an APN message.
- #
+ #
# Example:
# apn = APN::Notification.new
# apn.badge = 5
@@ -67,13 +67,17 @@ def apple_hash
def to_apple_json
self.apple_hash.to_json
end
-
+
# Creates the binary message needed to send to Apple.
def message_for_sending(device)
- json = self.to_apple_json
- message = "\0\0 #{device.to_hexa}\0#{json.length.chr}#{json}"
- raise APN::Errors::ExceededMessageSizeError.new(message) if message.size.to_i > 256
+ command = ['0'].pack('H') # Now, APN_ON_RAILS implements only "simple notification format".
+ token = device.to_hexa
+ token_length = [token.bytesize].pack('n')
+ payload = self.to_apple_json
+ payload_length = [payload.bytesize].pack('n')
+ message = command + token_length + token + payload_length + payload
+ raise APN::Errors::ExceededMessageSizeError.new(message) if payload.bytesize > 256
message
end
-
-end # APN::Notification
+
+end # APN::Notification
View
42 lib/apn_on_rails/app/models/apn/notification.rb
@@ -1,6 +1,6 @@
-# Represents the message you wish to send.
+# Represents the message you wish to send.
# An APN::Notification belongs to an APN::Device.
-#
+#
# Example:
# apn = APN::Notification.new
# apn.badge = 5
@@ -8,22 +8,22 @@
# apn.alert = 'Hello!'
# apn.device = APN::Device.find(1)
# apn.save
-#
+#
# To deliver call the following method:
# APN::Notification.send_notifications
-#
+#
# As each APN::Notification is sent the <tt>sent_at</tt> column will be timestamped,
# so as to not be sent again.
class APN::Notification < APN::Base
include ::ActionView::Helpers::TextHelper
extend ::ActionView::Helpers::TextHelper
serialize :custom_properties
-
+
belongs_to :device, :class_name => 'APN::Device'
has_one :app, :class_name => 'APN::App', :through => :device
-
+
# Stores the text alert message you want to send to the device.
- #
+ #
# If the message is over 150 characters long it will get truncated
# to 150 characters with a <tt>...</tt>
def alert=(message)
@@ -32,9 +32,9 @@ def alert=(message)
end
write_attribute('alert', message)
end
-
+
# Creates a Hash that will be the payload of an APN.
- #
+ #
# Example:
# apn = APN::Notification.new
# apn.badge = 5
@@ -42,7 +42,7 @@ def alert=(message)
# apn.alert = 'Hello!'
# apn.apple_hash # => {"aps" => {"badge" => 5, "sound" => "my_sound.aiff", "alert" => "Hello!"}}
#
- # Example 2:
+ # Example 2:
# apn = APN::Notification.new
# apn.badge = 0
# apn.sound = true
@@ -64,9 +64,9 @@ def apple_hash
end
result
end
-
+
# Creates the JSON string required for an APN message.
- #
+ #
# Example:
# apn = APN::Notification.new
# apn.badge = 5
@@ -76,18 +76,22 @@ def apple_hash
def to_apple_json
self.apple_hash.to_json
end
-
+
# Creates the binary message needed to send to Apple.
def message_for_sending
- json = self.to_apple_json
- message = "\0\0 #{self.device.to_hexa}\0#{json.length.chr}#{json}"
- raise APN::Errors::ExceededMessageSizeError.new(message) if message.size.to_i > 256
+ command = ['0'].pack('H') # Now, APN_ON_RAILS implements only "simple notification format".
+ token = self.device.to_hexa
+ token_length = [token.bytesize].pack('n')
+ payload = self.to_apple_json
+ payload_length = [payload.bytesize].pack('n')
+ message = command + token_length + token + payload_length + payload
+ raise APN::Errors::ExceededMessageSizeError.new(message) if payload.bytesize > 256
message
end
-
+
def self.send_notifications
ActiveSupport::Deprecation.warn("The method APN::Notification.send_notifications is deprecated. Use APN::App.send_notifications instead.")
APN::App.send_notifications
end
-
-end # APN::Notification
+
+end # APN::Notification
View
44 spec/apn_on_rails/app/models/apn/group_notification_spec.rb
@@ -1,19 +1,19 @@
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper.rb')
describe APN::GroupNotification do
-
+
describe 'alert' do
-
+
it 'should trim the message to 150 characters' do
noty = APN::GroupNotification.new
noty.alert = 'a' * 200
noty.alert.should == ('a' * 147) + '...'
end
-
+
end
-
+
describe 'apple_hash' do
-
+
it 'should return a hash of the appropriate params for Apple' do
noty = APN::GroupNotification.first
noty.apple_hash.should == {"aps" => {"badge" => 5, "sound" => "my_sound.aiff", "alert" => "Hello!"},"typ" => "1"}
@@ -28,39 +28,51 @@
noty.sound = true
noty.apple_hash.should == {"aps" => {"sound" => "1.aiff"}}
end
-
+
end
-
+
describe 'to_apple_json' do
-
+
it 'should return the necessary JSON for Apple' do
noty = APN::GroupNotification.first
noty.to_apple_json.should == %{{"typ":"1","aps":{"badge":5,"sound":"my_sound.aiff","alert":"Hello!"}}}
end
-
+
end
-
+
describe 'message_for_sending' do
-
+
it 'should create a binary message to be sent to Apple' do
noty = APN::GroupNotification.first
noty.custom_properties = nil
device = DeviceFactory.new(:token => '5gxadhy6 6zmtxfl6 5zpbcxmw ez3w7ksf qscpr55t trknkzap 7yyt45sc g6jrw7qz')
noty.message_for_sending(device).should == fixture_value('message_for_sending.bin')
end
-
+
it 'should raise an APN::Errors::ExceededMessageSizeError if the message is too big' do
app = AppFactory.create
device = DeviceFactory.create({:app_id => app.id})
group = GroupFactory.create({:app_id => app.id})
device_grouping = DeviceGroupingFactory.create({:group_id => group.id,:device_id => device.id})
noty = GroupNotificationFactory.new(:group_id => group.id, :sound => true, :badge => nil)
- noty.send(:write_attribute, 'alert', 'a' * 183)
+ noty.stub(:to_apple_json).and_return('_' * 257)
lambda {
noty.message_for_sending(device)
}.should raise_error(APN::Errors::ExceededMessageSizeError)
end
-
+
+ it 'should not raise any error if the payload is not too big' do
+ app = AppFactory.create
+ device = DeviceFactory.create({:app_id => app.id})
+ group = GroupFactory.create({:app_id => app.id})
+ device_grouping = DeviceGroupingFactory.create({:group_id => group.id,:device_id => device.id})
+ noty = GroupNotificationFactory.new(:group_id => group.id, :sound => true, :badge => nil)
+ noty.stub(:to_apple_json).and_return('_' * 256)
+ lambda {
+ noty.message_for_sending(device)
+ }.should_not raise_error
+ end
+
end
-
-end
+
+end
View
46 spec/apn_on_rails/app/models/apn/notification_spec.rb
@@ -1,19 +1,19 @@
require File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'spec_helper.rb')
describe APN::Notification do
-
+
describe 'alert' do
-
+
it 'should trim the message to 150 characters' do
noty = APN::Notification.new
noty.alert = 'a' * 200
noty.alert.should == ('a' * 147) + '...'
end
-
+
end
-
+
describe 'apple_hash' do
-
+
it 'should return a hash of the appropriate params for Apple' do
noty = APN::Notification.first
noty.apple_hash.should == {"aps" => {"badge" => 5, "sound" => "my_sound.aiff", "alert" => "Hello!"},"typ" => "1"}
@@ -28,44 +28,52 @@
noty.sound = true
noty.apple_hash.should == {"aps" => {"sound" => "1.aiff"}}
end
-
+
end
-
+
describe 'to_apple_json' do
-
+
it 'should return the necessary JSON for Apple' do
noty = APN::Notification.first
noty.to_apple_json.should == %{{"typ":"1","aps":{"badge":5,"sound":"my_sound.aiff","alert":"Hello!"}}}
end
-
+
end
-
+
describe 'message_for_sending' do
-
+
it 'should create a binary message to be sent to Apple' do
noty = APN::Notification.first
noty.custom_properties = nil
noty.device = DeviceFactory.new(:token => '5gxadhy6 6zmtxfl6 5zpbcxmw ez3w7ksf qscpr55t trknkzap 7yyt45sc g6jrw7qz')
noty.message_for_sending.should == fixture_value('message_for_sending.bin')
end
-
+
it 'should raise an APN::Errors::ExceededMessageSizeError if the message is too big' do
noty = NotificationFactory.new(:device_id => DeviceFactory.create, :sound => true, :badge => nil)
- noty.send(:write_attribute, 'alert', 'a' * 183)
+ noty.stub(:to_apple_json).and_return('_' * 257)
lambda {
noty.message_for_sending
}.should raise_error(APN::Errors::ExceededMessageSizeError)
end
-
+
+ it 'should not raise any error if the payload is not too big' do
+ noty = NotificationFactory.new(:device_id => DeviceFactory.create, :sound => true, :badge => nil)
+ noty.stub(:to_apple_json).and_return('_' * 256)
+ lambda {
+ noty.message_for_sending
+ }.should_not raise_error
+ end
+
end
-
- describe 'send_notifications' do
-
+
+ describe 'send_notifications' do
+
it 'should warn the user the method is deprecated and call the corresponding method on APN::App' do
ActiveSupport::Deprecation.should_receive(:warn)
APN::App.should_receive(:send_notifications)
APN::Notification.send_notifications
end
end
-
-end
+
+end
View
24 spec/spec_helper.rb
@@ -25,23 +25,23 @@
configatron.apn.cert = File.expand_path(File.join(File.dirname(__FILE__), 'rails_root', 'config', 'apple_push_notification_development.pem'))
RSpec.configure do |config|
-
+
config.before(:all) do
-
+
end
-
+
config.after(:all) do
-
+
end
-
+
config.before(:each) do
end
-
+
config.after(:each) do
-
+
end
-
+
end
def fixture_path(*name)
@@ -49,7 +49,11 @@ def fixture_path(*name)
end
def fixture_value(*name)
- return File.read(fixture_path(*name))
+ if RUBY_VERSION =~ /^1\.8/
+ File.read(fixture_path(*name))
+ else
+ File.read(fixture_path(*name), :encoding => 'BINARY')
+ end
end
def write_fixture(name, value)
@@ -61,4 +65,4 @@ def apn_cert
end
class BlockRan < StandardError
-end
+end
Something went wrong with that request. Please try again.