Hatena::ブログ(Diary)

このブログは証明できない。

2009-07-03

[][]SinatraとiUIを使って50行以下でiPhone用Webアプリを作る!

Rubyの軽量WebフレームワークSinatra」を紹介する記事を書いたところ、思わぬ反響がありました。


今日は、SinatraとiUIを使ってiPhone用Webアプリを作る方法について。オリジナルはこちら。

日本語に翻訳してブログに掲載していいという許可をいただきました。Thank you!


Word、ExcelPDFなどのドキュメントをうまいこと表示してくれるのは、iPhoneのスバラシイところです。でも、コンピューターやiPhoneにあるドキュメントを見るのは、それほど簡単なことではありません。もちろん、ドキュメントを添付したメールを自分に送ることはできます。でも、ドキュメントを探すために、iPhone上のメールを探しまわらなければなりません。(訳注:OS 3.0のSpotlightを使えばOK?)


それで、App StoreにはこのためのオサレiPhoneアプリがあるのは知ってます。でも、その代わりに、SinatraとiUIを使って、サクッとWebアプリを作ってみましょう。


これが、今から作るWebアプリです。(訳注:このスクリーンショットはshunsukが用意したもので、オリジナルとは異なります。今回のチュートリアルに従うと、このようになります。)

f:id:shunsuk:20090703200518p:image


Sinatraはホントにスバラシイ最小限のWebフレームワークです。2、3行のコードでWebアプリケーションを作ることができます。iUIはWebサイトを簡単にiPhoneっぽくするためのJavaScriptCSS、イメージのセットです。SinatraとiUIを使うと、シンプルなiPhoneアプリがホントに簡単に作れます。


まず、Sinatra gemインストール

> gem install sinatra

それでは、簡単なアプリを作ってみましょう。'butler'(訳注:「執事」のことです)というアプリです。butlerのディレクトリを作ります。

> mkdir butler
> cd butler
> touch butler.rb

butler.rbをお好みのエディタで開いて、下のように入力してください。

require 'sinatra'
get "/" do
  "<h1>Your files, sir.</h1>"
end

butlerをスタート。

> ruby -rubygems ./butler.rb

ブラウザで、http://localhost:4567を開きます。(ブラウザはコンピューターのでもiPhoneのでもいいのですが、コンピューターのブラウザの方が、Sinatraデバッグメッセージを読みやすいです。)"Your files, sir"というページが表示されるはずです。おめでとう!最初のSinatraアプリの完成です。簡単でしょ?


それでは、butlerをもう少し便利にしましょう。Sinatraはpublicというサブディレクトリに、いろいろなファイルを置くことができます。publicディレクトリには後でJavaScriptCSSのファイルを置くので、実際には./public/filesにファイルを置きます。そして、便利なようにリンクを作っておきます。最後に、テスト用のファイルを2つほど入れておきましょう。

> mkdir -p public/files
> ln -s public/files files
> echo "foo" > public/files/foo.txt
> echo "bar" > public/files/bar.txt

butlerにそれぞれのファイル(foo.txtとbar.txt)へのリンクが欲しいところです。そのために、ヘルパーを作りましょう。helperブロックにヘルパーを入れられます。1個のファイルへのリンクを生成するヘルパーを作ります。

require 'sinatra'
require 'pathname'
 
get "/" do
  html = "<h1>Your files, sir.</h1>"
  dir = "./files/"
  html += file_link("./files/foo.txt")
  html
end
 
helpers do
  def file_link(file)
    filename = Pathname.new(file).basename
    "<a href='#{file}'>#{filename}</a><br/>"
  end
end

変更を確認するために、ブラウザをリロードしてください。アプリケーション再起動する必要はありませんよ。Sinatraは自動的に変更をリロードしてくれます。スバラシイ!foo.txtへのリンクが表示されるはずです。クリックすると、foo.txtの中身を見ることができます。


特定のファイルをハードコードしたくありません。./filesディレクトリの中のすべてのファイルを見れるbutlerを作りましょう。

require 'sinatra'
require 'pathname'
 
get "/" do
  html = "<h1>Your files, sir.</h1>"
  dir = "./files/"
  Dir[dir+"*"].each do |file|
    html+=file_link(file)
  end
  html
end
 
helpers do
 
  def file_link(file)
    filename = Pathname.new(file).basename
    "<a href='#{file}'>#{filename}</a><br/>"
  end
 
end

では、ブラウザをリロードしてください。foo.txtとbar.txtの両方が表示されるはずです。うまくいっているように見えます。ですが、ちゃんとしたHTMLではなく、html、head、bodyタグがありません。これらのタグをすべて"get"ハンドラに書くこともできますが、コードがゴチャゴチャしてしまうでしょう。


