Ruby on Rails と Eclipse による iPhone アプリケーション開発: 第 2 回 iPhone 向けコンテンツをクライアントに表示する

iUI と iPhone リスト構造を使う方法

iPhone と iPod touch は、Mobile Safari を米国で最も人気のあるモバイル・ブラウザーにしました。Mobile Safari は通常の Web ページのレンダリングにも十分対応できますが、それでも数多くの Web 開発者たちは iPhone を対象としたアプリケーションのバージョンを作成しています。連載「Ruby on Rails と Eclipse による iPhone アプリケーション開発」の第 2 回では、ドリルダウン・リストをナビゲーション手段として使用する一般的な方法を学びます。

Noel Rappin, Vice President of Rails Development, Pathfinder Development

Noel Rappin は、Pathfinder Development (http://www.pathf.com) で Rails 業務の責任者を務めています。Web アプリケーション開発では 10 年の経験を積んでいます。彼が博士号を取得した Georgia Institute of Technology では、オブジェクト指向の設計概念の教授法を学びました。彼の著書には『Professional Ruby on Rails』、共著書には『wxPython in Action and Jython Essentials』があります。詳しくは、http://www.pathf.com/blogs、http://10printhello.blogspot.com を読んでください。



2008年 7月 08日

連載第 1 回では、既存の Ruby on Rails Web アプリケーションを例に、iPhone ユーザーに対応したアプリケーションへの拡張プロセスを開始しました。そのなかで重点を置いたのは、デスクトップ・ユーザーに送信するのとは異なるコンテンツを iPhone ユーザーに送信できるようにするとともに、iPhone ユーザーがビューを切り替えて完全なサイトを表示できるようにするために、サーバー・サイドに必要なサポートです。

第 2 回と第 3 回 (※現在翻訳中) では、ユーザーに送信される実際のコンテンツ、そしてそのコンテンツを iPhone または iPod touch ユーザーの期待に応えるものにする方法に重点を置いてプロセスを続けます。この第 2 回で焦点とするのは、ドリルダウン・リストをナビゲーション手段として使用する一般的な方法、続く第 3 回では、フォーム、グループ化、そしてさらに高度なその他のトピックを取り上げます。

この記事では、CSS (Cascading Style Sheets)、そして iUI という JavaScript ライブラリーを使用して iPhone コンテンツを操作します。iUI ライブラリーには、Apple による iPhone 用のヒューマン・インターフェース・ガイドラインに適合する CSS クラス、ならびに iPhone OS アプリケーション固有のインターフェースを模倣した横方向のスワイプを処理する JavaScript が備わっています。ただし、アプリケーションで常に iUI を使用する必要があるとは限らないので、一般的な要素の処理に必要な実際の CSS および JavaScript についても説明します。またこの記事では、適切な Rails のプラクティスに従って、共通 iUI パターンの HTML を Ruby ヘルパー・メソッドに分解しました。これらのメソッドは、Rails プラグインにバンドルされているので、このプラグインをダウンロードして任意の Rails アプリケーションに追加することができます。

今回も引き続き、第 1 回で使用したサンプル・サイト、Soups OnLine を拡張していきます。Soups OnLine は、私の著書『Professional Ruby On Rails』でサンプルとして作成したサイトで、スープのレシピを載せているサイトです。ほとんどの場合、このサイトの詳細がこの記事に関係してくることはありません。iPhone インターフェースを組み立てるために必要なステップは、サンプル Soups OnLine の詳細に結び付けられていないからです。唯一重要な詳細は、このアプリケーションは iPhone 以前のフォームになっているため、アプリケーションに含まれる RecipesController というコントローラーがその index メソッドを使ってレシピを掲載する処理を行うという点です。そこで、第 1 回ではサイトの Mobile Safari バージョンの表示切り替えを管理する BrowsersController を追加しました。

この記事に記載するサンプル・コードを使用するには、Ruby エディター、または Eclipse などの IDE が必要です。さらに、iPhone ディスプレイを模倣するブラウザー・シミュレーターもあれば役に立ちます。オプションとしては、Eclipse 用の Aptana iPhone プラグイン、Mac 用の iPhoney、そして公式の iPhone ソフトウェア開発キット (SDK) シミュレーターがあります。それぞれのシミュレーターのインストール方法と使用方法、そして利点と欠点については、この連載の第 1 回で説明しました。今回の記事に記載するサンプル・コードでは、iUI ツールキットと rails_iui プラグインを使用します。

iPhone とユーザー・エクスペリエンス

iPhone は何気なく見ただけでも、ほぼ一瞬にして従来のデスクトップ・ブラウザーとは若干違っているのがわかるはずです。例えば、バッグのフロント・ポケットに納まる標準的な大きさのノート PC にさえもサイズが及びません。このような違いは、iPhone のユーザーにとって最適な Web アプリケーションを作成する方法に計り知れない影響を与えます。なかでもとりわけ重要な違いとしては、以下のものがあります。

  • iPhone の画面サイズ (320x480) は、デスクトップ Web アプリケーションがターゲットとする最小のアプリケーションより遥かに小さくなっています。また、iPhone 画面のアスペクト比も、標準的なデスクトップまたはノート PC のモニターとはかなり異なります。
  • iPhone のピクセル密度は、小さなサイズのテキストを読みやすくするとともに、画像の相対サイズを変更しやくするため、デスクトップ・モニターに比べてかなり高くなっています。
  • ユーザーは Mobile Safari のビューを 90 度回転して、サイズだけでなく、さらに画面のアスペクト比も変更できるようになっています。
  • Mobile Safari とのタッチスクリーン・インターフェースは、マウス・インターフェースより精度が落ちます。つまり、ボタンやリンクなどのターゲットは、デスクトップ・アプリケーションでの場合よりサイズを大きくして、間隔も離さなければなりません。
  • iPhone は低速なネットワーク条件で使用されることがよくありますが、それでもユーザーは自分たちの操作に対する応答がほとんど即時に返ってくることを強く期待します。

このような違いがあることから、iPhone Web 開発は、画面に一度にどれだけ大量に詰め込めるかを競い合うゲームになることはありません。ナビゲーション・バー、ロゴ、広告、そしてコンテンツのすべてをどうにか iPhone 画面に詰め込めたとしても、ネットワークの速度が落ちてモバイル・ユーザーを苛立たせることになるか、あるいはモバイル・ユーザーがごく小さなポイントを操作できるように指の爪を研がざるを得なくなるのがおちです。iPhone Web 開発が目標とするのは、画面に多くのものを詰め込むことではなく、簡潔で単純な UI によってモバイル・ユーザーが最も重要な機能にアクセスできるようにすることです。おそらく Web アプリケーションの一部の機能については、モバイル・ユーザーが利用する際に何度もタップすることになるでしょうが、アプリケーションのコアは最前部中央となります。

iPhone 固有のバージョンを作成した人気の高い Web サイトの例としては、Amazon と Digg の 2 つが挙げられます。Digg では、この記事で説明する iUI フレームワークの変形を使って iPhone のルック・アンド・フィールを模倣している一方、Amazon では Mobile Safari ブラウザーでも極めて整った表示となるようにカスタマイズされています。以下に、Mobile Digg の写真を記載します (何らかの理由により、Amazon.com ではシミュレートが上手くいきません)。

図 1. iPhone 向け Digg
iPhone 向け Digg

Digg と Amazon ではいずれも、モバイル・ユーザー向けにコア機能 (Diggの場合は主要な話題のリスト、Amazon の場合は検索機能) を減らしています。このように機能を絞ることによって、サイトは iPhone 画面に納まり、モバイル・ユーザーがサイトの最も重要な機能に素早くアクセスできるようになっています。この記事の残りでは、サイトを iPhone に合わせるための方法を紹介します。


iUI を Rails アプリケーションに追加する

iPhone のルック・アンド・フィールを持った Web アプリケーションにするには、主に 2 つの方法があります。

  • Apple のサンプル・コードまたはその他の見栄えのよいサイトをベースにしたサイトに、独自の CSS と JavaScript を追加する
  • 既存のツールキットを使用する

既存のツールキットのなかで最も優れているのは、iUI です。このツールキットを使用する場合、ボタンに使われる画像、フォントの選択肢、JavaScript のエフェクトがすでに作成されているため、サイトのコンテンツに専念できるという利点があります。ただし以下のように、サイトの編成に関して特定の決まりに従わなければならないという欠点もあります。

  • 特定の場所では使用できる DOM (Document Object Model) ID が決められています。
  • サーバーとの対話はデフォルトで、Ajax (Asynchronous JavaScript + XML) によって行われます。

簡単にリストの概念に当てはめられるサイトに iUI が最適かどうかは疑わしいところですが、Apple の iPhone に関するヒューマン・インターフェース・ガイドラインでは、iPhone コンテンツの編成に「特に効果的な方法」として、リスト・フォーマットを提唱しています。したがって、可能な場合にはリスト編成を検討してください。

iUI は、JavaScript ファイル、CSS ファイル、そして一連の画像が含まれる単一のディレクトリーとしてパッケージ化されています。Rails ではこれらの種類のファイルを特定のディレクトリーで検索するため、iUI のファイル配布を以下のようにして Rails アプリケーションに統合する必要があります。

  • iui.js という JavaScript ファイルは、Rails アプリケーションの public/javascripts ディレクトリーに移動させます。
  • iui.css という CSS ファイルは、public/stylesheets ディレクトリーに移動させます。
  • 画像ファイル (.png および .gif) は、public/images ディレクトリーに移動させます。

上記のようにファイルを移動させることによって CSS ファイルの相対 URL が崩れてしまうので、url(button.png) という形のすべての参照は url(/images/button.png) に変更してください。こうすれば、CSS ファイルが Rails ディストリビューションに含まれる画像の場所を正確に見つけられます。

上記の手順を手作業で行うのは面倒だと思ったら、rails_iui プラグインに含まれている一連の Rake タスクで、CSS ファイルでの URL 変更を含め、iUI のダウンロードおよびインストールを実行することができます。該当するコマンドは rake iui:install です。また、iUI には、短時間でダウンロードできるように余分な空白を削除した CSS ファイルと JavaScript ファイルの圧縮バージョンも含まれています。圧縮バージョンのファイル名は iuix.js と iuix.css です。自動 Rake タスクには、ファイルの圧縮バージョンを使用するオプションが用意されています。

iUI がプロジェクト内にインストールされたら、JavaScript ファイルと CSS ファイルをレイアウトに追加してください。iPhone レイアウト・ファイル (このサンプルでは、app/views/layouts/recipes.iphone.erb) のヘッダーには、以下の 2 行が含まれていなければなりません。

    <%= stylesheet_link_tag 'iui' %>
    <%= javascript_include_tag 'iui' %>

rails_iui プラグインを使用している場合には、ただ単に <%= include_iui_files %> と表現することができます。

これで、iPhone コンテンツの作成に取り掛かる準備ができました。


iPhone レイアウトを作成する

Soups OnLine アプリケーションの元のバージョンでは、ナビゲーションはサイドバーにあり、メインのコンテンツは中央にありました。これを iPhone で表示しても同じようにはならないため、アプリケーションをリスト構造に変換します。まず、アプリケーションのホーム・ページを元のバージョンとほとんど同じナビゲーションの選択項目がリストとして表示されるようにします。そして、エントリーごとにユーザーがドリルダウンできるようにします。例えば、Recipes のナビゲーション・エントリーを選択すると、最近追加されたレシピのリストが表示されます。このリストには、詳細な項目を表示するためのオプションもあります。これらのエントリーが、それぞれ特定のレシピを表示したページにリンクするという仕組みです。

ここでは、以下の 3 段階でコードを説明します。

  • rails_iui プラグインが定義する Rails ヘルパー
  • このプラグインが iUI で定義されたスタイル・クラスを使用して生成する HTML
  • CSS 自体についての詳細 (iUI 以外のプロジェクト用)

デフォルトでは、iUI は通常のリンク・クリックに対するレスポンスを無効にします。iUI はページ全体を再描画する代わりに Ajax 呼び出しを行い、ページの可視の領域を再描画します。これにより、iUI は各リンクに、iPhone の iPod アプリケーションでのアーティストやアルバムのリストをドリルダウンするときの効果に似た横方向のスワイプ効果を追加することが可能になります。一方、この効果は、アンカー・タグの target 属性を変更することによって、2 通りの方法で無効にすることができます。まず、リンクのターゲットが _self に設定されている場合には、ページ全体を更新表示するという通常のハイパーリンクの振る舞いが使用されます。リンクのターゲットが _replace に設定されている場合には、アンカー・タグがサーバー・リクエストの結果に置き換えらます。

Rails の観点からすると、この iUI 構造はメインのレイアウトが 1 度だけしかレンダリングされないということを意味します。メイン・レイアウトがレンダリングされた後は、すべての呼び出しは Ajax となるからです。通常の link_to の呼び出しでさえも Ajax 呼び出しとして扱われることになり、:layout => false を設定して送信されます。さらに、iPhone Web アプリケーションでの単純な Ajax アクティビティーには link_to_remote を使う必要がないことも意味します。

つまり、このアプリケーションの初期ユーザー・ページにはナビゲーションのみが表示されるということです。したがって、アプリケーション自体のテキストをレンダリングするのではなく、単にメイン・ナビゲーションを備えたレイアウトだけを表示するアプリケーションのデフォルト・ルートをセットアップする必要があります。このルートを配置する明確な場所はないので、第 1 回で作成した BrowsersController に追加します。それには、config/routes.rb ファイルに map.root :controller => "browsers" という行を追加してください。

app/controllers/browsers_controller に含まれるこのコントローラーの動作は、極めて単純明快です。

リスト 1. デフォルトのレイアウト・ルート・コントローラーの動作
    layout "recipes"
    def index
      respond_to do |format|
        format.html {redirect_to recipes_url}
        format.iphone {render :text => "", :layout => true}
      end
    end

iPhone の場合、コントローラーはテキストのないレイアウトだけをレンダリングします。リクエストが HTML を対象にしている場合には、RecipesController index ページにリダイレクトします。この index ページは、アプリケーションのデスクトップ・ビューのメイン・ページです。

iPhone のレンダリング動作は、レンダラーで行われます。リスト 2 に示すように、現在このレンダラーは rails_iui プラグインで定義されたヘルパー関数のいくつかを呼び出して、iUI が要求するページをセットアップするようになっています (rails_iui ヘルパーは、rails_iui プラグインが Rails アプリケーションの vendor/plugin/rails_iui ディレクトリーに配置されると、自動的にすべてのビューで使用できるようになります)。

リスト 2. iPhone 用メイン・ナビゲーションのレイアウト body
    <body>
      <%= iui_toolbar "Soups OnLine", new_search_url %>
      <%= iui_list iphone_menu.items,
          :top => content_tag(:h1, "Soups OnLine", :class => "header"),
          :bottom => link_to ("Switch To Desktop View",
              {:controller => "browsers", :action => :desktop},
              :class => "mobile_link") %>
    </body>

上記のコードによって、図 2 のような表示になります。

図 2. iPhone 用 Soups OnLine のメイン・ナビゲーション
iPhone 用 Soups OnLine のメイン・ナビゲーション

ここでは 2 つのヘルパー関数が使われています。最初の iui_toolbar は、多くの iPhone アプリケーションで上部に灰色がかった青色のツールバーをセットアップするヘルパーです。Rails ヘルパーはリスト 3 のようになります。

リスト 3. iUI ツールバーの Rails ヘルパー
    def button_link_to(name, options, html_options = nil)
      html_options[:class] = "button"
      link_to(name, options, html_options)
    end
    
    def iui_toolbar(initial_caption, search_url = nil)
      back_button = button_link_to("", "#", :id => "backButton")
      header = content_tag(:h1, initial_caption, :id => "header_text")
      search_link = if search_url 
                    then button_link_to("Search", search_url, :id => "searchButton")
                    else ""
                    end 
      content = [back_button, header, search_link].join("\n")
      content_tag(:div, content, :class => "toolbar")
    end

このコードは以下の HTML になります。

リスト 4. iUI ツールバーの HTML
    <div class="toolbar">
      <a href="#" class="button" id="backButton"></a>
      <h1 dddd="header_text">Soups OnLine</h1>
      <a href="http://localhost:3000/search/new" class="button" 
          id="searchButton">Search
      </a>
    </div>

HTML のいくつかの項目は、iUI によって定義されます。まず、toolbar は上部ツールバーの色、サイズ、位置を定義するクラスです。このクラスに含まれる h1 タグも、iUI によって具体的に白いテキストとして定義されています。backButton は iUI が確保している DOM ID で、リンクがクリックされると iUI JavaScript によって作成されます。header_text という DOM ID は、次の rails_iui ヘルパーが使用します。リスト 5 は、 iUI から抜粋した関連 CSS です。

リスト 5. iUI ヘッダー CSS
     body > .toolbar {
         box-sizing: border-box;
         -moz-box-sizing: border-box;
         -webkit-box-sizing: border-box;
         border-bottom: 1px solid #2d3642;
         border-top: 1px solid #6d84a2;
         padding: 10px;
         height: 45px;
         background: url(/images/toolbar.png) #6d84a2 repeat-x;
     }

     .toolbar > h1 {
         position: absolute;
         overflow: hidden;
         left: 50%;
         margin: 1px 0 0 -75px;
         height: 45px;
         font-size: 20px;
         width: 150px;
         font-weight: bold;
         text-shadow: rgba(0, 0, 0, 0.4) 0px -1px 0;
         text-align: center;
         text-overflow: ellipsis;
         white-space: nowrap;
         color: #FFFFFF;
     }

2 番目の rails_iui ヘルパー (リスト 6 を参照) は、メニュー項目のリストから実際のリストを生成します。メニュー項目オブジェクト自体の作成は、このコンテキストでは重要ではありません (詳細は、「参考文献」に記載した『Professional Ruby on Rails』を参照してください)。この記事でのメニュー項目は、キャプション属性と、そのメニュー項目をクリックするとどこにあるコンテンツを取得しに行くのかを表す URL 属性とを持つオブジェクトです。

リスト 6. rails-iui リスト・ヘルパー
    def list_element(item)
      onclick_one = "$('header_text').innerHTML='#{item.caption}'; "
      onclick_two = "$('backButton').addEventListener('click', 
          function() {$('header_text').innerHTML='Soups OnLine'; }, false);"
      link = link_to(item.caption, item.option_hash, 
          :onclick => "#{onclick_one} " + " #{onclick_two}")
      content_tag(:li, link)
    end

    def append_options(list_content, options = {})
      list_content = options[:top] + list_content if options[:top]
      list_content += options[:bottom] if options[:bottom]
      list_content
    end

    def iui_list(items, options = {})
      list_content = items.map {|i| list_element(i)}.join("\n")
      list_content = append_options(list_content, options)
      content_tag(:ul, list_content, :selected => "true")
    end

