— boreal-kiss.com

Archive
2008年8月 Monthly archive

SimpleLogger

FlashやFlexのクラスオブジェクトArray, ArrayCollection, Objectの中身を最深層までモニターに表示するAdobe AIRアプリケーションです。中身を確認したいオブジェクトを送信専用クラス(SimpleLogger.as)の引数に渡すだけでモニターに中身が表示されます。一応既存のloggingツールと差別化されているはず。詳細は[AIR] SimpleLoggerよりどうぞ。

追記 2008/09/01

ログの消去ボタンの追加、スクロールバーの動作修正、ウィンドウの外観をOSデフォルトのものに変更。ThunderBoltもObject深層まで走査できるっぽいので差別化されてないかも。でもThunderBoltはでかくてダサい。

追記 2008/09/02

XMLオブジェクトの解析が可能になった。XMLだけ特別にツリー状に表示される。

追記 2008/09/04

英語ページ作成。日本語ページより見やすい気がする。

Read More

サーバーから受信したxmlデータをActionScript Objectで受信したとき、格納したArrayCollection (Array)の構造を簡単に調べたいというのがそもそもの目的。いくつかあたってみたのでその簡単な使い方と個人的な感想を書き留める。Flex 3でしか確認していないので、Flashの場合は少し勝手が違うかもしれません。結論を先に言うと、Xray, ThunderBolt, Arthropodの中で目的を達成できたのはXrayのみ。個人的に気に入ったのはArthropod。

調べたこと

以下のようなxmlデータをHTTPServiceのレスポンスとして受け取りArrayCollectionに格納したとき、ネストした内容(id, name)がLoggingツールで見れるかどうか確認。

<?xml version="1.0" encoding="utf-8"?>

<users>
    <user>
        <id>1</id>
        <name>Chris Allen</name>
    </user>
    <user>
        <id>2</id>
        <name>Wade Arnold</name>
    </user>
    <user>
        <id>3</id>
        <name>Aral Balkan</name>
    </user>
    <user>
        <id>4</id>
        <name>Nicolas Cannasse</name>
    </user>
</users>

1. Xray

生のArrayCollectionの中身は見えなかったが、ArrayUtil.toArray()を用いて受信データをArrayCollection -> Arrayに変換すれば確認可能。ツール自体の機能で、ステージ上のオブジェクト全てのプロパティを丸見えにすることができ、さらにプロパティをXrayコンソールから動的にいじることができるのが便利。フレームレートがリアルタイムに確認できるので、例えば予定以下のパフォーマンスだった場合に、ボトルネックになる箇所を探せる可能性がある(アルファをいじったら改善された etc.)。難点は超不安定なところ。専用コンソール(.swf)がやたらと落ちる(起動中に止まる)。Macを再起動しないと再生できないような状態になることもしばしばで、使うのがためらわれる。現在開発進行中ではないことも理由かもしれない。

使い方

  1. osflash-xray – Google Code > Downloads > Xray_Flex2_Library_v0.5.swc をダウンロード(コネクター)。Flex3と名のつくものはなくてこれが最新バージョンになっている。
  2. Xray ( The AdminTool ) Open Source Flash > Downloads > Interfaceよりコンソールをダウンロード(SWF Onlyと書かれたもの)。これを使ってモニターすることになる。
  3. Flexプロジェクトにswcファイルにパスを通す。
    import com.blitzagency.xray.inspector.flex2.Flex2Xray;
    import com.blitzagency.xray.logger.XrayLog;

    をインポートし、それぞれのインスタンスを作成して、swfファイルを起動(例えばmyFlexと命名)。

    var xray:Flex2Xray = new Flex2Xray();
    var log:XrayLog = new XrayLog();
  4. Xrayコンソール(Xray.swf)を起動して左側のGoボタンを押すと調べたいswfファイルのモニタリングを開始する。
  5. myFlex内の調べたいオブジェクトに例えば以下のような処理を(myFlex内で)施すことでXray.swfコンソールで中身を確認できる。
    //ac is ArrayCollection receiving the xml data
    var ary:Array = ArrayUtil.toArray(ac);
    log.debug("Nested arrays:", ary);

