nkjmkzk.net

powered by Kazuki Nakajima

Archive for 10月, 2012

まさに手間いらず。転送アップグレード

Force.comで開発したアプリケーションはノンストップで新しいバージョンにアップグレードすることができます。

データを退避する必要もなく、そのまま上書きする形でいつでもアップグレード可能です。アップグレードはユーザーがアプリのインストールURLをクリックすることで任意におこなうことができます。

さらにWinter’13のリリースでこのアップグレードがさらに強力になり、アプリの開発者側が能動的にユーザー環境をアップグレードできるようになりました。


ユーザーは何もする必要がなく、気がついたら常に最新のバージョンを使っている、ということが可能になったわけです。

この開発者からの能動的なアップグレードを「転送アップグレード」と呼んでいます。転送アップグレードを実行する様子を1分間のビデオでみてみましょう。

これはユーザーからアップグレード作業を不要にするというベネフィットはもちろんですが、開発中のテスト作業も随分楽になります。いろんな組織にログインする必要なく、開発組織から一元的にアップグレードをおこなえるわけですから。あー、楽だ楽だ。

without comments

Written by 中嶋 一樹

10月 18th, 2012 at 4:43 pm

Posted in Uncategorized

Tagged with ,

イベレジさんのSalesforce連携アプリにみる、ソーシャルがビジネスアプリに与えるインパクト

去る10月5日のAppExchangeカンファレンスにおいて「Facebookがビジネスアプリに与えるインパクト」というテーマでキーノートセッションをおこないました。

その中で、特に具体的にそのインパクトをご説明したのがイベレジさんとSalesforceの連携アプリ企画の事例でした。

今回のキーノートセッションの肝といえるこのパートを切り出して7分間のショートビデオにまとめました。ソーシャルがビジネスに与えるインパクトは何なのか、AppExchangeアプリケーションの魅力とは何なのか?そのヒントをこのビデオの中に見つけていただければ幸いです。

*EventRegistとSalesforceの連携アプリは企画中のイメージです。本アプリは現在開発中であり、仕様・画面は変更になる可能性があります。

without comments

Written by 中嶋 一樹

10月 15th, 2012 at 6:27 pm

モーダル・ダイアログ「jquery.confirm(改)」

私はVisualforceでしばしば<apex:actionFunction>やJavascript Remotingを使ってApexコードを実行します。その処理内容は往々にして標準コントローラではまかなえない、アプリケーション依存の少し複雑な処理です。

そんなとき、確認、経過、結果を表示するため、あるいは処理中にユーザーの操作をブロックするためにモーダル・ダイアログを多用しています。

こちらのデモはレコードの削除操作をユーザーに確認し、その後削除処理中の経過を表示&ユーザーの操作をブロックし、削除結果を表示するモーダル・ダイアログです。

このモーダル・ダイアログはこちらで紹介されているjquery.confirmをベースに、画像を使用せず、activity-indicatorを組み合わせ処理中のインジケーターを表示できるようにしたりといったカスタマイズをおこなっています。

ダウンロードはこちらから。
https://github.com/nkjm/jquery.confirm-and-status

index.htmlファイルがサンプルの実装になっています。

<html>
<head>
    <link rel="stylesheet" href="jquery.confirm.css"></link>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script type="text/javascript" src="jquery.activity-indicator-1.0.0.js"></script>
    <script type="text/javascript" src="jquery.confirm.js"></script>
</head>
<body>
    <script>
        function do_status(){
            $.confirm.status({
                'title' : 'Processing',
                'message' : 'Please wait for a while...'
            });
        }

        function do_alert(){
            $.confirm.alert({
                'title' : 'Completed',
                'message' : 'Transaction has been finished.',
                'color' : '#888888',
                'button_label' : 'Close'
            });
        }

        function do_confirm(){
            $.confirm({
                'title' : 'Deleting "object"',
                'message' : 'Are you sure?',
                'button_yes_label' : 'Yes',
                'button_no_label' : 'No',
                'processing_title' : 'Processing',
                'processing_message' : 'Please wait for a while...',
                'action' : function(){
                    alert('add delete process here');
                }
            });
        }
    </script>
    <div id="container">
        <div>
            <button type="submit" onclick="do_status()">status</button>
        </div>
        <div>
            <button type="submit" onclick="do_alert()">alert</button>
        </div>
        <div>
            <button type="submit" onclick="do_confirm()">confirm</button>
        </div>
    </div>
