40歳からのキャリアチェンジ

20代はエンジニア・PM、30代はWeb系エンジニア向けのキャリアアドバイザー。40代の今はフリーランスで開発含めて色々やってます。技術ネタとしてはRuby/RailsとJavaScript関連あたり

ACS上にあるデータをnode.js使って抽出するスクリプト

Titanium+ACSの組み合わせで、社内向けに位置情報活用したアプリを何故か作ってます^^;

f:id:h5y1m141:20131228091744j:plain

データの集計処理のような機能はACS標準には無く、例えば

「会社別に毎週何回チェックインされたか」

というような集計処理は自作する必要があります。

幸いと言っていいのかわかりませんが、ACSには、REST APIがあるので、それをうまく使うことで簡単に処理が出来そうです。

事前準備

HTTP Client的なモジュールを使って、REST APIを叩く・・・のはちょっと面倒な感じがしたのでちょっと調べた所、開発元のAppceleratorがacs-nodeというNode.jsからACSを利用しやすくするモジュールを開発されていました。

これを使うことで、TitaniumでACSを利用する時と同じようなコードで、Node.jsからもACSにアクセス出来るようになります。

acs-nodeは、npm 経由でインストール可能です。

グローバルな領域にインストールするのがちょっと嫌なので、現在開発中のプロジェクトのルートディレクトリ上で

npm init

を実行して、package.jsonを作成して、このプロジェクト内で必要なモジュールを適宜導入するようにしてます。詳しくはnpmでnode.jsのpackageを管理するあたりが参考になるかと重います。

package.jsonを作成した後にacs-nodeをインストールします。あと、データの抽出処理をする際に、今週の月曜日から金曜日までみたいな感じの日付処理をやるケースが多く、日付処理は面倒なので、moment.jsも利用したいのでついでにそれもインストールします

npm install acs-node --save-dev
npm install moment --save-dev

Noe.jsからacs-node使う

使い方はとても簡単で、

  1. acs-nodeを読み込む
  2. ACS利用時のDevelopmentKey、もしくはProductionKeyを指定して初期化する

これだけです。

ACS利用時のDevelopmentKey、もしくはProductionKey、ユーザID,パスワードをソースコード内に埋め込みたくなかったので、それら設定情報は、apiKey.jsonにすべてまとめてるので少しコードが長いですが、CoffeeScriptのサンプルコードはこんな感じになります

ACS = require('acs-node')
fs = require('fs')
path = require("path")
file = fs.readFileSync(path.resolve(__dirname, "apiKey.json"))
json = JSON.parse(file.toString())
apiKey = json.apiKey.development
loginID = json.login
loginPasswd = json.password
ACS.init(apiKey);

apiKey.jsonはこんな感じです

{
"apiKey":{
"development":"KEY",
"production":"KEY"
},
"login":"username",
"password":"password"
}

ACSにアクセスしてデータ抽出する

TitaniumでACSを利用したことがある人だと、acs-nodeにある以下のJavaScriptのサンプルコードは、違和感ないかと思います

var ACS = require('acs-node');
ACS.initACS('<App Key>');
function login(req, res) {
    var data = {
        login: req.body.username,
        password: req.body.password
    };
    ACS.Users.login(data, function(data){
        if(data.success) {
            console.log("Successful to login.");
            console.log("UserInfo: " + JSON.stringify(data.users[0], null, 2))
        } else {
            console.log("Error to login: " + data.message);
        }
    }, req, res);
}

これを応用して、「今週月曜日から金曜日までのチェックイン情報を抽出する」みたいなコードを考えてみました。

今週月曜日とか、今週金曜日とかは、素のJavaScriptでどうにかするのがつらいですが、前述のmoment.jsを使うことで

thisMonday = moment().day(1).hours(0).minutes(0).seconds(0).milliseconds(0)
thisFriday = moment().day(5).hours(23).minutes(59).seconds(59).milliseconds(0)

という形で書けます。この状態ですと、出力される形式が日本時間にならないので、format()にて、出力形式を指定することでより見やすくなります。

具体的には

thisMonday = moment().day(1).hours(0).minutes(0).seconds(0).milliseconds(0).format("YYYY-MM-DDTHH:mm:ssZ")
thisFriday = moment().day(5).hours(23).minutes(59).seconds(59).milliseconds(0).format("YYYY-MM-DDTHH:mm:ssZ")

という感じです。詳しいことは、JavaScriptで日付を扱うならこれ!「moment.js」がとても参考になると思います。

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

moment = require("moment")
ACS = require('acs-node')
fs = require('fs')
_ = require("underscore")
path = require("path")
file = fs.readFileSync(path.resolve(__dirname, "apiKey.json"))
json = JSON.parse(file.toString())
apiKey = json.apiKey.development
loginID = json.login
loginPasswd = json.password

ACS.init(apiKey);

thisMonday = moment().day(1).hours(0).minutes(0).seconds(0).milliseconds(0).format("YYYY-MM-DDTHH:mm:ssZ")
thisFriday = moment().day(5).hours(23).minutes(59).seconds(59).milliseconds(0).format("YYYY-MM-DDTHH:mm:ssZ")

data =
  login: loginID
  password: loginPasswd

ACS.Users.login data, (response) ->
  
  console.log response
  result = []
  if response.success
    ACS.Checkins.query
      page: 1
      per_page: 50
      where:
        updated_at:
          "$gt":thisMonday
          "$lt":thisFriday
    , (e) ->
      if e.success
        for checkin in e.checkins
          console.log("id:#{checkin.id} name: #{checkin.place.name} date: #{moment(checkin.updated_at).format('YYYY-MM-DD HH:mm:ss')}")

      else
        console.log "Error:\n" + ((e.error and e.message) or JSON.stringify(e))

  else
    console.log "Error to login: " + response.message