Xray

2. Arthropod

シンプルでコンパクトで見た目もこぎれいなAIR製Logger。利用方法も簡単なので非常に良いと思うけど、目的は達成できず。ArrayColection、ArrayCollectionをArray変換したもの、ネストしたArrayともに視覚化できなかった。今回は結局何にもできなかったけど、個人的にはオススメ。

使い方

  1. Arthropod > DownloadよりASソース(1ファイル)とコンソール本体(.air)をダウンロード
  2. Flexプロジェクト(myFlex)にソースをインポート。
    import com.carlcalderon.arthropod.Debug;
  3. myFlex内の調べたいオブジェクトに以下のような処理を施し、myFlex.swfを起動するとArthropod.airで中身をモニターすることができる。Logging用のインスタンスを作らなくてよいところが便利。
    //ac is ArrayCollection receiving the xml data
    var ary:Array = ArrayUtil.toArray(ac);
    Debug.array(ary);
  4. 他にもいくつかユーティリティがあるがそれほど多くなく、長ったらしいドキュメンテーションもない。

Arthropod

3. ThunderBolt

Arthropodと同じくモニターはair製で、Flash Playerが吐くFlashlog.txtをモニターする作りになっている。ArrayCollection、ArrayCollectionをArray化したものの視覚化はできなかったが、例えば以下のようにネストしたArrayの中身は確認できた。

var ary:Array = [{id:"1",name:"Chris Allen"}, 
                {id:"2",name:"Wade Arnold"}, 
                {id:"3",name:"Aral Balkan"},
                {id:"4",name:"Nicolas Cannasse"}];

ただ、僕の目的は達成できておらず、さらに起動までの設定が少し面倒、モニターが無駄にでかい、なんか見た目がダサイというところが使う気を起こさせない。

使い方

設定についてはFlashのログ閲覧アプリThunderBoltをいれてみた|_level0.CUPPYが詳しいのでそちらを参照ください。少し補足しておくと、Flash PlayerにFlashlog.txt (Macの場合、/Users/USERNAME/Library/Preferences/Macromedia/Flash Player/Logs/flashlog.txt)というログファイルを吐き出させる設定が必要で、そのためには”/Users/USERNAME/mm.cfg”に以下の記述をする必要がある。

TraceOutputFileEnable=1

ThunderBolt

Read More

twitter円グラフ | ra66it.netがキレイだったんで真似てみた。円弧の描画はAS3CB Libraryを使った。画面クリックで描画再スタートします。

[Flash]パイチャート

Read More

Railsからの応答をE4Xで受信した場合とAMFで受信した場合を比較した。使ったのはidとnameからなる1000行のMySQLデータ。Flexからリクエストしてから応答までの時間を測定したところ、AMFの方が5倍も遅くなって困惑した。環境はFlex SDK 3.0, Ruby 1.8.6, Rails 2.1, MySQL 5.0.45で全て同じローカルマシン内。

Rails側

RubyAMFをインストールしたRailsプロジェクト内にUserモデルとUsersControllerを作成。UserモデルはMySQLのusersテーブル(id, name)とシンクロ済み(テストデータはgeneratedata.comで作成)。UsersControllerに以下のようにindexを記述。

class UsersController < ApplicationController

  def index
    @users = User.find(:all)    
    respond_to do |format|
      format.xml {render :xml => @users} # For HTTPService
      format.amf {render :amf => @users} # For RemoteObject
    end
  end
end

AMFの結果をArrayCollectionで簡単に受け取れるようrubyamf_config.rbを一部修正。ただしこの設定はRemoteObjectに対して有効で、NetConnectionではArrayCollectionが使えないため無効。

require 'app/configuration'
module RubyAMF
  module Configuration
    ClassMappings.assume_types = true
    ClassMappings.use_array_collection = true
  end
end

Flex側 (HTTPService – E4X)

