EN TW

更換的原因

其實PRX本來就是元祖,不過當初要用APN功能的時候,PRX的版本還不支援rails 3,自己也沒有把握能修好,所以就改用了已支援rails 3的fork。

沒想到過了一年多,PRX版已支援rails 3、而且新增了一些我需要的功能;當初選用的folk反而一直沒有更新…,只好再換回來。

重大變更與新功能

  • PRX版的 send_notifications 方法不接受 array,只能一次寄出所有 unsent
  • 新增 APN::App,將cert內容放在資料庫內,可達到一個rails app對應多個ios apps
  • 新增 APN::Group(以及 GroupNotification、DeviceGrouping)可以群組發訊息,但對Apple的那段還是一封一封傳,只是我們的rails app不必生一堆notifications而已。

更新步驟

修改 Gemfile 改回

	gem 'apn_on_rails'

然後

	bundle install

補新版的 migrateions

	rails generate apn_on_rails:install
  • 如果遇到名稱衝突,可能要先將舊的改名,跑完再改回來、並把重複的刪掉。
  • README裡有提到migration 002 create_apn_notifications 被手動修改過,可能會造成問題。於果有遇到請參考 Upgrade Notes小節。但他的migrations其實也有寫防呆,應該不會有問題才對(我自己沒遇到問題)。

然後

	rake db:migrate

把cert移到資料庫,設定第一個APN::App

/config/apple_push_notification_development.pemapple_push_notification_production 的cert內容移到資料庫內,不知道怎麼搞的可以先參考這篇,但他提供的demo code在rails 3.2不能直接跑,要先解決massive-assignment的問題,不然就自己改寫。

其實cert file的方法也有相容,只是不能用group notifications功能,但我覺得一次衝到底比較乾脆,省得以後維護麻煩。

改寫application,在新增apn_devices時要指定app

這就是要自己清查自己寫的 code 了。

問題解決

NameError: uninitialized constant APN::App::RAILS_ENV

config/environment.rb 新增

	APN::App::RAILS_ENV = Rails.env

Errno::ENOENT: No such file or directory - /config/apple_push_notification_development.pem

因為我是我直接捨棄cert file的方法,所以我想讓他閉嘴。如果你想沿用cert file,可能可以試試看把那段改寫成 Rails.root.join('config', 'apple_push_notification_development.pem')

依照教學執行

	script/rails generate configatron:install

生出configatron檔案,並在 config/configatron/defaults.rb 新增

	configatron.apn.cert = ''

改寫成讓 APN::Notification.send_notifications 接受 array

config/initializers/apn_notification_reopen.rb

	class APN::Notification

	 # ...

	 def self.send_notifications(notifications = APN::Notification.where("sent_at is null"))
	 app_ids = notifications.map {|n| n.device.app_id }.uniq
	 app_ids.each do |app_id|
	 begin
	 if (app = APN::App.where(:id => app_id).first)
	 the_cert = Rails.env.production? ? app.apn_prod_cert : app.apn_dev_cert
	 APN::Connection.open_for_delivery({:cert => the_cert}) do |conn, sock|
	 unsent_notifications = notifications.select {|n| n.device.app_id == app_id }
	 unsent_notifications.each do |noty|
	 conn.write(noty.message_for_sending)
	 noty.sent_at = Time.now
	 noty.save
	 end
	 end
	 end
	 rescue Exception => e
	 STDERR.puts e.message
	 raise e
	 end
	 end

	 end
	end