メニュー・リストに含まれるそれぞれの項目が、HTML リストの中の固有の li 要素を取得します。この要素に含まれるのは、正しい URL へのリンク、そしてツールバーのキャプションを管理するための JavaScript です。JavaScript ハンドラーが行うことは 2 つあり、まず、ツールバーのテキストを変更して新しいリンクを反映させます (新しいリンクは Ajax 呼び出しを行ってページの body を更新するだけなので、テキストの変更はクライアント・サイドでしか処理できません)。次に、Back (戻る) ボタンのハンドラーを変更して、Back (戻る) ボタンがツールバーのヘッダーを Soups OnLine に戻すようにします。ドリルダウン全体をとおしてヘッダーを同期させておくという問題は、これで完全に解決されることにはなりませんが、この記事を書いている時点では、iUI と rails_iui プラグインのいずれも、この機能をサポートしていません。

すべてのリスト項目は、selected=true という特殊な属性のペアを持つ HTML UL リストに 1 つにまとめられます。iUI はこの属性のペアを使用して、iPhone ビューポートの body に配置するリストを判断します。つまり、selectedtrue に設定されたページに HTML タグがある場合、CSS は CSS 宣言 display: block を使用して、ビューポートの body 全体にこのタグを割り当てます。このタグの割り当てが body タグのサイズ定義と効果的に連動して、選択された項目にビューポート全体が提供されます。このような仕組みは確かに役立つはずです。iUI サンプルの 1 つでは、それぞれに異なるドリルダウンのレベルを表す複数のリストが同じページに配置されていますが、1 つのリストだけが選択されたリストとして最初に表示され、他のリストには同じページ内でアンカーや名前のリンクによってアクセスすることができるからです。