</body>
</html>

エンジョイ。

without comments

Written by 中嶋 一樹

10月 12th, 2012 at 2:51 pm

Posted in Uncategorized

Tagged with ,

Facebookのソーシャル・チャネルを利用した広告アプリをForce.comで構築

私はFacebookが持つ機能の中で、企業活動につなげることができるパワーを次の3つに分類しています。

  • Social Profile(ソーシャル・プロファイル)
  • Social Channel(ソーシャル・チャネル)
  • Engagement

この中のソーシャル・チャネルに注目した広告アプリをForce.com上に構築し、それをひとつのデモにまとめました。ソーシャル・チャネルとは、Facebookの友達間をLikeやComment、Shareといった機能によって情報がねずみ講式に広がっていく伝播を意図しています。

このデモのユースケースは、下記の通りです。

  • 店舗マネージャはあらかじめ商品情報を広告アプリの管理画面から登録しておく。
  • とある小売店に訪れた消費者が商品を購入する際、店員が「もしFacebookでこの商品を購入したことを共有していただいたら10% 割引しますよ」とオファーする。
  • 消費者は自身のスマートフォンを用いて広告アプリのMobile Webサイトにアクセスする。
  • 消費者は自身が購入する商品をタップし、それだけでFacebookへの共有(広告)が完了する。

そのデモがこちらです。

このデモで技術的にキーとなる箇所は下記の2点です。

  • 登録した商品情報から、消費者がスマートフォンでアクセスするMobile WebサイトのHTMLを生成する
  • Mobile WebサイトからFacebookのAPIを呼び出してワンタッチで消費者のFacebook Wallに「この商品を買いました」というエントリーを投稿する

HTMLを生成する部分は、実際にはHeroku上で稼働するPHPアプリケーションがForce.comのREST APIにアクセスし、必要な商品情報を取得、jQuery Mobileでデザインされたレイアウトにその商品情報を並べるという仕組みで実装しています。

Facebookへの連携部分は、Mobile WebサイトでFacebookのJavascript用SDKをインポートし、Facebook Wallへ投稿をおこなうダイアログの表示ファンクションをfbPublishStoryとして下記のように定義しておきます。

<!-- Load facebook sdk -->
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
    FB.init({
        appId      : 'あなたのApp ID', // App ID
        status     : true, // check login status
        cookie     : true, // enable cookies to allow the server to access the session
        xfbml      : true  // parse XFBML
    });
};

// Load the SDK Asynchronously
(function(d){
    var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
    if (d.getElementById(id)) {return;}
        js = d.createElement('script'); js.id = id; js.async = true;
        js.src = "//connect.facebook.net/ja_JP/all.js";
        ref.parentNode.insertBefore(js, ref);
    }(document)
);

function fbPublishStory(product_name, photo_url, shop_url) {
    discountCode = code;
    FB.ui({
        method: 'feed',
        name: product_name + 'を買いました。',
        link: shop_url,
        picture: photo_url
    }
    return false;
}
</script>

そしてあらかじめ取得しておいた商品情報からリストを作成し、そのリストのonclickイベントに前述のFacebookのダイアログ表示のファンクションを紐付けます。

<div data-role="page" id="page_product_list" data-theme="d">
    <div data-role="header" data-backbtn="false" data-theme="d">
        <h1><?php echo LABEL_PRODUCT_LIST; ?></h1>
    </div>
    <div data-role="content">
        <ul data-role="listview" data-inset="false" data-filter="true" data-split-icon="gear" id="list_product">
        <?php
        if (is_array($sugoid_product_list['records'])){
            foreach ($sugoid_product_list['records'] as $k => $v){
                ?>
                <li>
                    <a onclick="fbPublishStory(
                                    '<?php echo addslashes($v['Name']); ?>',
                                    '<?php echo addslashes($v['sugoidiscount__discount_rate__c']); ?>',
                                    '<?php echo addslashes($v['sugoidiscount__code__c']); ?>',
                                    '<?php echo addslashes($v['sugoidiscount__description__c']); ?>',
                                    '<?php echo addslashes($v['sugoidiscount__photo_url__c']); ?>',
                                    '<?php echo addslashes($v['sugoidiscount__url_to_buy__c']); ?>'
                                );" class="product_button" id="<?php echo $v['Id']; ?>" href="#">
                        <img src=" <?php echo $v['sugoidiscount__photo_url__c']; ?>" />
                        <h3><?php echo htmlspecialchars($v['Name']); ?></h3>
                        <p>通常価格<?php echo $v['sugoidiscount__price__c']; ?>円から<?php echo $v['sugoidiscount__discount_rate__c']; ?>% OFF</p>
                    </a>
                </li>
                <?php
            }
        }
        ?>
        </ul>
    </div>
