2010年6月15日火曜日

Rhomobile RhoSync 2.0

以下のドキュメントは、英語の原文を日本語へ翻訳したものをRhomobile社の許可のもと、公開しています。
公式なドキュメントはRhomobile社のサイトをご覧ください。
また、この文書は2010/6/8(JST)の情報がもとになっています。
この日本語の翻訳について問題・質問などがある場合、コメントを残してください。それ以外については、本ドキュメント内にある問い合わせ先にお願いします。

The following document (a translation of the English original into Japanese) is published with Rhomobile permission.
If you need official documents, please visit Rhomobile site.
In addition, the following document is based on 2010/June/8 (JST) information.
If you have any question, problem about the Japanese translation, please leave your comment. Except for that, refer contacts in the document.

RhoSync 2.0


目次

Rhosync

RhoSyncは、エンタープライズアプリケーションのデータをユーザのスマートフォン上で利用可能にするサーバー型同期ツールです。情報はユーザーのローカルデバイスに格納され、切断やオフライン時でも利用可能です。

RhoSyncインストール

製品には最新のstableバージョンをインストールし、edgeバージョンの使用は開発目的のみに使用することを強く推奨します。

前提条件

必須

  1. ruby - v1.8.7 + RubyのWindowsインストーラ1.8.7
  2. RubyGems - v1.3.7 + RubyGemsは1.3.7
  3. Redis - v1.2.6
  4. Ruby Webサーバー-mongrelでテストしています。rubyに付属するデフォルトのWevサーバー,WEBrickはHTTPのheaders/cookiesにおいて問題の原因として知られており、推奨していません。
  • 注:私たちはredis1.2.6を使用してテストしています。redis 2.0 rc1が作業中の間、final 2.0がリリースされるまで、公式にサポートしません。

Redisのインストール

注:redisを提供されるrhosync rake tasksで管理したい場合、このセクションを飛ばしてください。

POSIXシステムでは:

 wget http://redis.googlecode.com/files/redis-1.2.6.tar.gz
tar xvzf redis-1.2.6.tar.gz
cd redis-1.2.6
make
./redis-server

Windowsシステムでは:

redis 1.2.6 for wondowsをダウンロードして、解凍します。
そしてredis-server.exeを起動します。redis-server.exeを起動します。

オプション

  1. Java JDK -BlackBerryデバイスでバルク同期を使用する場合、Java 1.6が必要です。
  2. sqlite3 Ruby driver -Cプラットフォームでバルク同期を使用する場合、sqlite3-ruby gemのインストールが必要になります:
[sudo] gem install sqlite3-ruby

注:Windowsの場合は、sqlite3.dllをrubyのbinディレクトリ(例 c:\Ruby\bin)へ追加する必要もあります。

安定版インストール

[sudo] gem install rhosync

ベータ版のインストール

[sudo] gem install rhosync --pre

これはrhosyncの最新pre-releaseタグをインストールします。

エッジバージョンをインストール

最新のEdge RhoSyncをインストールするには、あらかじめgitをインストールしおかなければなりません:

 git clone git://github.com/rhomobile/rhosync.git
cd rhosync
[sudo] gem install jeweler
[sudo] rake install

RhoSync 2.0対1.x

RhoSync 2.0はRhoSyncシステムを完全に書き直したものです。スタンドアロンのアプリではなく、今ではバンドルされたコンポーネントが付属したrubyライブラリとなっています。これは重要な違いです。なぜなら、rhosync rails appにプラグイン・コードを書く代わりに、2.0ならばRhoSyncアプリを書くことになるからです。RhoSyncアプリを書くのに、もはやrailsは必要がなくなったのです。必要なものはrhosync gemとredisです。

RhoSyncの開発ワークフローは、今や、Rhodes開発ワークフローと同じようになりました。

  1. rhosync app helloworld-server #=> generates a new rhosync app
  2. cd helloworld-server
  3. rhosync source person
  4. specコードを書いたり、person adapterコードを書いたり
  5. テスト、修正、繰り返して...
  6. helloworld-server をdeployする
  7. helloworld Rhodesアプリをhelloworld-serverに接続する

RhoSync2.0の構成:

  • 同期フレームワーク - RhoSyncコア、これはRhodesクライアントとサードパーティ製のソース(SOAP,RESTなど)間のデータ同期を容易にします。各ソースは、単純な"ソースアダプタ"クラスを実装することによって同期されます。ソースアダプタの集合と双方向にやりとりするために、Rhodesのクライアントは組み込まれたsinatraサーバに接続します。ソースアダプタAPIはいくつかの機能強化と小規模な変更がありますが、パラダイムは1.xと同様です。詳細については、rhosunc 1.x ソースアダプタを2.0へ移行参照してください。
  • REST API -RhoSync APIを参照してください。
  • 管理コンソール - 動作しているRhoSyncアプリの操作や状態を見ることに使用されます。コンソールはそれらすべてにおいてRhoSyncのAPIを使用します。
  • 非同期ジョブ- RhoSync 2.0は実行する必要があるタスクの非同期実行を提供するために、resqueライブラリを使用します。これらのタスクは、ソースアダプタの実行、プッシュメッセージの送信、バルクデータの準備などを含みます。Resqueはとても簡単に使え、拡張性も高いので、ここで説明されないその他の機能のためにも簡単に利用することができます。

RhoSyncアプリケーションを作成する

RhoSyncアプリケーション生成

まず、アプリケーションをRhoSyncコマンドラインユーティリティを使用して生成することから始まります:

 rhosync app helloworld
cd helloworld

dtachのセットアップ

MacOS/Linuxを使っている場合、このpath上でdtach をインストールします:

 [sudo] rake dtach:install

Redisのセットアップ

前のセクションで既にredisをインストールや起動していないなら、RhoSyncアプリケーションのディレクトリから行うことができます:

 [sudo] rake redis:install
rake redis:start

アプリケーションの起動

そして、サーバを起動しましょう!

rake rhosync:start

すべてがうまくいった場合は、コンソールで次のようなメッセージが見られるでしょう:



[07:01:15 PM 2010-05-04] Rhosync Server v2.0.0.beta7 started...
[07:01:15 PM 2010-05-04] ************************************************************

[07:01:15 PM 2010-05-04] WARNING: Change the session secret in config.ru from <changeme> to something secure.
[07:01:15 PM 2010-05-04] i.e. running `rake secret` in a rails app will generate a secret you could use.