一方、選択されたリストがビューポート全体を占めることになるため、Soups OnLine ロゴを示すヘッダーと Switch to Desktop View (デスクトップ・ビューに切り替え) リンクを示すフッターはどちらも UL タグのなかに配置しなければならなくなります。このヘルパーには、任意の HTML をリストの上部と下部に組み込むためのオプションが用意されています。それは、前に記載したレイアウト body からのスニペット (リスト 2) に含まれている :top:bottom です。最終的な HTML はリスト 7 のようになります。ここには、メニューの最初の要素に対応するリスト全体を記載しましたが、その他の要素のリストについては記載していません。

リスト 7. iUI リストの HTML
    <ul selected="true">
      <h1 class="header">Soups OnLine</h1>
      <li>
        <a href="/recipes" 
          onclick="$('header_text').innerHTML='Most Recent Recipes';   
                $('backButton').addEventListener('click', 
                function() {$('header_text').innerHTML='Soups OnLine'; }, false);">
                Most Recent Recipes</a>
      </li>
      
      ### OTHER LIST ITEMS REMOVED
      
      <a href="/browsers/desktop" 
          class="mobile_link">Switch To Desktop View</a></ul>

Most Recent Recipes 項目をクリックすると、横方向に画面が流れ、図 3 に示す画面が表示されます。この画面のヘッダーと Back (戻る) ボタンは、すでに iUI JavaScript によって変更されています。