</div>

このデモのポイントは、下記の通りです。

  • ソーシャル・チャネルで関心度の高い広告を伝播していくことができる(一般的な広告より、知り合いが購入したアイテムというのは関心度が高いと考えられる)
  • コードを書くのはMobile Webサイトだけ。アプリケーションへのサインアップ、ライセンス管理、商品登録、APIといった部分はForce.comが提供するフレームワークをそのまま利用して開発をスキップできる
  • さらに、Mobile WebサイトはHerokuを使うことで無料でスタートできる

最小限の労力でソーシャルパワーを装填したアプリを開発する。そんなデモでした。

without comments

Written by 中嶋 一樹

10月 11th, 2012 at 5:37 pm

Transloaditを使ってSalesforceから透過的にファイルをAmazon S3にアップロードする

SalesforceにはAttachmentやFilesといったファイル格納機構があります。ただ、そのファイルを外部公開する(認証不要でアクセス可とする)のは少し厄介です。そういう要件がある場合は素直にAmazon S3等にアップした方がよいケースもあるでしょう。

そんなアーキテクチャーでも、ユーザーにはSalesforceを使いながら意識させずにS3にアップロードするような実装をしたいものです。また、アップロードのコードも出来る限りさぼって書きたいですよね。

アップローダーとして使えそうなツールやサービスをいろいろ見ていると、UploadifyPluploadなどがあるなー、と。結果的に私はTransloaditというサービスを使ってみました。

Transloaditは単なるアップロードツールやWidgetという域にとどまらず、画像や動画のエンコーディングという中間処理を得意とするサービスです。そしてもちろんアップロードのためのUIもjQuery Pluginとして提供してくれています。使用感はこちらの動画で確認してみてください。

実際、クロスブラウザ対応などを含め、ファイルのアップロードというのはなにかと問題が発生する意外に難しい処理です。Transloaditはそのあたりのクライアント側の制御をjQuery Pluginを提供することで開発者から解放しつつ、その後の処理もクライアントとファイル格納先(S3等)の中間に入って動作することでお任せすることができるというサービスです。

S3にファイルをアップロードするときにTransloaditはリバースプロキシのような位置づけで機能します。クライアントはjQuery Pluginを使ってファイルをTransloaditにアップロードし、アップロードされたファイルは事前に定義されたTemplateに従って処理されます。最終格納場所(S3)にファイルが保存された後にクライアントはTransloaditからJSONレスポンスでファイルのメタデータを受け取ります。上のデモ動画では、このメタデータからファイルのURLを取得してSalesforceのフィールドに保存しています。

Transloaditのサイトにもこのアップローダーの構築方法が書かれていますが、ここでも簡単に解説しておきます。

まずアカウントを作成します。Transloaditは従量課金の有料サービスですが、100MB/月までは無料で利用できます。

次にTemplateを作成します。Templateはアップロードするファイルをどの順番で、どんな処理をおこなうかを記述したファイルです。これはTransloaditの管理画面から作成することができます。上のデモ動画で定義しているTemplateは下記の通りです。

{
  "steps": {
    "store": {
      "robot": "/s3/store",
      "key": "あなたのAWS KEY",
      "secret": "あなたのAWS SECRET",
      "bucket": "nkjm-sfdc-tokyo"
    }
  }
}

次にアップロードフォームを作成します。これはVisualforceで作成することになります。

<form id="MyForm" action="http://api2.transloadit.com/assemblies" enctype="multipart/form-data" method="POST">
    <input type="hidden" name="params" value='{"auth":{"key":"あなたのAPI KEY"},"template_id":"あなたのTemplate ID","redirect_url":"{!$CurrentPage.URL}"}'></input>
    <input type="file" name="my_file"></input>
    <input type="submit" value="Upload"></input>
</form>

