location設定に左右されない認証のかけ方

Wordpress などでマルチサイトやら色々設定していると、Basic 認証などかけたいときに、location ディレクティブの適用優先順位で混乱することがある。

そういうときは、下記のように記述すると、location ディレクティブの設定の影響は受けないので、すっきりかける。

http コンテキストで map で認証をかけたい場所を設定する。

    map $request_filename $auth_realm {
        default off;
        ~*/wp-login\.php|/wp-admin/((?!admin-ajax\.php).)*$ 'wp-admin';
    }

server など認証をかけたいコンテキストで認証をかける。

    auth_basic_user_file /path/to/.htpasswd;
    auth_basic $auth_realm;

FormValidator::Lite で Xslate のテンプレートの文法チェックをする方法

そこそこ大きい Web アプリを作ってると非エンジニアに管理画面でテンプレート編集させたりするケースもあると思いますが、文法チェックをしないと、テンプレートがレンダリングできないがためにシステムがコケるとかいう悲しい事態が起こったりするので、チェックを通ったもののみ保存したいというニーズもたまにあると思います。
そこで、ヴァリデーターをかましてチェックすることにしてみました。

package MyApp::FormValidator::Constraint;
            
use strict;
use warnings;
use FormValidator::Lite::Constraint;
use Text::Xslate;
use Try::Tiny;
            
our %ErrStr;
my $xslate = Text::Xslate->new;
            
rule 'CAN_RENDER' => sub {
    return try {
        $xslate->render_string($_);
    } catch {
        $ErrStr{'CAN_RENDER'} = $_;
        return 0;
    };
};

1;

こんな Constraint クラスをこしらえて、

FormValidator::Lite->load_constraints(qw/Email +MyApp::FormValidator::Constraint/);

my $validator = FormValidator::Lite->new(...);
$validator->check(
    'template' => [ 'NOT_NULL', 'CAN_RENDER' ],
);

テンプレートのエラーメッセージも後から参照したかったりするので、とりあえず$MyApp::FormValidator::Constraint::ErrStr{'CAN_RENDER'} に Xslate が吐くエラーメッセージ突っ込んでおきましたが、相当ダサいのでもうちょっとスマートな方法で実装したいです。

Ubuntu に公式レポジトリの nginx を入れる

Ubuntu 12.04 LTS でデフォルトで入る nginx パッケージは現時点(2013/10/18)でバージョン 1.1.19 と大分古いです。最新バージョンは 1.4.3 なのでレポジトリを apt に登録します。

sudo add-apt-repository ppa:nginx/stable

あとは、普通にインストールするか、既にインストールされていれば下記でアップグレード可能です。

sudo apt-get update
sudo apt-get upgrade

nginx + php5-fpm で真っ白なページしか表示されない時の対処

大分ハマりました。

ubuntu/12.04
nginx/1.2.7
php5-fpm/5.4.6

結論から書くと、Nginx 公式のリポジトリから取得したパッケージには、fastcgi_param 用の設定がデフォルトで一通り入っていますが、いくつか記述が無いものもあります。

下記の PATH_TRANSLATED を追加したら無事動きました。

fastcgi_param PATH_TRANSLATED   $document_root$fastcgi_path_info;

「nginx php5-fpm blank page」などググったら色々出てきますが、PATH_TRANSLATED に直接触れているのは少なかったです。

Ti.Filesystem.File で知らないとハマること

Ti.Filesystem.resourcesDirectory は read-only です。
シミュレーターだと書き込みできてしまうため、実機でハマります。

https://wiki.appcelerator.org/display/guides/Filesystem+Access+and+Storage

Ti.Filesystem.resourcesDirectory: A read-only directory where your application resources are located; this directory corresponds to the project/Resources directory in Titanium Studio. The contents of this directory persist until the user uninstalls the application.

applicationDataDirectory とか使えってことですね。
ガイド読んでたら気付きましたが、API リファレンスの方にも書いてありました。

ImageView.addEventListener('load', listener) する時に無限ループする場合があるので注意

var listenerImage = function(e) {
  var image = e.source;
  var blob  = image.toBlob();

 // blob.imageAsResized() とか適当な画像処理

  image.image = blob;
};

var image = Ti.UI.createImageView({ image: imageUrl });
image.addEventListener('load', listenerImage);

みたいなことをしていると、ImageView の image プロパティを書き換えた時に、また load イベントが発火するので、どこかでイベントリスナーを解除しておかないと無限にループします。リサイズ処理させていたら画像がどんどん小さくなるアニメーションをしたので気付きました。

リスナー関数の中で自分自身を指定するには下記で行けます。

e.source.removeEventListener('load', arguments.callee);

これで、イベント発火したときにイベントリスナー解除できるので、最初の1回だけ実行することができます。

ScrollView の中に入れた TableView が行数が増えても自動的に高さ調整させる方法

ScrollView の中に TableView を入れていると、TableView の内容を動的に変更している場合に、何も指定しないと高さを再計算してくれないので、スクロールが働かなかったりします。

解決策は、TableView と全ての TableViewRow に、height: Ti.UI.SIZE を指定すれば、setData() などで動的に内容を変更しても高さを良しなに調整してくれます。height プロパティを持たない TableViewSection には指定不要です。

Titanium SDK 2.1.4.GA