代わりに、このコードをviewに書いてみましょう。Sinatraは他のコードの後ろにviewのコードを書くことができます。なので、アプリケーション全体を1つのファイルで作ることができるのです。説明を簡単にするために、このチュートリアルでも全体を1つのファイルに書くことにします。もしこれがイヤなら(もしくは、エディタシンタックスハイライトがおかしくなるなら)、viewのコードををviewsディレクトリに置くこともできます。それでも、同じように動きます。


ファイルの末尾にviewを追加して、ハンドラの中で使いましょう。@@ indexという宣言で、'index'というviewを定義しています。もし、viewを別のファイルにしたいなら、./views/index.erb(Hamlも使えます)に置くだけです。また、ハンドラ内で@linksを定義していますが、これはviewの中からも使えます。

require 'sinatra'
require 'pathname'
 
get "/" do
  dir = "./files/"
  @links = Dir[dir+"*"].map { |file|
    file_link(file)
  }.join
  erb :index
end
 
helpers do
 
  def file_link(file)
    filename = Pathname.new(file).basename
    "<a href='#{file}'>#{filename}</a><br/>"
  end
 
end
 
use_in_file_templates!
 
__END__
 
@@ index
<html>
  <head>
  </head>
 
  <body>
    <h1>Your files, sir.</h1>
    <%= @links %>
  </body>
</html>

ブラウザをリロードしてください。見た目が変わらないので、オモシロくないですね。でも、簡単にviewの見た目を変えることができます。


このページには、ひとつ重大な問題があります。iPhoneでは、それほど使い勝手がよくないのです。そこで、iUIの登場です。butlerディレクトリダウンロード解凍。必要なファイルをpublicディレクトリにコピーします。

> mkdir iui
> cd iui
> wget http://iui.googlecode.com/files/iui-0.13.tar.gz
> tar -xzvf iui-0.13.tar.gz
> cd ..
> mkdir public/images
> cp iui/iui/*.png public/images
> cp iui/iui/*.gif public/images
> mkdir public/javascripts
> cp iui/iui/*.js public/javascripts
> mkdir public/stylesheets
> cp iui/iui/*.css public/stylesheets

iUIを使うために、viewにJavaScriptCSSを含める必要があります。また、いくつかの要素をviewのbodyに追加する必要があります。全部終わったら、viewのコードはこのようになります。

<html>
  <head>
    <meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
    <style type="text/css" media="screen">@import "/stylesheets/iui.css";</style>
    <script type="application/x-javascript" src="/javascripts/iui.js"></script>
  </head>
 
  <body>
    <div class="toolbar">
    <h1 id="pageTitle"></h1>
    </div>
    <ul id="home" title="Your files, sir." selected="true">
       <%= @links %>
    </ul>
  </body>
 
</html>

このhtmlはチョット解りづらいかも知れません。でも、ご心配なく。./iui/samples/にサンプルがあります。(WEbには解りやすいiUIのチュートリアルもあります。)最後に、file_linkヘルパーをiUIに対応させます。

helpers do
 
  def file_link(file)
    filename = Pathname.new(file).basename
    "<li><a href='#{file}' target='_self'>#{filename}</a></li>"
  end
 
end

target='_self'に注意してください。 iUIで普通の方法でリンクを開くのに必要です。これを書かなかった場合、現在のページにファイルをロードするためのAJAX呼び出しが使われます。PDFのようなバイナリファイルを開くときに使うと、おかしくなります。


最終的なコードはこのようになります。

require 'sinatra'
require 'pathname'
 
get "/" do
  dir = "./files/"
  @links = Dir[dir+"*"].map { |file|
    file_link(file)
  }.join
  erb :index
end
 
helpers do
 
  def file_link(file)
    filename = Pathname.new(file).basename
    "<li><a href='#{file}' target='_self'>#{filename}</a></li>"
  end
  
end
 
use_in_file_templates!
 
__END__
 
@@ index
<html>
  <head>
    <meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
    <style type="text/css" media="screen">@import "/stylesheets/iui.css";</style>
    <script type="application/x-javascript" src="/javascripts/iui.js"></script>
  </head>
 
  <body>
    <div class="toolbar">
      <h1 id="pageTitle"></h1>
    </div>
    <ul id="home" title="Your files, sir." selected="true">
      <%= @links %>
    </ul>
  </body>
 
</html>

これで、iPhone用Webアプリが50行以下で書けました。SinatoraとiUI、ありがとう。iPhoneでファイルを見たい時は、下のどちらかの方法でファイルをコピーしてください。

> cp path/to/my_file ./files

または。

> ln -s path/to/my_file ./files

そして、butlerを起動します。

> ruby -rubygems ./butler.rb

コンピューターのIPアドレスを調べて、iPhoneブラウザでhttp://<ip>:4567を開くだけです。


私はbutlerを主にホームネットワークで使っています。もし、外出先でファイルを見れるようにしたいなら、ファイアウォールのポートを開けてやる必要があります。それは、このチュートリアルの範疇じゃないので、ググってみるといろいろ出てきます。


Enjoy!


スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証