[07:01:15 PM 2010-05-04] ************************************************************

Webコンソールを開くには、ブラウザでhttp://localhost:9292/に移動するか、以下のコマンドを実行します:

 rake rhosync:web

RhoSyncソースアダプタの作成

RhoSyncでは、目的とするエンタープライズ・バックエンドのquery(クエリ)、create(作成)、update(更新)、およびdelete(削除)の少量のコードを書くことが要求されます。これらのオペレーションのためのrubyコードの集合を私たちは"ソース"または"ソースアダプタ"と呼びます。

ソースアダプタの生成

rhosyncアプリケーションに新しいソースアダプタを追加するのは簡単です:

 cd <my-rhosync-app>

rhosync source product

これは、sources/product.rbと呼ばれる新しいrubyファイルを生成します:

class Product < SourceAdapter
def initialize(source,credential)
super(source,credential)
end

def login
# TODO: Login to your data source here if necessary
end

def query
# TODO: Query your backend data source and assign the records
# to a nested hash structure called @result. For example:
# @result = {
# "1"=>{"name"=>"Acme", "industry"=>"Electronics"},
# "2"=>{"name"=>"Best", "industry"=>"Software"}
# }
raise SourceAdapterException.new("Please provide some code to read records from the backend data source")
end

def sync
super
end

def create(create_hash,blob=nil)
# TODO: Create a new record in your backend data source
# If your rhodes rhom object contains image/binary data
# (has the image_uri attribute), then a blob will be provided
raise "Please provide some code to create a single record in the backend data source using the create_hash"

end

def update(update_hash)
# TODO: Update an existing record in your backend data source
raise "Please provide some code to update a single record in the backend data source using the update_hash"
end

def delete(object_id)
# TODO: write some code here if applicable
# be sure to have a hash key and value for "object"
# for now, we'll say that its OK to not have a delete operation
# raise "Please provide some code to delete a single object in the backend application using the hash values in name_value_list"
end

def logoff
# TODO: Logout from the data source if necessary
end
end

また、specファイルspec/sources/product_spec.rbを追加し、settings/settings.ymlを編集し、いくつかのデフォルト値でproduct adapterをsources sectionへ追加します:

#Sources 
:sources:
Product:
:poll_interval: 300

これでソースアダプタのメソッドを実装したことになります。さらなる詳細はチュートリアルを見てください。

ソースアダプタのAPI

  • login(ログイン)
  • logoff(ログオフ)
  • query(クエリー)
    • stash_result
  • search(検索)
  • create(作成)
  • update(更新)
  • delete(削除)
  • @source - source settings(ソースの設定)
  • current_user - 要求を発行する現在のユーザーの処理

データ・パーティショニング

RhoSync 2.0のソースアダプタは2つの方法でデータをパーティションすることができます:ユーザーとアプリです。推測のように、ユーザー・パーティションは、各ユーザのソースアダプタのデータセットのコピーを格納します(1つのコピーは1ユーザーのすべてのデバイス間で共有されます)。

同様に、アプリケーション・パーティションはアプリ全体のソースアダプタの1コピーを格納します(すべてのユーザとデバイスが同じデータを共有します)。アプリ・パーティションは、ユーザごとに変化しない大量のデータを取得するソース・アダプタの場合、特に便利です。例えば、製品カタログのようなものです。

ユーザーパーティション

ユーザーのパーティションは、ソースアダプタのデフォルトの方式ですが、明示的にsettings/settings.ymlでそれを定義することができます:

:sources: 
Product:
:poll_interval: 300
:partition_type: user
アプリケーションパーティション

同様にアプリパーティションを有効にします:

:sources: 
Product:
:poll_interval: 300
:partition_type: app

これで、すべてのユーザーに対して製品データセットの1つのコピーを持つことになります。

RhoSyncアプリケーションのテスト

RhoSync 2.0は、動作駆動型開発のためにspecフレームワークを提供します。アプリケーションとソースアダプタが生成されるときに、アプリケーションの最上位の'spec"フォルダー中にspecファイルが生成されるのが分かるでしょう。

例

rhostoreのproductアダプタの簡単なspecのサンプルです:

it "should process Product query" do
test_query.size.should > 0
query_errors.should == {}
end

この単純なspecは、productアダプタのqueryメソッドを実行し、一つ以上のオブジェクトがあること、エラーがないことを検証します。

productアダプタの完全なコードはGitHub上で入手可能です。

TestMethods API

最新のTestMethods APIは、hosted rdocsを見てください。

setup_test_for(adapter,user_id)

指定されたユーザー用のテストのためソースアダプタを初期化するには、通常(:each) blockの前に以下を記述します。

setup_test_for(Product,'testuser') #=> 'testuser' will be used by rest of the specs

test_query

アダプタのqueryメソッドを実行し、redisに格納されているmaster document(:md)を返します。

たとえば、ソースアダプタのクエリメソッドがこのような場合:

def query(params=nil)
@result = {
"1"=>{"name"=>"Acme", "industry"=>"Electronics"},
"2"=>{"name"=>"Best", "industry"=>"Software"}
}
end

test_queryは以下のような結果を返すでしょう:

{ 
"1"=>{"name"=>"Acme", "industry"=>"Electronics"},
"2"=>{"name"=>"Best", "industry"=>"Software"}
}

query_errors

redisに格納された、直前のソースアダプタのqueryのエラーを返します。

たとえば、
{"query-error"=>{"message"=>"error connecting to web service!"}}

test_create(record)

与えられたレコードをアダプタのcreateメソッドで実行し、createメソッドからオブジェクトの文字列を返します。createメソッドが文字列を返したら、デバイスが次回同期するためにリンクが保存されます。このリンクはここでテストできます。

たとえば、specで以下のようになります:

@product = {
'name' => 'iPhone',
'brand' => 'Apple',
'price' => '$299.99',
'quantity' => '5',
'sku' => '1234'

}
new_product_id = test_create(@product)
create_errors.should == {}
md[new_product_id].should == @product

create_errors

これはアダプタのcreateメソッドの結果を返します。マスタドキュメント(:md)は新しいレコードも含んでいるでしょう。この前のソースアダプタでcreateした以降の、redisに格納されたどんなエラーも返ります。(query errorsと同じ構成です)

test_update(レコード)