図 3. 1 レベルのドリルダウン
1 レベルのドリルダウン

この画面を作成するには、Recipe Controller の index メソッドに含まれる respond_to ブロックに、format.iphone {render :layout => false} を配置する必要があります。以下を参照してください。

リスト 8. Recipe の index 動作
    def index
      @recipes = Recipe.find_for_index(params[:type])
      respond_to do |format|
        format.html # index.html.erb
        format.xml  { render :xml => @recipes }
        format.iphone {render :layout => false}
      end
    end

レンダリングされる app/views/recipes/index.iphone.erb ファイルも、同じ rails_iui ヘルパーを使用します。ここで前提となるのは、Recipe オブジェクトが、<%= iui_list @recipes %> ヘルパーによって呼び出される caption メソッドと option_hash メソッドに適切に応答できることです。


置換を使用してリストを拡張する

前に説明したように、iUI アンカー・タグでターゲットを _replace に設定すると、タグの結果が自動的に元のリストに置き換わります。この設定は、リストの最後の要素に「次の 25 項目」などのテキストを表示させ、元のリストと同じリストに新しい項目を表示させてユーザーがリスト全体を簡単にスクロールアップ/スクロールダウンできるようにする場合に便利です。

これまでの手順で作成したヘルパーを使って置換機能を有効にするには、iui_list メソッドを 2 つの方法で拡張します。まず、リスト・ヘルパーに必要となるのは、「その他の項目」をリストに追加するためのオプションです。とりあえず、このオプションはリストの下部に表示される追加オプションという前提とします。次に、このオプションのクリックに対する応答が、li タグ付きで、ただし ul タグでは囲まれていないリストを返す必要があります。ul タグは変更中のページにすでに存在するからです。

