RailsでAPNSするときの注意点

ライブラリはこちらを使わせてもらう

jpoz / APNS

railsからapnsを使うためにgemfileに追記する


gem "apns"

bundle install

Apple Developer Centerからダウンロードした開発用.p12証明書を鍵とセットの証明書に変換

openssl pkcs12 -in 証明書.p12 -out apns.pem -nodes

証明書をRailsのプロジェクトディレクトリににアップロード

あとはアップロードしたファイルを指定して、指定のデバイスIDに送ればOK!

APNS.pem = Rails.root.join("cert","apns.pem")
APNS.send_notification(アプリから登録したデバイスID, "Hello iPhone!")


なはずだったのだが・・・・

なぜか英語の通知はできるのに日本語だと通知が行かない。



とりあえずtcpdump port 2195すると、正常に送れる時と送れない時で微妙に応答がちがう。。。

半日ぐらい悩んだ挙句、こちらにたどり着いた

APNS.pem = Rails.root.join("cert","apns.pem")
alert = String.new("はろーあいふぉん")
alert.force_encoding("ascii-8bit") if RUBY_VERSION.to_f >= 1.9
APNS.send_notification(アプリから登録したデバイスID, alert)

これで日本語もちゃんとpushできました。


参考にさせてもらったページ
https://github.com/jpoz/APNS
http://d.hatena.ne.jp/arcright/20120620/1340428736
http://atotok.net/note/rails/?incompatible+character+encodings%3A+ASCII-8BIT+and+U

テーブルの内容をテキストに書き出す方法

MySQLでテーブルのデータをテキストにエクスポートする場合、ターミナルからコマンドラインでやる方法とCUIから出力するのと2種類方法があります。

ターミナルからやる

# echo "select * from fuga" | mysql hogehoge > abc.csv

MySQL CUIからやる

select * from `fuga` into outfile "/tmp/abc.csv" fields terminated by ',';

ターミナルからやるとTSV形式になるけどカラムヘッダが出力されるのでデータを渡したりエクセルとかに取り込んで何か加工する時に何かと都合がいいけど、テーブルサイズによっては落ちちゃう。
CUIだと区切り文字が選べるけどヘッダが吐き出せないので、後でどのカラムが何のデータだったかわかんなくなる可能性がある、でもサイズが大きくてもちゃんと書きだしてくれる。

どっちも一長一短があるけど、とりあえずCUIでヘッダを吐き出す方法を考えた。

select id1,id2,id3,... from (select "id1","id2","id3",... union select id1,id2,id3 from fuga) as a into outfile "/tmp/abc.csv" fields terminated by ',';

何か他にいい方法ないですかねぇ。

追記
最後のやつだと一回一時領域にデータをコピーするのですごく遅い

Rails3.2+Backbone.jsでモデルの永続化ができない場合

Rails3.2+Backbone.jsの組み合わせで

this.model.save({hogehoge:...})

とやっても何故か永続化できない。

webrickのログを見ると

Started OPTIONS "/test" for 192.168.26.120 at 2012-10-11 18:24:35 +0900

とかなってて、正しくHTTPメソッドがセットされてない。

色々調べた結果、自分の環境ではAJAX通信時に

contentType="application/json"

をセットしてもRailsJSONリクエストとして処理してくれないらしい。

とりあえず

Backbone.emulateJSON = true;

にして、test.json宛てのリクエストに変更して逃げたけど、そもそも何故jsonヘッダを見てくれないんだぜ。

Webviewのlocalstorage

PhoneGap(cordva)のお話です。

よく釣り記事でPhoneGap+Javascriptでアプリを作ろう!なんて話で、不発揮データはlocalstorageに保存しましょうなどと簡単に書かれてますが、AndroidのWebviewだとlocalstorageのデータはRAMに保存されるので、RAMフラッシュのタイミングで消去されます。
https://groups.google.com/forum/?fromgroups=#!topic/phonegap/joymOyDsMlE