ソースアダプタのupdateメソッドを実行します。ハッシュのハッシュとして(object_id => object)、レコードを受け取ります。

たとえば、

test_update({'4' => {'price' => '$199.99'}})
update_errors.should == {}
test_query
md[product_id]['price'].should == '$199.99'

これは、object_idが'4'のアダプタのUpdateメソッドを呼び出します。

注:マスタードキュメントをテストするには、上記のようにtest_queryを実行する必要があります。

update_errors

以前のソースアダプタのupdate以降からのredisに格納されたエラーを返します(クエリのエラーと同様の構造)。

test_delete(record)

ソースアダプタのdeleteメソッドを実行します。ハッシュのハッシュとして(object_id=>object)レコードを指定します。

たとえば、

@product = {
'name' => 'iPhone',
'brand' => 'Apple',
'price' => '$299.99',
'quantity' => '5',
'sku' => '1234'

}
test_delete('4' => @product)
delete_errors.should == {}
md.should == {}

これは、製品'4'のアダプタのdeleteメソッドを呼び出します。

注:master document(:md)は更新され、上記のように確認することができます。

delete_errors

直前のソースアダプタのdelete以降からのredisに格納されたエラーを返します(クエリのエラーと同様の構造)。

md

redisに格納されたソースアダプタのマスタドキュメント(:md)を返します。これは@result ハッシュのハッシュ構造と同様です。

たとえば、

md.should == { 
"1"=>{"name"=>"Acme", "industry"=>"Electronics"},
"2"=>{"name"=>"Best", "industry"=>"Software"}
}

cd

ソースアダプタとテスト中のクライアントのclient document(:cd)を返します。master document(:cd)とclient document(:cd)はqueryが実行されたあと、等しくなります。

たとえば、

test_query.size.should > 0
md.should == cd

RhoSyncアプリケーションのデプロイ

RhoSync 2.0アプリケーションは標準的なsinatraアプリケーションです。シナトラ本には、RhoSyncアプリケーションを製品として稼働させる前にぜひ読むべき素晴らしいいくつかのデプロイドキュメントがあります。

デバイスに対してpingを実行

RhoSync 2.0はユーザーのデバイスにpingする簡単なruby APIを用意しています。デバイスにメッセージを通知したり、rhodesアプリケーションの応答の仕方を制御したりすることに利用できます。

pingのAPI

Iphone.ping(params)

Blackberry.ping(params)

バルク同期

場合によっては、特にデバイスのアプリケーションの初期化中には、オブジェクトのかなりの数を同期させる必要があります。これは、データをメガバイト単位でデバイスに送信する可能性があります。このような場合には、増分同期は完了にしばらくかかることがあります。RhoSyncの"バルク同期"機能を使用することで、このプロセスを高速化します。

rhosyncサーバーにRhodesアプリケーションがバルクデータの取得を要求した場合、RhoSyncアプリケーションは以下のように動作します:

  • すべてのソースアダプタの'query'メソッドを実行し、バックエンドサーバーからオブジェクトの最新のセットを取得する
  • デバイスの適切なdbファイルを生成 - Blacberryにはhsql,
    その他にはsqliteを生成します。RhoSyncはsqlite3-ruby gemをsqlite dbファイルを生成するために使い、vendor/hsqldata.jarをBlackBerryのdbファイルを生成するために使います。(javaがインストールされて、hsqldata.jarを実行するように設定されていることを確認してください)
  • Rhodesアプリケーションは生成中にdbファイルが利用可能かポーリングします。ファイルが生成されると、Rhodesはロードしてデバイス上にインストールします。デバイス上の以前のオブジェクトはバックエンドから最新のセットに置き換えられますので注意してください。

バルクデータ同期プロセスが完了すると、このデータソースを通常の増分同期プロセスを使用して同期を続行できます。しかし、通常の同期プロセスはsync_typeを:bulk_sync_onlyと対応するソースに設定することにより無効にします。

バルク同期を有効に

デバイス上のrhodesアプリケーションにおいて、rhoconfig.txtのbulksync_stateを0にすると、次の同期が行われるときに、バルク同期が起動します:



bulksync_state = 0

アプリケーションがバルク同期を行った後は、bulksync_stateに1が設定され、次の同期が行われる際にはバルク同期は行われません。アプリケーションでrubyを使って、bulksync_stateに再び0を設定することで、次の同期サイクルでバルク同期を強制的に行うことができます:

Rho::RhoConfig.bulksync_state = '0'

バルク同期のデータファイル

デフォルトでは、バルク同期のデータファイルはアプリケーションのルートフォルダ、'data'ディレクトリの下に格納されます。Rhodesアプリケーションからバルクデータが要求されると、RhoSyncはbulk_sync_poll_interval有効期限が切れていないならば、ファイルへのリンクを返します。期限切れの場合は、RhoSyncはRhodesにwaitコマンドを返し、新たなバルクデータファイルを生成するresque_jobsを待ち行列に入れます。デフォルトでは、bulk_sync_poll_intervalには1時間(3600秒)に設定され、settings.ymlで設定可能です:


:development:
:redis: localhost:6379
:licensefile: settings/license.key
:syncserver: http://localhost:9292/application/
:bulk_sync_poll_interval: 3600

画像やバイナリブロブの同期(blob sync)

メタデータ

メタデータのフレームワークは、ランタイムにおける動的なアプリケーションのレイアウトを提供するRhoSync/Rhodes2.0の特徴です。メタデータドキュメントを確認してください。

非同期ジョブ

RhoSync2.0は非同期ジョブを管理・実行するするために、resqueライブラリを使用します。非同期ジョブを使用する場合、アプリケーションが大規模なデータの処理を必要としたり、built-inのpush通知を使ってデバイスへpingしたり、長時間かかる処理を必要とする場合に、特に便利です。

非同期ジョブの種類

RhoSyncは、次のジョブをサポートします:

バルクデータ

バルクデータジョブは、RhoSyncがデータファイルを用意するために利用されます。

BulkDataJob.enqueue(params)

デバイスに対してping

Pingのジョブはdevice pingを実行するために利用されます。

PingJob.enqueue(params)

例:

PingJob.enqueue(
{
"user_id" => current_user.login,
"message" => "New products available!",
"badge" => 1,
"sources" => ['Product']
}
)

ソース