この実装の最初の部分は、iUI の特殊な _replace および _self の振る舞いを管理するための特殊な link_to ヘルパーです。それに続いて、引数 target に応じて各種のリンク・タイプを切り替えるメソッドを追加しました。この両方を以下に示します。

リスト 9. iUI リンク・ヘルパー
    def link_to_replace(name, options, html_options = {})
      html_options[:target] = "_replace"
      link_to(name, options, html_options)
    end

    def link_to_external(name, options, html_options = {})
      html_options[:target] = "_self"
      link_to(name, options, html_options)
    end

    def link_to_target(target, name, options, html_options = {})
      if target == :replace 
        link_to_replace(name, options, html_options)
      elsif target == :self or target == :external
        link_to_external(name, options, html_options)
      else
        link_to(name, options, html_options)
      end
    end

上記のリンク・ヘルパーを配置すれば、iui_list ヘルパーとそれに付随する append_options メソッドを拡張することで新しい機能を実現することができます。

リスト 10. iUI リンク・ヘルパー
    def append_options(list_content, options = {})
      list_content = options[:top] + list_content if options[:top]
      list_content += list_element(options[:more], :replace) if options[:more]
      list_content += options[:bottom] if options[:bottom]
      list_content
    end

    def iui_list(items, options = {})
      list_content = items.map {|i| list_element(i)}.join("\n")
      list_content = append_options(list_content, options)
      if options[:as_replace] 
        list_content
      else
        content_tag(:ul, list_content, :selected => "true")
      end
    end