load()とonResult()までの時間を10回測った。測定時間はTextAreaに、受信内容はDataGridにそれぞれ表示。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:HBox width="100%" height="100%">
        <mx:DataGrid id="dg" width="50%" height="100%">
            <mx:columns>
                <mx:DataGridColumn dataField="id"/>
                <mx:DataGridColumn dataField="name"/>
            </mx:columns>
        </mx:DataGrid>
        <mx:TextArea id="loadText" width="50%" height="100%"/>
    </mx:HBox>  
    <mx:Button label="Load" width="100" height="30" click="load(event)" />

    <mx:Script>
        <![CDATA[
            import mx.rpc.http.HTTPService;
            import mx.rpc.events.ResultEvent;
            import mx.rpc.events.FaultEvent;
            import flash.utils.getTimer;
            
            private var _start:uint;
            private var _str:String = "";
            
            private function load(e:Event):void{
                var req:HTTPService = new HTTPService();
                req.url = "http://127.0.0.1:3000/users.xml";
                req.resultFormat = HTTPService.RESULT_FORMAT_E4X;
                req.send();
                req.addEventListener(ResultEvent.RESULT,onResult);
                req.addEventListener(FaultEvent.FAULT,onFault);
                _start = getTimer();    
            }
            
            private function onResult(e:ResultEvent):void{
                dg.dataProvider = e.target.lastResult.user;
                _str += (getTimer() - _start).toString() + " msec\n";
                loadText.text = _str;
            }
            
            private function onFault(e:FaultEvent):void{
                loadText.text = e.fault.faultDetail;
            }
        ]]>
    </mx:Script>
</mx:Application>

Flex側 (RemoteObject – AMF)

MXMLの骨格はHTTPServiceを使う場合と同じ。スクリプト部分とservices-config.xmlの設定は以下の通り。

スクリプト部分

<mx:Script>
    <![CDATA[
        import mx.rpc.remoting.RemoteObject;
        import mx.rpc.events.ResultEvent;
        import mx.rpc.events.FaultEvent;
        import flash.utils.getTimer;
        
        private var _start:uint;
        private var _str:String = "";
        
        private function load(e:Event):void{
            var ro:RemoteObject = new RemoteObject();
            ro.source = "UsersController";
            ro.destination = "rubyamf";
            ro.index();
            ro.addEventListener(ResultEvent.RESULT,onResult);
            ro.addEventListener(FaultEvent.FAULT,onFault);
            _start = getTimer();
        }
        
        private function onResult(e:ResultEvent):void{
            dg.dataProvider = e.result;
            _str += (getTimer() - _start).toString() + " msec\n";
            loadText.text = _str;
        }
        
        private function onFault(e:FaultEvent):void{
            loadText.text = e.fault.faultString;
        }
    ]]>
</mx:Script>

services-config.xml (コンパイラオプションに追加)

<?xml version="1.0" encoding="UTF-8"?>
<services-config>
    <services>
        <service id="remoting-service" 
            class="flex.messaging.services.RemotingService" 
            messageTypes="flex.messaging.messages.RemotingMessage">
            <destination id="rubyamf">
                <channels>
                    <channel ref="ch-rubyamf" />
                </channels>
                <properties>
                    <source>*</source>
                </properties>
            </destination>
        </service>
    </services>
    
    <channels>
        <channel-definition id="ch-rubyamf" 
            class="mx.messaging.channels.AMFChannel">
            <endpoint uri="http://127.0.0.1:3000/rubyamf/gateway" 
                class="flex.messaging.endpoints.AMFEndpoint" />
        </channel-definition>
    </channels>
</services-config>

結果

HTTPService – E4X

load()からonResult()までの時間測定は右テキストエリア内(msec)。10回測定でだいたい0.5-0.6秒。ちなみにRESULT_FORMAT_OBJECT(ActionScript Object)で受信すると0.7-0.8秒ぐらいだった。

RemoteObject – AMF

HTTPServiceの場合と同じ測定で一回あたり約3秒。

AMF、通信設定が面倒なくせにすげー遅い。Ajax and Flex Data Loading Benchmarks | James Ward – RIA Cowboyの結果と違いすぎる。どっか間違ってる?

Read More