ソースジョブは、非同期にソースアダプタの待ち行列キューを実行するために使用されます。

SourceJob.enqueue(params)

非同期ジョブを有効にする

非同期ジョブの実行

RhoSyncジョブを実行するには一つ以上のresque workerが動作している必要があります。たとえば、すべてのジョブキューを処理するひとつのresque workerを起動するには:



cd <your rhosync app>
QUEUE=* rake resque:work

複数のworkerを起動するには(この場合、5):


cd <your rhosync app>
QUEUE=* COUNT=5 rake resque:workers

RhoSyncのAPI

RhoSync APIは、RhoSyncアプリケーションの管理制御とデバッグ機能を提供します。詳細はRhoSync API docsを参照してください。

RhoSyncコンソール

RhoSyncコンソールとWebアプリケーションは、ブラウザからRhoSyncアプリケーションを制御したりデバッグしたりすることができます。RhoSyncアプリケーションの一部またはスタンドアロンのWebアプリケーションとして、それを実行することができます。

RhoSyncアプリケーションの一部としてコンソールアプリケーションを起動するには、以下をconfig.ruで指定します:

# Setup the url map
run Rack::URLMap.new \
"/" => Rhosync::Server.new,
"/resque" => Resque::Server.new,
"/console" => RhosyncConsole::Server.new # Add this line to run console app as part of RhoSync

RhoSyncコンソールは、すべてのユーザー、デバイスとデータソースに関連付けられているデータへのアクセスを提供します。我々は、開発モードでのみ走らせて、製品版では無効することをお勧めします。

RhoSync 1.xのソースアダプタを2.0へ移行

RhoSync2.0のソースアダプタのAPIが変更されているため、既存のソースアダプタを1.xから2.0へ変更するには、アダプタのコードの細かい変更が伴います。

APIの変更点

initialize(初期化)

変更はありません。

login(ログイン)

変更はありません。

query(クエリー)

1.x:

query #=> takes no args, or optionally takes conditions,limit,offset

2.0:

query(params=nil) #=> takes optional params sent by the client using search

sync(同期)

すべてのActiveRecord固有のコード、またはObjectValueクラスを使用しているコードを削除します。ActiveRecordまたはObjectValue ActiveRecordのクラスはもうありません。

create(作成)

1.x:

create(name_value_list,blob=nil) #=> name_value_list is an array

2.0:

create(create_hash,blob=nil) #=> create_hash is a hash containing the attributes and values

update(更新)

1.x:

update(name_value_list) #=> name_value_list is an array

2.0:

update(update_hash) #=> update_hash is a hash containing the attributes and values
# update_hash contains n 'id' element for the object to be updated

delete(削除)

1.x:

delete(name_value_list) #=> name_value_list is an array

2.0:

delete(object_id) #=> object_id is the id of the object to delete

logoff(ログオフ)

変更はありません。

page(ページ)

2.0ではこのメソッドを削除します。代わりにstash_resultを使用してください。これは@resultハッシュを隠し、その他の処理にも使うことができます。

移行例

このソースアダプタ(product.rb)があったとしましょう。

このアダプタをRhoSync 2.0アプリケーションへ移行するには、次のようにします:

  • 2.0のソースを生成します:


cd <my-rhosync-app>
rhosync source product
  • sources/product.rbのqueryメソッドの内容を置換します:
    url="http://rhostore.heroku.com/products.json"
parsed=nil
open(url) do |f|
parsed=JSON.parse(f.read)
end
@result={}
parsed.each { |item|@result[item["product"]["id"].to_s]=item["product"] } if parsed @result
  • Rails.loggerやconditions,limitそしてoffsetを削除したことに注意してください。RhoSync 2.0では、これらは必要とはされません。
  • create,update,deleteメソッドの手順を繰り返します。前のセクションに記載されているAPIの変更に注意してください。
  • 最後に、完全なアダプタがこのようになります: http://gist.github.com/415136
  • そしてspec/product_spec.rbにいくつかのspecを書きます。http://gist.github.com/415138

貢献

RhoSyncに機能を追加したい?レポートまたは修正したいバグを見つけたら?

RhoSyncの問題を報告

バグ、特徴、機能拡張をRhoSyncの問題へ報告してください。

RhoSyncのspecを走らせる

環境が開発用に最新であることを確認するために、rhosync specを先ず走らせます:

  1. RhoSyncリポジトリをフォークする
  2. 新しいレポジトリをcloneします:
    git clone git://github.com/<yourhandle>/rhosync.git
    cd rhosync
  3. Jewelerをインストール:
    [sudo] gem install jeweler
  4. Jewelerは、開発の依存関係の欠如を識別するためにしています。実行して、報告された不足しているgemsをインストールしてください:
    rake check_dependencies
  5. hsqldataをインストール :
    git clone git://github.com/rhomobile/hsqldata.git
    cd hsqldata
    ant
    mkdir -p <path-to-rhosync>/vendor/
    cp bin/hsqldata.jar <path-to-rhosync>/vendor/
  6. rake #=>デフォルトですべてのrhosync specが走ります


すべてがパスしたら(pending specはOK)、環境は開発のための準備が整っています。もし特定のgemのインストールで問題が発生したり、specが正しく動作しなったりした場合、ご自由にrhomobile google groupへ知らせたり、issueに記録したり、hop on IRCで他のRhoSync開発者とチャットしたりしてください。

パッチの貢献

これで、環境の準備ができて、あなた自身の変更を加えることでできます!

  1. テーマとなるbranchを作ります:
    git checkout -b cool_new_feature
  2. テストを書きます( 例 )
  3. 変更を加えます...
  4. 関連ドキュメントを追加(RDocと、該当する場合はREADMEを更新)
  5. branchにプッシュ:
    git checkout -b cool_new_feature
  6. テーマのbranchへのリンクを含んだGitHubのissueを作成します。

以上です。コーディングの際には、これらのruby styleガイドラインをお勧めします。

ベンチマーク

詳細はbenchmarksのページを参照してください。


2010年6月14日月曜日

Rhomobile Tutorial2

以下のドキュメントは、英語の原文を日本語へ翻訳したものをRhomobile社の許可のもと、公開しています。
公式なドキュメントはRhomobile社のサイトをご覧ください。
また、この文書は2010/6/4(JST)の情報がもとになっています。
この日本語の翻訳について問題・質問などがある場合、コメントを残してください。それ以外については、本ドキュメント内にある問い合わせ先にお願いします。