次に同じVisulaforceページにアップローダーとなるjQuery Pluginを追加します。

<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" />
<apex:includeScript value="https://assets.transloadit.com/js/jquery.transloadit2.js" />

<script type="text/javascript">
   // We call .transloadit() after the DOM is initialized:
   j$ = jQuery.noConflict();
   j$(document).ready(function() {
     j$('#MyForm').transloadit({
        wait: true
     });
   });
</script>

次にファイルのアップロードが完了した際にJSONレスポンスを解析して必要な情報をデータベースに保存するApexクラスを作成します。

public class transloadit_uploader {
    public final product__c product;

    public transloadit_uploader(ApexPages.StandardController controller){
      product__c p = (product__c)controller.getRecord();
      if (p.id != null){
          this.product = [select id, name, price__c, code__c, discount_rate__c, photo_url__c, url_to_buy__c, description__c from product__c where id = :p.id];
      }
    }

    public void update_photo_url(){
        string s3_url;
        if (ApexPages.currentPage().getParameters().get('transloadit') != null){
            string result_json = ApexPages.currentPage().getParameters().get('transloadit');
            JSONParser parser = JSON.createParser(result_json);
            while (parser.nextToken() != null) {
                if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) && (parser.getText() == 'url')) {
                    parser.nextToken();
                    if (parser.getText().contains('s3.amazonaws.com')){
                        s3_url = parser.getText();
                    }
                }
            }
        }
        if (s3_url != null){
            this.product.photo_url__c = s3_url;
            update this.product;
        }
    }
}

最後に、先ほどのVisualforceページに、上記のApexクラスのupdate_photo_url()を最初にキックするように<apex:page>タグにaction=”{!update_photo_url}”を追加します。

<apex:page standardController="sugoidiscount__product__c" extensions="sugoidiscount.transloadit_uploader" action="{!update_photo_url}">

最終的にデモのVisualforceページは下記のようになります。

<apex:page standardController="sugoidiscount__product__c" extensions="sugoidiscount.transloadit_uploader" action="{!update_photo_url}">
<apex:includeScript value="https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" />
<apex:includeScript value="https://assets.transloadit.com/js/jquery.transloadit2.js" />

<script type="text/javascript">
   // We call .transloadit() after the DOM is initialized:
   j$ = jQuery.noConflict();
   j$(document).ready(function() {
     j$('#MyForm').transloadit({
        wait: true
     });
   });
</script>

<apex:detail />

<apex:pageBlock title="{!$Label.sugoidiscount__upload_photo}" mode="edit">
    <apex:pageBlockSection >
        <form id="MyForm" action="http://api2.transloadit.com/assemblies" enctype="multipart/form-data" method="POST">
            <input type="hidden" name="params" value='{"auth":{"key":"あなたのAPI KEY"},"template_id":"あなたのTemplate ID","redirect_url":"{!$CurrentPage.URL}"}'></input>
            <input type="file" name="my_file"></input>
            <input type="submit" value="Upload"></input>
        </form>
    </apex:pageBlockSection>
    <apex:pageBlockSection >
        <apex:outputpanel id="product_photo" rendered="{! !ISNULL(photo_url)}">
            <img height="200px" src="{!sugoidiscount__product__c.sugoidiscount__photo_url__c}" />
        </apex:outputpanel>
    </apex:pageBlockSection>
</apex:pageBlock>
</apex:page>

エンジョイ。

without comments

Written by 中嶋 一樹

10月 11th, 2012 at 11:58 am

動的にQRコードを生成・設置できるサービス:QR-SERVER

先日開催されたAppExchange Conferenceのセッションでおこなったデモの中で、意外に皆様の関心を引いた機能の一つがQRコードの自動生成でした。

デモではとあるURLをポイントするQRコードを動的に生成し、それをブラウザ上に表示するという機能をお見せしました。そのQRコードをiPhone等のスマートフォンでスキャンさせることによって小売り店の店頭等で任意のURLに瞬時にアクセスしてもらう、というユースケースです。

実はQRコードを生成する部分は外部サービスを使えば極めてシンプルに実装できます。

先日のデモで私が利用したサービスはQR-SERVERです。

