Class: APNS::Payload

Inherits:
Object
  • Object
show all
Defined in:
lib/apns/payload.rb

Constant Summary collapse

APS_ROOT =
:aps
APS_KEYS =
[:alert, :badge, :sound]
PAYLOAD_MAX_SIZE =
256

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(device_token, message_string_or_hash = {}) ⇒ Payload

Returns a new instance of Payload.



11
12
13
14
15
16
17
18
19
20
21
# File 'lib/apns/payload.rb', line 11

def initialize(device_token, message_string_or_hash = {})
  self.device = APNS::Device.new(device_token)
  if message_string_or_hash.is_a?(String)
    self.message = {:alert => message_string_or_hash.strip}
  elsif message_string_or_hash.is_a?(Hash)
    self.message = message_string_or_hash.each_value { |val| val.strip! if val.respond_to? :strip! }
  else
    raise "Payload message argument needs to be either a hash or a string"
  end
  self
end

Instance Attribute Details

#deviceObject

Returns the value of attribute device.



4
5
6
# File 'lib/apns/payload.rb', line 4

def device
  @device
end

#messageObject

Returns the value of attribute message.



4
5
6
# File 'lib/apns/payload.rb', line 4

def message
  @message
end

Class Method Details

.batch(device_tokens, message_string_or_hash = {}) ⇒ Object

Batch payloads Ex: APNS::Payload.batch(Device.all.collect{|d|d.token}, :alert => “Hello”)

or with a block
  APNS::Payload.batch(Device.all.collect{|d|d.token}, :alert => custom_big_alert) do |payload|
    payload.payload_with_truncated_alert
  end


30
31
32
33
34
35
36
37
38
39
# File 'lib/apns/payload.rb', line 30

def self.batch(device_tokens, message_string_or_hash = {})
  raise unless device_tokens.is_a?(Array)
  payloads = []
  device_tokens.each do |device|
    payload = self.new(device, message_string_or_hash)        
    payload = yield(payload) if block_given?
    payloads << payload
  end
  payloads
end

Instance Method Details

#alert(string) ⇒ Object



56
57
58
59
# File 'lib/apns/payload.rb', line 56

def alert(string)
  message[:alert] = string
  self
end

#apn_messageObject



84
85
86
87
88
89
90
91
92
# File 'lib/apns/payload.rb', line 84

def apn_message
  message_hash = message.dup
  apnm = { APS_ROOT => {} }
  APS_KEYS.each do |k|
    apnm[APS_ROOT][k] = message_hash.delete(k) if message_hash.has_key?(k)
  end
  apnm.merge!(message_hash)
  apnm
end

#badge(number) ⇒ Object

Handy chainable setters

Ex: APNS::Payload.new(token).badge(3).sound(“bipbip”).alert(“Roadrunner!”).custom(:foo => :bar)



46
47
48
49
# File 'lib/apns/payload.rb', line 46

def badge(number)
  message[:badge] = number
  self
end

#custom(hash) ⇒ Object



61
62
63
64
65
66
# File 'lib/apns/payload.rb', line 61

def custom(hash)
  return nil unless hash.is_a? Hash
  return nil if hash.any?{|k,v| APS_KEYS.include?(k.to_sym) || (k.to_sym == APS_ROOT)}
  message.merge!(hash)
  self
end

#payload_with_truncated_alertObject

Returns a new payload with the alert truncated to fit in the payload size requirement (PAYLOAD_MAX_SIZE) Rem: It’s a best effort since the alert may not be the one string responsible for the oversized payload

also, if your alert is a Hash containing loc-* keys it won't work, in this case you should use the #payload_with_truncated_string_at_keypath


97
98
99
# File 'lib/apns/payload.rb', line 97

def payload_with_truncated_alert
  payload_with_truncated_string_at_keypath([:alert])
end

#payload_with_truncated_string_at_keypath(array_or_dotted_string) ⇒ Object

payload_with_truncated_string_at_keypath(“alert”) or payload_with_truncated_string_at_keypath()

or

payload_with_truncated_string_at_keypath(“custom1.custom2”) or payload_with_truncated_string_at_keypath([:custom1, :custom2]) Rem: Truncation only works on String values…



106
107
108
109
110
111
112
113
114
115
116
# File 'lib/apns/payload.rb', line 106

def payload_with_truncated_string_at_keypath(array_or_dotted_string)
  return self if valid? # You can safely call it on a valid payload 
  return unless message.at_key_path(array_or_dotted_string).is_a?(String)
  
  # Rem: I'm using Marshall to make a deep copy of the message hash. Of course this would only work with "standard" values like Hash/String/Array
  payload_with_empty_string = APNS::Payload.new(device.token, Marshal.load(Marshal.dump(message)).at_key_path(array_or_dotted_string){|obj, key| obj[key] = ""})
  wanted_length = PAYLOAD_MAX_SIZE - payload_with_empty_string.size

  # Return a new payload with truncated value
  APNS::Payload.new(device.token, Marshal.load(Marshal.dump(message)).at_key_path(array_or_dotted_string) {|obj, key| obj[key] = obj[key].truncate(wanted_length) })
end

#sizeObject



75
76
77
# File 'lib/apns/payload.rb', line 75

def size
  self.to_ssl.size
end

#sound(filename) ⇒ Object



51
52
53
54
# File 'lib/apns/payload.rb', line 51

def sound(filename)
  message[:sound] = filename
  self
end

#to_sslObject



70
71
72
73
# File 'lib/apns/payload.rb', line 70

def to_ssl
  pm = self.apn_message.to_json
  [0, 0, 32, self.device.to_payload, 0, pm.size, pm].pack("ccca*cca*")
end

#valid?Boolean

Validity checking only checks that the payload size is valid. We do not check the message content.

Returns:

  • (Boolean)


80
81
82
# File 'lib/apns/payload.rb', line 80

def valid?
  self.size <= PAYLOAD_MAX_SIZE
end