The following document (a translation of the English original into Japanese) is published with Rhomobile permission.
If you need official documents, please visit Rhomobile site.
In addition, the following document is based on 2010/June/4 (JST) information.
If you have any question, problem about the Japanese translation, please leave your comment. Except for that, refer contacts in the document.

Tutorial2


このチュートリアルでは、現在出荷しているスマートフォンにRhodesとRhoSync 2.0を使用してネイティブモバイルアプリケーションを構築する方法を説明します。具体的にどのようにRhodes controllerやテンプレートを作成し、バックエンドアプリケーションからデバイスへデータを同期するためにRhoSyncソースアダプタ(source adapter)を作成する方法について説明します。このアーキテクチャはここで見ることができます。


目次


1 Rhodesアプリケーションの作成(Build)

Rhodesのアプリを書くのは次の手順から成ります:

  • Rhodesのインストール
  • Rhodesアプリの生成
  • データmodel(モデル)のRhodes controller生成
  • controller(コントローラ) actionのview(ビュー)を編集
  • アプリケーションをテスト

Rhodesのインストール

Rhodesフレームワークでは2つの方法が動作します。最初の方法はRhodes gemを使ってRhodesをインストールする方法で、このチュートリアルで説明する、推奨されれる方法です。2番目の方法はソースを直接使う方法です。Using Rhodes From Source

続ける前にRubyとRubyGemsのインストールを確認してください。

  • Windowsでは、 RubyInstallerがRubyをインストールする便利な方法です
  • RubyGemsは.tgzファイル・.zipファイルと.gemのダウンロードを提供します。.zipファイルがいいでしょう。

Windowsは、gemをインストールする必要なUnixツール(例えば、'make')は付属していません。これらのツールを取得する方法は色々ありますが、GnuWin32プロジェクトがこれらのツールを提供し、GetGnuWin32インストーラ経由で便利にインストールできます。

Rhodesを使用する最初の手順は、Rhodes gemをインストールすることです(OS X上で、このコマンドの前に"sudo"を入力することがあります)

gem install rhodes

TIP:rake taskやrhogemコマンドを実行している間に、"no such file to load -- something"というメッセージが表示されたなら、これは通常'[sudo] gem install something'することで解決されます。


Rhodesをインストールしたら、アプリをbuild(作成)する対象のプラットフォームSDKが必要になります。この説明はここにあります。


このgemと必要なSDKをインストールした後、コマンドを実行する必要があります。



rhodes-setup

これは様々なプラットフォーム用のSDKをインストールした場所を尋ねます。このインストールスクリプトは、SDKの場所の最適な推測を表示するでしょう。別の場所を入力するか、その提案をそのまま使うために空白のままにすることもできます。あなたが特定のプラットフォーム向けのbuild(作成)をしないならば(たとえばWindows上でiPhoneを構築できません)、そのSDKの場所を空白のままにすることができます。それぞれのプラットフォームごとの前提条件はBuilding Rhodes Apps in Support Platformsで見つけることでできます。

1.2 Rhodesアプリケーションの生成

最初のステップは、アプリケーションと基本となるファイルを生成することです。これは、前の手順でインストールされたRhodes gemの一部RhoGen(Rhodesジェネレータ)ユーティリティで行います。

先ず、StoreManagerと呼ばれるアプリケーションを次のコマンドで生成します:


rhogen app storemanager http://localhost:9292/application

これは、"storemanager"と呼ばれるアプリケーションのディレクトリを生成し、複数のファイル生成します。また、上記の3番目の引数はRhoSyncサーバーのデータソース(次のセクションで説明するようにデータを同期したい場合に必要)へのURLであることに注意してください。具体的には、次のオプションがファイルrhoconfig.txtへ設定されます:



syncserver ='http://localhost:9292/application'

オフライン・データを同期する必要がない場合は、3番目の引数は除外することができます。

アプリのデフォルトのホーム画面がstoremanager/app/index.erbファイルに定義されます。アプリケーションが表示するものを作るために、そのHTMLを編集することができます。標準のHTML技術でそこから他のHTMLファイルやERBファイルにリンクすることができます。その後、rake taskでアプリケーションを構築することができます。たとえば、iPhone用にビルドしシミュレータを実行するには、次のコマンドを入力します:


cd storemanager
rake run:iphone

20100512 - px2wrmj1bj7yixjy7fp2d31yw6.png

他のプラットフォームやシミュレータ用にビルドするには、例えばBlackBerryエミュレータで動作させるには"rake run:bb"のように、適切なrake taskを実行します。すべての可能なrake taskを表示するには次のコマンドを入力します:


rake -T

model(モデル)を生成

アプリケーションがコンパイルされ実行できたら、model(モデル)とcontroller(コントローラ)の追加を行うことができます。model(モデル)を生成したとき、Rhodesはモデルの表示と編集用に標準的なUIのファイルも作成されます。これは、標準のmodel(モデル)-view(ビュー)-controller(コントローラ)のパラダイムに準じます。

"product"モデルを生成して、それにいくつかの属性を与えてみましょう。



cd storemanager
rhogen model product brand,name,price,quantity,sku

RhoGenがコントローラ(product_controller.rb)といくつかのHTMLテンプレート(.erbファイル)を作成するのが分かるでしょう。これらは指定されたmodel(モデル)のオブジェクトを読んだり編集したりするものです。


Generating with model generator:
[ADDED] app/Product/index.erb
[ADDED] app/Product/edit.erb
[ADDED] app/Product/new.erb
[ADDED] app/Product/show.erb
[ADDED] app/Product/index.bb.erb
[ADDED] app/Product/edit.bb.erb
[ADDED] app/Product/new.bb.erb
[ADDED] app/Product/show.bb.erb
[ADDED] app/Product/product_controller.rb
[ADDED] app/Product/product.rb
[ADDED] app/test/product_spec.rb

Rhodes view(ビュー)の編集

見た目を合わせるようにHTMLをカスタマイズするために、生成されたERBを編集することができます。一般的には、model(モデル)のindexページへのリンクをホーム画面に配置します。以下はStore Managerアプリ用に生成されたトップレベルのindex.erbファイルです。

<div id="pageTitle">
<h1>Storemanager</h1>

</div>