If I recall correctly, Android (at least in 2.X) localStorage was stored in available RAM. If this is the case, it might make sense that it would be wiped out on restart of device.

Android4.xでも試したけどリセットで消えちゃったので、ここらへんの挙動は変わってないっぽい。デフォルトブラウザなら保存されるんだけどなあ。
iOSはちゃんと保存されてた。

jQuery Mobileの初期化イベントが微妙

jQuery Mobileではpage="ID"の要素がページとして認識されます。

ページなのでjQuery Mobile APIが使えます。

jQuery Mobile APIとは初期化メソッドとかchangePageとかのアレです。

この初期化イベント、使ってみてわかったんですが結構厄介でした。

・たとえば一番最初に読み込まれるページ(index.htmlの一番上のpage="ID"のセクション)だとそもそも初期化イベントが呼ばれない。
起点になるページが#topだとすると、$("top").on("showpage",f(){})や$("top").on("createpage",f(){})が発火しない(1.1で確認)。
※"showpage"が評価されるのは再度#topを表示した時から。

・"pagebeforeshow"イベントでAJAX通信して準備して、"pageshow"で表示イベントを設定したとします。
$.mobile.changePage(#hoge)すると"pageshow"は評価されるけど"pagebeforeshow"は評価されないので、動的コンテンツが反映されない、もしくは最悪の場合前回表示された結果が再度表示される。

・"pageshow"とか一連のページ系初期化処理、dialogの表示非表示でも評価される。
 ダイアログを閉じるとそのページの"pageshow"が再度実行されてアッーとなる。

とまあ、ちょっといじっただけでもこれだけのトラップが待ってます。
jQuery Mobileだとテンプレート用意しなくていいのは魅力だけど、ちょっと盛りすぎてて使いどころを考えないと結構苦労する。
あとpage()の挙動が微妙。

ちなみにjQuery Mobile + Phonegapだとクリックの反応が鈍くなります。iOSだと大丈夫なのにな。
しかもjQuery Mobileの特徴の一つであるtransitionのほとんどがアンドロイドブラウザで動かない。
よく聞くjQuery MObile+Phonegapでアプリ作ろう!っていうのはちょっとちゃんと考えないと後々大変なことになるよ(自戒)

jQuery Mobileでlistviewに動的にエレメントを追加する

jQuery Mobileってあるじゃないですか。
あれってHTMLのdata属性を見て、勝手に要素に色々属性つけて見栄え良くするんですけど、$(jQuery).append()とかで属性を付与すると、付与した属性には当然そういった処理はやってくれないんで、追加した属性だけみすぼらしくなります。

たとえば

<section data-role="page" data-iscroll="enable" id="list">
<div class="content" data-role="content" data-iscroll="scroller" id="scroll_list">
<ul data-role="listview">
</ul>
</div>
</section>

みたいのがあったとして、

こいつに

$page = $("#list");
$list = $page.find(".content ul");
$list.append("<li>あああああ</li>");

とかってやっても、当然

<li>

が足されるだけで、自動的に

<li class="ui-btn ui-btn-icon-right ui-li-has-arrow ui-li ui-li-has-thumb ui-btn-up-c" data-corners="false" data-shadow="false" data-iconshadow="true" data-wrapperels="div" data-icon="arrow-r" data-iconpos="right" data-theme="c">

になってくれるわけではありません。

で、listviewの場合は$listに対して.listview()を呼び出せば良いわけなんですが、

$page = $("#list");
$list = $page.find(".content ul");
$list.append("<li>あああああ</li>");
$list.listview();

これが何故か上手くいかない。

何でかと思ってjQueryMobileのドキュメントを読んでたら

スクリプトからリストにアイテムを追加した後は refresh() メソッドを呼んで明示的にスタイルを更新してやる必要があります。

orz

これってもしかして1.0からなのかしら?

$page = $("#list");
$list = $page.find(".content ul");
$list.append("<li>あああああ</li>");
$list.listview("refresh");

これで解決!