Flash Player 10だとWordpressのアップローダー(.swf)のダイアログがポップアップせず、だからファイルアップロードしようにもできなかった。何が悪いのかわからないままFlash Player 10をアンインストールしていたのだけどセキュリティの問題らしい。

The latest one that’s bugging me is a Flash 10 Player change that only allows you to open a file browse dialog via a direct user interaction such as a button push/mouse click. The idea here is to prevent malicious code from opening a file dialog and perhaps making you think it is for something else, and you wind up uploading some sensitive data to someone else’s server. I can see the point, but it’s creating some havoc.

Flash Player 10 Beta breaking WordPress, Flickr, other uploaders | BIT-101 Blog

つまりローカルファイルにアクセスできるようになった分セキュリティが厳しくなり、マウスクリック等の直接的なユーザーインタラクションのみFileReference.browse()が発動するようになっているのが原因らしい。WordpressやFlickrなどJavaScriptなどでアップローダーを遠隔発動させているところは軒並みアウトということになる。

Thanks Keith Peters, I have been suffered from the problem without any ideas.

関連リンク:

The Flash Blog » Flash Player 10 FileReference Changes
[FlashPlayer10]Flash Player 10自体のバグ・10が原因の不具合

追記 2008/08/20

修正じゃなくて仕様になるっぽい。

FileReference.browse() と FileReference.download() の呼び出しが、ユーザ操作により発生したイベント内に制限されるようになります。Flsh Player 10 以降、これらのメソッドを使用するには、マウスのクリックやキーの押下等によるイベントから呼び出すよう記述する必要があります。

akihiro kamijo: Flash Player 10 におけるセキュリティ変更

追記 2008/09/15

WordPress 2.6ではFlashアップローダーを使わないように設定できるので問題ない。2.5以前はプラグインでFlashアップローダーをdisableにできる。詳しくはデバッグ機能付きFlash Player 10のブラウザプラグイン – blog Boreal Kissを参照。

Read More

ソースコード HTML化 コンバーター「唐辛子」という非常に便利なアプリケーションがあるんですが、残念ながらRubyに対応していません。そこでRubyコード変換機能を追加したものをリリースしました。僕が使いたいというのが最大の理由なので必要最小限のプログラミング言語(Flex, ActionScript, JavaScript, Ruby, HTML, and XML)のみ変換可能です。その他の言語については本家をご利用ください。

Ruby唐辛子
[Flex]Ruby唐辛子

Rubyコードはこんな感じに表示されます。

  # POST /projects
  # POST /projects.xml
  def create
    @project = Project.new(params[:project])

    respond_to do |format|
      if @project.save
        flash[:notice] = 'Project was successfully created.'
        format.html { redirect_to(@project) }
        format.xml  { render :xml => @project, :status => :created, :location => @project }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @project.errors, :status => :unprocessable_entity }
      end
    end
  end

参考:

八角研究所 : Flex2でソースコードをブログに貼り付けるツールを作る(1) – ブログに美しいソースコードを貼り付けよう
八角研究所 : Flex2でソースコードをブログに貼り付けるツールを作る(2) – ソースコードをブログに貼り付けるツールを拡張しよう

Read More

例えばデータベースにfirst_name, last_nameというコラムを持つusersというテーブルがあって、Railsでデータベースの内容をto_xmlで呼び出すと、以下のようにfirst_nameとlast_nameのアンダースコアを勝手にハイフンに変える。

<?xml version="1.0" encoding="UTF-8"?>
<users>
    <user>
        <first-name>Colin</first-name>
        <last-name>Moock</last-name>
    </user>
</users>

Flexでこのxmlデータのノードを受け取る場合

//Data set from Rails
var user:XML;

trace(user.child("first-name"));//Colin

とするか、Rails側で勝手にハイフンに変えないようにする。

@user = User.find(params[:id])
render :xml => @user.to_xml (:dasherize => false)
Read More

Version Control With Subversion

上記オライリー本のオンラインページがあって、Subversion 1.4と1.5用のpdfファイルが無料ダウンロードできる。英語だけどネットで断片的な情報集めるよりは全然楽。図もわかりやすいし、2章まで読めば仕組みと簡単な使い方は覚えられると思う。同サイトには日本語ページも作成されつつあるようだったけど、こちらは解説にまで至ってなかった。