<div id="toolbar">
<div id="leftItem" class="blueButton">
<%= link_to "Sync", :controller => :Settings, :action => :do_sync %>

</div>
<% if SyncEngine::logged_in > 0 %>
<div id="rightItem" class="regularButton">
<%= link_to "Logout", :controller => :Settings, :action => :logout %>

</div>
<% else %>
<div id="rightItem" class="regularButton">
<%= link_to "Login", :controller => :Settings, :action => :login %>

</div>
<% end %>
</div>

<div id="content">
<ul>
<li>

<a href="#">
<span class="title">Add Links Here...</span>
<span class="disclosure_indicator"></span>
</a>

</li>
</ul>
</div>

Productのmodel(モデル)のインデックスページとテンプレートへのリンクを配置するため、"Add links here"のtitleがあるリスト・アイテムを以下で置き換えます:

<li>
<a href="Product">

<span class="title">Products</span>
<span class="disclosure_indicator"></span>
</a>
</li>

20100512 - grk9ymqwj66jypdckthmm5484n.png

この最上位レベルのページや他のページを、任意のHTMLで編集することができます。ここではHTMLやRubyを教えることはしませんが、たくさんの良い文献があります。

2 Rhodesでさらに行うこと

Rhodesの開発にRhoHubホスト・サービスを使ったより長いチュートリアルがあります。Technical FAQはRhodesにおいて個々のタスクを行う方法が記述されています。次のセクションでは、アプリとRhoSyncでデータを同期する仕組みを追加する方法について説明します。

RhoSyncとアプリケーションとのデータを同期の追加

RhoSyncは同期フレームワークです。デバイスのクライアント・コンポーネントとRubyが動作することができるサーバで動くサーバ・コンポーネントから構成します。RhoSyncでは、エンタープライズのバックエンドのquery(クエリ)、create(作成)、update(更新)、およびdelete(削除)の少量のコードを書くことが要求されます。これらの操作のためのRubyのコードの集まりを、"source(ソース)"または"source adapter(ソースアダプタ)"といいます。

RhoSync依存関係をインストール

RhoSync 2.0をインストールしてください



rhosync app storemanager-server
cd storemanager-server/

LinuxまたはMac上で最初に実行する場合、dtachをインストールする必要があります:


sudo rake dtach:install

インストールの確認

そしてredisとrhosyncサーバーを実行することができます:


rake redis:start
rake rhosync:start

すべてがうまくいけば、次のような表示が見えるでしょう:



[07:01:15 PM 2010-05-04] Rhosync Server v2.0.0.beta1 started...

注意:config.ruのsession secretを編集するように求められるでしょう

RhoSync source adapterの定義

一度RhoSyncをインストールしたら、バックエンド・アプリケーションと統合するRhoSync sourceをbuild(生成)する準備ができたことになります。RhoSync sourceを定義するため、バックエンドのデータソースと対話する一握りの操作:login(ログイン)、query(クエリ)、sync(同期)、create(作成)、update(更新)、delete(削除)、logoff(ログオフ)を特定する必要があります。以下のコードはRhoSyncのリリース2.0(ソースからビルドする場合、これはRhoSyncのmaster branchです)に適合します。

storemanager-serverディレクトリから、product modelのsource adapterを生成します:


rhosync source product

これはproduct adapterとproduct specの2つのファイルを生成します。


Generating with source generator:
[ADDED] sources/product.rb
[ADDED] spec/sources/product_spec.rb

以下のようなファイルを見つけることができるでしょう。生成されたsource adapterは、必要なすべてのメソッドに例外が発生するコードになっています。source generatorを使用する必要がないことに注意してください。Rubyのファイルを作成して、それをlibディレクトリに置くこともできます。source adapterのクラス名は、クライアントのmodel(モデル)と一致していなければなりません。

class Product < SourceAdapter
def initialize(source,credential)
super(source,credential)
end

def login
# TODO: Login to your data source here if necessary
end

def query
# TODO: Query your backend data source and assign the records
# to a nested hash structure called @result. For example:
# @result = {
# "1"=>{"name"=>"Acme", "industry"=>"Electronics"},
# "2"=>{"name"=>"Best", "industry"=>"Software"}
# }
raise SourceAdapterException.new("Please provide some code to read records from the backend data source")
end

def sync
# Manipulate @result before it is saved, or save it
# yourself using the Rhosync::Store interface.
# By default, super is called below which simply saves @result
super
end

def create(create_hash,blob=nil)
# TODO: Create a new record in your backend data source
# If your rhodes rhom object contains image/binary data
# (has the image_uri attribute), then a blob will be provided
raise "Please provide some code to create a single record in the backend data source using the create_hash"

end

def update(update_hash)
# TODO: Update an existing record in your backend data source
raise "Please provide some code to update a single record in the backend data source using the update_hash"
end

def delete(object_id)
# TODO: write some code here if applicable
# be sure to have a hash key and value for "object"
# for now, we'll say that its OK to not have a delete operation
# raise "Please provide some code to delete a single object in the backend application using the hash values in name_value_list"
end

def logoff
# TODO: Logout from the data source if necessary
end
end

generatorはまた、settings/settings.ymlを編集し、いくつかのデフォルトのオプションでproduct adapterをsources sectionへ追加します。



#Sources
:sources:
Product:
:poll_interval: 300

次のステップはバックエンド・サービスを呼び出す独自のコードを、login(ログイン)、query(クエリ)、create(作成)、update(編集)、delete(削除)とlogoff(ログオフ)のメソッドに埋め込むことです。

以下にどのようなコードになるかを説明します。

RhoSync query(クエリ)