QR-SERVERは非商用であれば無償で利用できるQRコード生成サービスです。使い方も至って簡単。下記のようにQRコードで表現したい文字列をquery stringのdataパラメーターにセットしてHTTP GETでアクセスするだけで、レスポンスとしてQRコードのイメージを返してくれます。sizeパラメーターはイメージのサイズをピクセルで指定しています。

http://api.qrserver.com/v1/create-qr-code/?data=http://nkjmkzk.net//&size=150x150

つまり、Webページ上でQRコードを表示させたいときは、imgタグのsrcに前述にAPI呼び出しをセットしてあげるだけです。

<img src="http://api.qrserver.com/v1/create-qr-code/?data=http://nkjmkzk.net/&size=150x150" />

上記HTMLで下図のQRコードが表示されます。

残念なのはQR-SERVERはSSLに対応していないところです。SSLに対応している同様のサービスとしてはSPARQ CodeのQRGen APIといったサービスがあるようです。QRコードに若干ブランドタグが入ってしまうものの、QR-SERVERと同じような使用感で利用できそうなのでご興味のある方はチェックしてみてください。

without comments

Written by 中嶋 一樹

10月 10th, 2012 at 6:02 pm

Posted in Uncategorized

Tagged with ,

Herokuを使って1分でスタートできるFacebookアプリ

FacebookアプリとはFacebookの機能を取り込んだアプリケーションであり、下記の3つのタイプがあります。

on Facebookは下図のような外観で、FacebookのWebインターフェース中のキャンバスと呼ばれるエリアにiframeでアプリケーションを表示させ、Facebookサイトと一体化した形でユーザーに提供されます。このキャンバスに読み込むアプリは別途外部Webサーバーで稼働させておく必要があります。

このタイプのFacebookアプリでは、ユーザーとのEngagement(ユーザーが繰り返しアプリを使う可能性)を高めることができるのが特徴です。

一般的にFacebookユーザーはあなたのアプリを使うという意図がなくても定期的にFacebookサイトを訪問します。その際に、Notification, Counter, BookmarkといったFacebookならではの通知機能でユーザーの目をひきつけ、ユーザーがすぐアクセスできる状態でアプリへのアクセスを促すことができ、スムースにユーザーを誘導できます。

他にもFacebookのSDKを組み込んでAPIにアクセスすることで、様々なFacebookの情報を活用することができます。

そのようなon Facebookのアプリは、実は1分で作成することができます。

まずは自身のFacebookアカウントでログインし、https://developers.facebook.com/appsにアクセスします。

*まだDeveloper登録していない場合はこの後に登録プロセスがあります

右上のCreate New Appボタンをクリックします。

App Nameにアプリの名前、App NamespaceにURLの一部に使われる名前空間を入力します。そして重要なのが、Web Hostingのチェックボックスです。このチェックボックスにチェックを入れることで、アプリのホスティング環境としてHeroku上のアプリが連動して作成されます。もしすでにHerokuのアカウントを持っており、登録EmailアドレスがFacebookとHerokuで同じであれば、既存のアカウントにアプリが追加されます。もしまだHeroku のアカウントがない場合は自動的に作成されます。

captchaで認証をおこなった後に、プログラミング環境としてどのプラットフォームを選択するかが表示されます。2012年10月時点での選択肢はPHP, Ruby, Python, node.jsです。

数秒するとプロビジョニングが完了し、Go to Appボタンをクリックすることで作成されたばかりのFacebookアプリを表示させることができます。Facebookアプリはサンプルコードとともに作成されています。Log Inボタンをクリックすることで自身のアカウントでこのアプリを認可し、サイトがどのようにパーソナライズ出来得るのかという例を見ることができます。

ただしこのときはHeroku上のアプリに直接アクセスするため、on Facebookのような外観ではありません。Facebookのアプリの設定画面にもどり、Canvas PageのURLを確認し、このURLにアクセスすれば、Facebookのフレーム内にHeroku上で稼働するアプリが埋め込まれて表示されます。

作成されたアプリはHerokuのダッシュボードですぐに確認することができます。

Heroku上で稼働するアプリはHerokuのDynoベースのアーキテクチャーの恩恵を受け、インジケーターひとつで簡単にスケールアウト・インすることができます。デフォルトの1Dynoだとホスティング料は無料です。

あとはHeroku上のアプリにgitでアクセスし、コードをコミットすることでアプリを自在に更新することができます。

without comments

Written by 中嶋 一樹

10月 10th, 2012 at 4:02 pm