追加の list 要素は、実際には append_options メソッドの 2 行目に追加されます。この要素は :more オプションに渡され、items リスト要素と同様にキャプションと URL が設定されることになります。iui_list に含まれる最後の if 文により、:as_replace => true オプションが渡された場合には ul リスト・タグが省略されます。

追加された最後のリンクでの iui_list メソッドの呼び出しは、以下のようになります。ここでは :more オプションを使用して、リストの一番下に配置されるリスト要素を提供しています。

    <%= iui_list @recipes, 
        :more => ListModel.new(nil, "Next 25 items", more_recipes_url) %>

more_recipes_url に対するコントローラーの動作は、その結果に関わらず、:as_replace => true を指定して iui_list を呼び出すことになります。

iUI では、もう 1 つの特殊な技をリストで使えます。それは、CSS の group クラスを使用すると、音楽用のネイティブ iPod アプリケーションで使われているリスト表示のようなヘッダーをリスト内に表示できるということです。

図 4. グループ・ヘッダー付きのリスト
グループ・ヘッダー付きのリスト

グループ・リストを作成する rails_iui ヘルパーは、単純なリストのコードのほとんどを再利用します。このメソッドでは、ブロックを引数に取って動的にヘッダーを決定します。

リスト 11. グループ・リスト用の rails_iui ヘルパー
    def iui_grouped_list(items, options = {}, &group_by_block)
      groups = items.group_by(&group_by_block).sort
      group_elements = groups.map do |group, members|
        group = content_tag(:li, group, :class => "group")
        member_elements = [group] + members.map { |m| list_element(m) }
      end
      content_tag(:ul, group_elements.flatten.join("\n"), 
          :selected => "true")
    end