Read More

Apache + Rails + Flex: FlashVarsを使う場合でレーダーチャートをFlexで作ったらファイルサイズ236Kb、同じものをActionScriptファイルのみで作ったら4Kbだったので驚愕。ためしに以下のような空のFlexアプリケーションを作ってみた。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
            width="200" height="200" backgroundColor="#FFFFFF">
</mx:Application>

ファイルサイズ148Kbだった。こんな感じ。

gradient

同じものをActionScriptクラスで作ったら4Kbだった。差ありすぎじゃねー。

package {
    import flash.display.GradientType;
    import flash.display.Sprite;
    import flash.geom.Matrix;

    [SWF(width="200",height="200")]

    public class GradientFlash extends Sprite{
        
        public function GradientFlash(){
            var w:Number = this.stage.stageWidth;
            var h:Number = this.stage.stageHeight;
            
            var mat:Matrix = new Matrix();
            mat.createGradientBox(w,h,Math.PI/2);
            var colors:Array = [0xFFFFFF, 0xDDDDDD];
            var alphas:Array = [1,1];
            var ratios:Array = [0x00,0xFF];
            graphics.beginGradientFill(GradientType.LINEAR,
                                    colors,alphas,ratios,mat);
            graphics.drawRect(0,0,w,h);
            graphics.endFill();
        }
    }
}

おまけ

Flexで背景のグラディエントをなくす場合は以下の通り。

backgroundGradientColors="[#FFFFFF,#FFFFFF]"
Read More

注意: 書かないと確実に忘れてミスりそうなのでメモ。当方SVN初心者。もっと手順の少ない楽な方法があれば是非教えてください。

やりたいこと

ローカルのRailsアプリケーションの変更をリモートサーバー上のRailsアプリケーションに「安全に」反映させたい。

Railsの性質上、ローカル – リモートサーバー間の直接の書き換えは超絶危険なので、中継地点としてSVNリポジトリを利用する。これにより、ローカルの変更はSVNリポジトリへ別(サブ)バージョンとして保管、実際のリモートサーバー上での運営はSVNリポジトリから適切なバージョンを拾ってくることで反映させる。つまり手元で変ちくりんな修正を行ってしまっても古いバージョンが保管されているのでリセット可能。かなり大胆なweb運営ができる。

簡単な環境説明

RailsPlayground.comは名前の通り、Ruby on Railsアプリケーションが簡単に使えるのが売りの海外のレンタルサーバー。例えばさくらインターネットだとRailsは手動でインストールできるけど、FastCGIが使えないので動作が遅いらしい(例えばがんちゃんのブログ: さくらのレンタルサーバでRuby on Railsをうごかしてみた…らかなり遅いかも…)。日本国内だとRailsが標準装備のレンタルサーバーは値段がはってしまうようなので、月額$5のRailsPlaygroundを借りてみた。海外だと他にもBluehostTextdrive(現Joyent?)等が有名みたいだけど少し高い。

RailsPlayGroundの$5プランは破格なんだけど使用できるサーバーがApacheオンリーのようなので、Lighttpd等を複数使いたい場合は上のプランを選ばないといけない。あとRailsPlayGroundは契約フォームまわりがすっごくうさんくさかった。User IDが6文字までとか、いきなりクレジットカード番号いれさせられたり、なんか諸々。性能やら手続きやらについてはRailsPlaygroundの申し込み方法 (Ruby on Rails)あたりがわかりやすいかも。サブドメイン、データベースが作成し放題なので、例えばxreaみたいにスパムサイトの温床になりそうなので少し気がかりだけど、今のところ快適に動作している。