もしREAD-ONLYの認証なしのソースアダプタを作るのならば、ここで説明するようにレコードを取得するqueryメソッドを一つ書くだけで終わります。以下はRESTインターフェースを公開している簡単な製品カタログ(http://rhostore.heroku.com)とやり取りするqueryメソッドの見本です。RhoSyncは任意のプロトコルで動作することができます。この例は、一般的なRESTインターフェースでのJSON over HTTPです。RhoSyncソースアダプタは純粋なRubyコードで、必要なものはなんでも簡単に接続して解析することができるRubyライブラリ(別名、gems)があります。--queryコードはちょっと違います。

カタログのすべての製品を返す私たちのサンプルWebサービス( http://rhostore.heroku.com/products.json )はこのようなデータを返します:


[
{"product":
{"name": "iPhone", "brand": "Apple", "updated_at": "2010-05-11T02:04:57Z", "price": "$299.99", "quantity": "5", "id": 649, "sku": "1234", "created_at": "2010-05-11T02:04:57Z"}},
{"product":
{"name": "Accord", "brand": "Honda", "updated_at": "2010-05-13T22:24:48Z", "price": "$6000", "quantity": "", "id": 648, "sku": "123", "created_at": "2010-05-11T02:04:53Z"}}
]

データを解析する以下のRubyコードは、REST webサービスを簡単にアクセスするため、標準のRuby JSONライブラリとRestClientライブラリを使っています。この例では、ハッシュキーとしてproductレコードのidを使用します。注:このハッシュのキーはstring(文字列)でなければなりませんし、値はRubyのハッシュとして表現されるname-valueのペアの任意のセットとなります。インスタンス変数@resultはqueryメソッドによって設定されるユニークなidでインデックスされるこの"ハッシュのハッシュ"でなければなりません。それはbaseとなるSourceAdapter classのsync()メソッドがObjectValueテーブルを作成できるようにするためです。

利用する標準ライブラリをファイルの先頭で宣言する必要があります:

require 'json'
require 'rest_client'

簡単にするため、コンストラクタにwebサービスのベースURLを持つインスタンス変数@baseを追加し、その値を設定します

  def initialize(source,credential)
@base = 'http://rhostore.heroku.com/products'

super(source,credential)
end

次に、クエリメソッドの入力:

  def query
parsed=JSON.parse(RestClient.get("#{@base}.json").body)

@result={}
if parsed
parsed.each do |item|
key = item["product"]["id"].to_s
@result[key]=item["product"]
end
end
end

上のコードはもっと簡潔になるかもしてませんが、Ruby言語に慣れていないプログラマにとって読みやすく書かれています。Rubyに始めたばかりの場合は、良い手引きがその他の言語からRuby読むことができます。

RhoSync Sync(同期)メソッド

syncコードはクエリの結果をばらばらにしてobject_valuesテーブルに格納します。ObjectValueオブジェクトを作成し、source_idとuser_id属性と共にそのオブジェクト・属性・値の属性を設定することができる独自のコードを書くことができます。しかし、@resultにハッシュのハッシュを設定すると、この作業を避けることができます。syncメソッドをこのようにするだけです:

def sync
super
end

上記のメソッドはデフォルトで生成されるメソッドで、もう何もする必要はありません。

queryメソッドで処理を分割する方法もあります。@resultに設定せずsyncメソッドがハッシュのハッシュを設定する方法です。このハッシュのハッシュは(上記のqueyメソッドで説明したように)外側のハッシュのキーがそれぞれのオブジェクトのIDとなるハッシュです。内部ハッシュの各ハッシュキーは、個々のオブジェクトの属性を表します。注意しなければならないのは、すべてのデータ型は文字列(string)でなければなりません。(よって、ハッシュ値は、すべて整数ではなく文字列である必要があります。たとえば、以下のようになります。

  @result={"1"=>{"name"=>"inner tube","brand"=>"Michelin"},"2"=>{"name"=>"tire","brand"=>"Michelin"}}

クライアントからの同期テスト

redisを実行していることを確認して、サーバーを起動(または再起動)してください:

  rake rhosync:start

サーバーが起動すると、ソースアダプタのコードがロードされます。Rubyコードで構文エラーがある場合は、その旨が表示されサーバーは起動しません。ランタイムエラーがある場合は、ソースアダプタが呼ばれるまでそのエラーは表示されません。

このサーバーのURLがアプリケーションに設定されていることを確認してください。サーバーがデフォルトのポートでlocalhost上で実行されている場合、次の行をrhoconfig.txtの下部に設定する必要があります:

syncserver ='http://localhost:9292/application'

storemanager/app/Product/product.rbのmodel(モデル)でsync(同期)を有効にします。

class Product
include Rhom::PropertyBag

enable :sync
end

起こっていることの感触をつかむためには、ターミナル・ウィンドウでサーバーのログ(rake rhosync;startの出力)と別のウィンドウでクライアントログのtail(末尾)を見ることです。たとえば、iPhone上でクライアントのログの末尾を表示するには:

  tail -f rholog-User.txt

サーバーと同期するには、クライアントはログインする必要があります。生成されたアプリにはログインとその他一般的な機能のための画面があります。これらは、一般的にアプリのデザインに合うように変更します。重要だけどありきたりなユーザー認証や設定を実装する前に、アプリケーションのコア機能に焦点を当てることができるので、この生成されたUIは便利でしょう。

  1. 画面の下部にある歯車のアイコンをクリックして設定画面に移動します
  2. 任意の名前とパスワードでログインします。生成されたコードはどんなログインでも許可しますが、application.rbで変更することができます。
  3. ログインが成功した場合は、設定画面でClientIDが表示されます。ClientIDは、あなたが初めてログインしたときに生成され、クライアントのデータベースに格納されます。それはrhosyncに必要な一意の識別子として機能します。(注:この値はログインをまたいで保持されますが、クライアントのデータベースをリセットしたりアプリを再インストールした場合、新しいClientIDが生成されます)
  4. sync(同期)は自動的にトリガされます。homeアイコンをクリックし"Products"を選択すると、サーバーからのレコードを見ることができるでしょう。

RhoSyncでオブジェクトの作成

create(作成)メソッドには、RhoSyncサーバーが"new_object_hash"という新しいレコードを含むハッシュを渡すと考えてください。例えば、それは次のようなものです:

{"name"=>"sku","value"=>"1", "name"=>"name", "value"=>"inner tube"}

create(作成)メソッドは、最後のsync(同期)以降クライアントで作成されたすべてのオブジェクトに対して一度ずつcallされます。createするコード(またはeditやdeleteも)は動作するために、この設定された配列を使用する必要があります。以下は、HTTP POSTを受け付けるhttp://heroku.com/rhostoreに対するcreateメソッドの一例です。createメソッドは、後々クライアントで変更可能なオブジェクトの一意のID string(文字列)を返す必要があります。もしidが返されない場合は、クライアント・オブジェクトをREAD-ONLY(読み取り専用)と取り扱うべきでしょう。なぜなら、そのオブジェクトはsync(同期)できないからです。

def create(new_object_hash, blob=nil)
result = RestClient.post(@base,:product => new_object_hash)

# after create we are redirected to the new record.
# The URL of the new record is given in the location header
location = "#{result.headers[:location]}.json"


# We need to get the id of that record and return it as part of create
# so rhosync can establish a link from its temporary object on the
# client to this newly created object on the server

new_record = RestClient.get(location).body
JSON.parse(new_record)["product"]["id"].to_s
end

コードを変更した後、ソースアダプタをリロードするために、rhosyncを再起動する必要があります。オブジェクトはクライアント上ですぐに作成されますが、サーバーに送信されるのは次回のsync(同期)時であることに注意してください。設定画面の"Perform Sync"をクリックすると、すぐにサーバーコードをテストすることができますが、通常の同期は5分ごとに発生します。

認証

生成されたアプリケーションコードには、認証をフックする"application.rb"ファイルがディレクトリのルートにあります。完全なファイルは次のようになります:

class Application < Rhosync::Base
class << self
def authenticate(username,password,session)
true # do some interesting authentication here...
end

# Add hooks for application startup here
# Don't forget to call super at the end!
def initializer(path)
super
end

# Calling super here returns rack tempfile path:
# i.e. /var/folders/J4/J4wGJ-r6H7S313GEZ-Xx5E+++TI
# Note: This tempfile is removed when server stops or crashes...
# See http://rack.rubyforge.org/doc/Multipart.html for more info
#
# Override this by creating a copy of the file somewhere
# and returning the path to that file (then don't call super!):
# i.e. /mnt/myimages/soccer.png
def store_blob(blob)
super #=> returns blob[:tempfile]
end
end
end

Application.initializer(ROOT_PATH)

バックエンドのWebサービスが認証を必要とする場合は、単にauthenticateメソッドにコードを追加して、認証が成功したらtrueを返し、クライアントからのアクセスの認証が失敗したらfalseを返すようにしてください。たとえば、

    def authenticate(username, password, session)
[... connect to backend using API and authenticate... ]
if success
# we store these in the session encrypted
session[:someprivatedata] = someprivatedata
end
return success
end

詳細情報

RhoSync 2.0 :新しいRhoSync 2.0のマニュアル。RhoSync 2.0の違いと新しく追加された機能について

APIのサンプル :このRhodesアプリケーションは、個々のRhodes機能を紹介するコードが書かれています。

このような本もありますbook on Rhomobile。さらなるご質問については、 私たちへメールかRhomobile Google Groupへ参加してpostしてください。


2009年8月22日土曜日

Rails on heroku

heroku.com上でRailsAppをdeployしたときのメモ

環境:
MacOSX 10.5.8
ruby 1.8.7 (2008-08-11 patchlevel 72)
rails 2.3.3
heroku-gem/1.1

手順:
localでdevelop

$ rails heroku
$ cd heroku
$ ./script/generate i18n_scaffold status content:text
$ rake db:migrate

*localでdbのmigrateして、deploy時に必要に応じてdb:pushする

$ ./script/generate i18n ja
$ cat config/environment.rb
config.time_zone = 'Tokyo'
config.i18n.default_locale = 'ja'

*i18n化 http://rails-i18n.org/wiki/wikipages/i18n-rails-guide


$ ./script/plugin install git://github.com/technoweenie/restful-authentication.git
$ mv vendor/plugins/restful-authentication/ vendor/plugins/restful_authentication/

>IMPORTANT FOR RAILS > 2.1 USERS To avoid a NameError exception (lighthouse tracker ticket), check out the code to have an underscore and not dash in its name:
*restful_authenticationはrenameが必要(?)のため、vendor/pluginsにinstall。他のはheroku上でinstallする。

$ ./script/generate authenticated user sessions
$ cat app/controllers/application_controller.rb
include AuthenticatedSystem
$ rake db:migrate

*restful_authenticationのためのmigrate

$ vi config.environment.rb
config.gem "searchlogic"
config.gem "will_paginate"
config.gem "jpmobile"

*localでは他のpluginはsudo gem installでインストールしておく


$ cat .gems
searchlogic
will_paginate
jpmobile

*.gemsにheroku上でのmanifestを書いておく。
herokuのplatform上に既にインストールされているgemsはhttp://installed-gems.heroku.com/

で、いろいろ開発して、git&heroku


$ heroku create appname
$ heroku info --app appname

*gitアカウント作成、キー登録後に、appの作成

$ git init
$ git add .
$ git commit -m "my first commit"


$ git remote add heroku git@heroku.com:appname.git
$ git push heroku master

*git remoteリポジトリにherokuを登録し、masterブランチにpush


$ heroku db:push

*必要に応じて、delopmentDBをdeployのherokuにpush。もしくはheroku rake db:migrateか?

$ heroku restart

*app serverのリスタート

2009年7月24日金曜日

gem 1.3.5 さくら

%cat .cshrc
set path $HOME/ROOT/bin
setenv RUBYLIB $HOME/ROOT/lib
setenv GEM_HOME $HOME/ROOT/lib/ruby/gem

%mkdir $HOME/ROOT
%ruby setup.rb --prefix=$HOME/ROOT

%gem18 -v
1.3.5

%gem18 update --system
Updating RubyGems
Nothing to update

%setenv RB_USER_INSTALL true
%gem18 install hpricot

2009年7月4日土曜日

MacOS Leopard メニューを隠す

1. Appを右クリック、パッケージの中身を表示を選択
2. ContentsフォルダーのInfo.plistを開く
3. Information Property Listにアイテムを追加
4. 新しいKeyに「Application UI Presentation Mode」を追加して、Valueを「4」(All Suppressed)に
5. 編集したInfo.plistを保存

2009年5月27日水曜日

Ruby AWS API

amazon-ecs http://amazon-ecs.rubyforge.org/doc/
ruby-amazon http://raa.ruby-lang.org/project/ruby-amazon/
ruby-aws (ruby-aaws) http://www.caliban.org/ruby/ruby-aws/
ruby-aws http://rubyforge.org/projects/ruby-aws

2009年5月15日金曜日

searchlogic と asct_as_taggable_on

ActiveRecordへのhookのタイミングか、searchlogicでtagが指定できない。
とりあえず、
  • find_tag_with でtagによる絞り込みをオブジェクトへ
  • 絞り込んだオブジェクトに対して、searchlogic
でOK。ソースは読んでいない