iui_grouped_list メソッドが使用する Rails ActiveSupport の group_by メソッドは、リストを [group, [members]] の 2D リストに変換します。このリストをソートすることで、グループが確実にアルファベット順にリストされます (このメソッドに至る前に、個別の項目を順に配置する必要があります)。

以下は、このメソッドのビュー・コードの一例です (ブロックは、レシピのタイトルの先頭文字を返します)。

    <%= iui_grouped_list(@recipes) {|r| r.title[0, 1]} %>

今までのまとめと、次回の予告

ここまでのところで、Mobile Safari ユーザーのためにカスタム・コンテンツを提供する方法を学びました。また、iPhone ユーザーの期待に合ったルック・アンド・フィールで、しかも速度の遅いエッジ・ネットワークでも素早くロードできるリストを使ってサイトのナビゲーションを表示する方法もわかったはずです。

連載の第 3 回 (※現在翻訳中) では、ユーザーがドリルダウンしたときに表示する内容について説明し、実際にコンテンツに取り掛かります。その内容には、パネルとダイアログの表示、そして一般的な iPhone の Rounded-Rectangle のスタイルを使用する方法も含まれます。さらに、ユーザーがデバイスの表示を回転させて Mobile Safari を横向きにしたときの変更に対処する方法についても説明する予定です。


ダウンロード

内容ファイル名サイズ
Sample codeos-eclipse-iphoneruby2-v1c.zip116KB

参考文献

学ぶために

製品や技術を入手するために

  • git://github.com/noelrappin/rails-iui.git に用意された rails_iui プラグインをインストールしてください。
  • Aptana.com にアクセスして Aptana Studio をダウンロードしてください。
  • Aptana Update Site から、Aptana の RadRails および iPhone プラグインを入手してください。
  • IBM alphaWorksEclipse 技術の最新ダウンロードを調べてください。
  • Eclipse Foundation から Eclipse Platform およびその他のプロジェクトをダウンロードしてください。
  • IBM 製品の評価版をダウンロードして、DB2®、Lotus®、Rational®、Tivoli®、および WebSphere® のアプリケーション開発ツールとミドルウェア製品を使ってみてください。
  • IBM ソフトウェアの試用版を使用して、次のオープンソース開発プロジェクトを革新してください。ダウンロード、あるいは DVD で入手できます。

議論するために

  • Eclipse に関する質問を投じる最初の場所として、Eclipse Platform newsgroups があります (このリンクをクリックすると、デフォルト Usenet ニュース・リーダー・アプリケーションが起動され、eclipse.platform が開きます)。
  • Eclipse newsgroups には Eclipse を利用し、拡張することに関心を持つ人達のために、さまざまなリソースが用意されています。
  • developerWorks blogs から developerWorks コミュニティーに加わってください。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Open source, Web development
ArticleID=326515
ArticleTitle=Ruby on Rails と Eclipse による iPhone アプリケーション開発: 第 2 回 iPhone 向けコンテンツをクライアントに表示する
publish-date=07082008