SVNリポジトリ設定

  1. RailsPlaygroundにSVNで管理したい旨をメールで要請(要請しないと使えない)。24時間サポートらしくすぐ専用のURLが送られてくる。アクセス先(IDとPW入力)でリポジトリスペースとアカウント作成などを行う。ここではリポジトリ名をrailsappとしておく。SVNリポジトリの保管先はこんな感じになる。
    http://YOURACCOUNT.svnrepository.com/svn/railsapp
    

    YOURACCOUNT部分はサーバー管理者が適当に与えてくれる。

  2. RailsPlaygroundサーバースペースにRailsアプリケーション(以下railsapp)を作成(ドキュメントルートより上)。理由はrailsappを作成する際、Apacheで動作するよう.htaccessをRailsが勝手に作成してくれるから。Apacheでちゃんと動作するように.htaccessを自分で作成できるならこの手順は不要。Apacheサーバーで運営する予定のない人にも不要。
  3. 先ほど作成したrailsappプロジェクト全部をローカルに保存。実際に欲しいのは.htaccessファイル「のみ」なので、事前にローカルで作成したRailsアプリケーション内に.htaccessだけコピーしてもってきてもよいと思う。
  4. ローカルのrailsappプロジェクト全部をSVNリポジトリにインポート。ローカルのrailsappディレクトリ内より
    svn import -m "MESSAGE" . http://YOURACCOUNT.svnrepository.com/svn/railsapp
    

    MESSAGE部分はお好みで(“First import”など)。

  5. インポートが完了したら手元にSVNリポジトリからのコピーを持ってこないといけない(リポジトリとシンクロさせるため)。とりあえずローカルのrailsappを別ディレクトリに移すなどする(ここではrailsappディレクトリと同じ階層にrails_backとして保存)。
    mv /path/to/railsapp /path/to/railsapp_back
    
  6. あらためてリポジトリよりチェックアウト。コピーしたい場所より
    svn co http://YOURACCOUNT.svnrepository.com/svn/railsapp
    

    これでSVNリポジトリrailsappとローカルrailsappがシンクロする。ローカルrailsappを変更してSVNリポジトリへコミット(ci)すると別バージョンとして保存されるはず。

  7. 次にSVNリポジトリのrailsappをRailsPlaygroundのリモートサーバー上へコピーする。これも基本はローカル – SVNリポジトリの場合と同じように、SVNリポジトリ – リモートサーバー間でシンクロさせてやる必要がある。RailsPlaygroundの自分のドメインへアクセス、sshで
    ssh YOURID@YOURDOMAIN.COM
    

    YOURIDとYOURDOMAIN.COMはRailsPlaygroundの契約IDと設定ドメイン。

  8. ドキュメントルートより上にSVNリポジトリをチェックアウト。手順2ですでにrailsappを作成している場合は全部削除。かわりにSVNリポジトリより呼び出す。
    svn co http://YOURACCOUNT.svnrepository.com/svn/railsapp
    

    これでリモートサーバーとSVNリポジトリがシンクロする。必要なときに必要なバージョンをSVNリポジトリから拾ってくればよい。バージョンの選び方等はSubversionの使い方を参照ください。

  9. RailsPlaygroundサーバー上railsapp/publicのシンボリックリンクをドキュメントルート配下に設置。例えば
    ln -s ~/railsapp/public ~/public_html/railsapp
    

    これでhttp://YOURDOMAIN.COM/railsappにアクセスするとSVNリポジトリの内容を反映したRailsアプリケーションが表示されるはず。Railsアプリケーションをドキュメントルート以下に配置すると色々不都合があるためこのような回りくどい処理を行う。

基本の作業手順

ローカル – SVNリポジトリ、SVNリポジトリ – リモートサーバーがシンクロしていることが前提。

  • SVNリポジトリより必要なバージョンをチェックアウト
    svn co http://YOURACCOUNT.svnrepository.com/svn/railsapp
    
  • ローカル作業後、SVNリポジトリへコミット。メッセージはお好みで。
    svn ci -m "MESSAGE" http://YOURACCOUNT.svnrepository.com/svn/railsapp
    
  • RailsPlaygroundサーバーへアクセス
    ssh YOURID@YOURDOMAIN.COM
    
  • SVNリポジトリよりリモートサーバーへチェックアウト
    svn co http://YOURACCOUNT.svnrepository.com/svn/railsapp
    
  • web上に反映される。
  • Read More