とりあえず動く RubyAMF

RubyAMF とは

FlashRails の間でオブジェクトの相互変換を行ってくれるプラグイン
サンプルでは Hello World の送信をしているくらいのものしかなかったので、モデルの情報を Flash 側から入力して Rails で受け取るまでの最小限のサンプルコード。例によって私が忘れたときの俺様用メモ。

導入

Rails のバージョンは 2.1.1 で確認。いつものようにプラグインをインストールします。

ruby script/plugin install http://rubyamf.googlecode.com/svn/trunk/

完了すると、 routes.rb に RubyAMF 用のルーティングが定義されるはずです。また、 RAILS_ROOT/config 以下に rubyamf_config.rb というファイルが作成されるので、これを編集します。


  1. ClassMappings.translate_case = true
    Ruby と AS の命名規則の差を埋めます。 created_at <=> createdAt への変換を行うという設定。

  2. ClassMappings.assume_types = true
    これを設定しないと、 Rails 側に送信される値がただのハッシュになります。true にすることで各種モデルのクラス(のようなもの)として送信されます。

  3. ParameterMappings.scaffolding = true
    これを true にしないと Rails 側で値を受け取るときに params[0] のような値を受け取る事になります。true にしても params[0] のような表記も使えるので、とりあえず true にします。

ここまで完了したら、今回操作するモデルを作成します。名前は Sample にして、持っている値は以下のとおり。
なお、 name という名前は AS の String 型のメンバと競合するようなので避けましょう。

  • subject(String)
  • body(String)

以上、設定終わり。

ActionScript を記述

続いて、一旦 ActionScript の記述に入ります。ファイルの配置は以下のとおり。

┌mainApp.mxml
├Sample.as
└as─sample.as

それぞれのファイルの中身を見ていきます。

mainApp.mxml
これがアプリケーションのメイン、入力フォーム。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
  xmlns:mx="http://www.adobe.com/2006/mxml"
  xmlns:comp="*"
  layout="absolute"
  backgroundColor="#000000"
  backgroundAlpha="0"
>
  <!-- ここで sample.as を呼び出す事にして、スクリプトの中身は外に出す -->
  <mx:Script source="as/sample.as" />

  <!-- ここで Rails 側と連携を行っている -->
  <mx:RemoteObject
    id="sampleService"
    destination="rubyamf"
    endpoint="http://localhost:3000/rubyamf_gateway/"
    source="SampleController"
  />

  <!-- 送信メソッドは as/sample.as に記述済み -->
  <mx:Panel title="送信テスト" width="100%" height="100%">
    <mx:VBox width="100%">
      <mx:Form width="100%" height="500">
        <mx:FormItem label="題名" required="true">
          <mx:TextInput width="150" id="subject" />
        </mx:FormItem>
        <mx:FormItem label="本文" required="true">
          <mx:TextInput width="150" id="body" />
        </mx:FormItem>
        <mx:Button label="作成" click="createSample()" />
      </mx:Form>
    </mx:VBox>
  </mx:Panel>
</mx:Application>

Sample.as
as 以下のファイルとは別なので注意。
これは主に Rails のモデルに相当するクラスの情報を AS 向けに記述します。

package {
  [RemoteClass(alias="Sample")]
  public class Sample {
    // これは全部共通
    public var id:int;
    public var errors:Object;
    
    // ここからは個別のデータ
    public var subject:String;
    public var body:String;
  }
}

as/sample.as
先ほど外に出したスクリプト
主な処理はここで行います。

import mx.rpc.remoting.*;
import mx.rpc.events.*;
import mx.rpc.*;
import mx.collections.ArrayCollection;
import Sample;
import mx.controls.Alert;
import mx.controls.*;
import mx.events.ListEvent;

// モデルの作成
private function createSample():void {
  var sample:Sample = new Sample();
  sample.subject = subject.text;
  sample.body = body.text;
  save(sample);
  // わかりやすいようにメッセージを表示する
  Alert.show("送信できました");
}

// モデルの保存
private function save(sample:Sample):void {
  // ここで Rails の save メソッドを呼び出している
  var call:AsyncToken = sampleService.save({sample:sample});
  call.addResponder(new mx.rpc.Responder(onSaveSuccess, onSaveFault));
}

// 保存完了時
private function onSaveSuccess(e:ResultEvent):void {
}

private function onSaveFault(e:ResultEvent):void {
}

ここまで終わったら mainApp.mxmlコンパイルします。

Rails 側の記述

Rails 側では、値を受け取る SampleController を記述します。
今はとりあえず作成だけ。

class SampleController < ApplicationController
  # 保存
  def save
    # ここでエラーになる場合 config の記述とサーバの再起動を確認
    @sample = params[:sample]

    respond_to do |format|
      format.amf do
        if @sample.save
          render :amf => params[:sample]
        else
          render :amf => FaultObject.new(params[:sample].errors.join("/n"))
        end
      end
    end
  end
end

以上、条件はすべてクリアした!
後は localhost の 3000 番ポート(設定により可変)でサーバを立ち上げて、 Flash アプリからデータを送信してみましょう。
上のサンプルでは確認用メソッドを記述していませんが、その辺りは適当にどうぞ。

参考

いつもお世話になっているちゅう君のサイト。サンプルソースもいただきました。
http://ecpplus.net/weblog/ruby/rubyamf/