jscafe vol7に参加してきた

JavaScript基礎勉強会ことjscafe vol7に参加してきた。
jscafe、久しぶりに行ったらBacbone.js/jQueryの勉強会に変わってた。

Backbone.js

@lxyumaさんのスライドParseというBaaSのテンプレートを元にBackboneのサンプルアプリを作っていく感じだった。Parse知らなかったんだけど、JavaScriptやiOSのテンプレートがあって即席でバックエンドのAPIが用意できるの凄かった。モックとかならこれで十分そう。
Backbone、恥ずかしながらあまり触った事無いんだけど、クライアントサイドMVCにデータバインディングも任せたいなーという感想だった。Angular.jsとか当たった方が良いのか?

jQuery

同じく@lxyumaさんのスライド
導入だったしjQueryの基本的な部分をおさらいした。と思いきや下記の様な書き方ができるの知らなかったり。

var x = $("<div id='test'>this is test</div>")

var x = $("<div>",
                { id : "test",
                  text : "this is test"})

LT

毎回LT枠があるのでNode入門的なノリで最近書いたモジュールとかの話をしてみた。こっそりeXcaleを差し込んでみたけど反応的にはどうだったんだろ。


二人目はDeNA@yosuke_furukawaさんで、Bower/Yeomanの話だった。スライドにsocket.io仕込んでて意識の高さがヤバかった。要約すると

  • Bowerのイケてない所はgrunt-bower-taskで補え
  • Yeomanでオリジナルのアプリケーションテンプレート作ると管理がめっちゃ便利

という感じ。Yeomanは自分の中でいまいち使い所が分かってなかったので為になった。

jscafe、特にcafeの要素は無いので、「***.js」みたいな名前にした方が人集まりやすいのかな?とか思った。

NodeでCoverallsしてみる

テストカバレッジをバッジで表示してくれるCoverallsをNodeで実行してみる。
Coverallsは最近話題になってる気がするけどNodeの日本語記事は少なくてハマったので手順をメモ。

サインアップ〜リポジトリの登録はTravis-ciと似てるので迷わないと思う。
デフォルトはRubyの手順が表示されるが、今回はNodeでやりたいのでDocsを見るとnode-coveralls見ろと書いてあるのでその通りにする。ちなみにnode-coverallsはTravis-ci経由での実行にしか対応していないので注意。
実践してみたリポジトリはこちら。

jscoverage

必要なのでHomebrewを使ってインストール。

   $ brew install jscoverage

package.json

devDependenciesにcoveralls、jscoverageを追加する。自分の場合はmochaを使っているのでlcov形式でレポートを出力してくれるmocha-lcov-reporterも追加する。 travis-ciはビルド時にnpm testを実行するので、テストコマンドは下記の様にしておく。make test-coverallsの中身はMakefileを参照する。

  "scripts" : {
    "test" : "make test-coveralls"
  },
 "devDependencies": {
    "mocha": "*",
    "expect.js": "*",
    "jscoverage" : "0.3.6",
    "mocha-lcov-reporter" : "0.0.1",
    "coveralls": "*"
  }

Makefile

Makefileを参考にして必要な部分を自分で書き換える。
jscoverageの機能やコマンドに関してはここを見れば分かる。make test-coverallsではmocha-lcov-reporterで吐かれたIcovをAPI経由でcoverallsに送信している。

REPORTER = spec
test:
  @NODE_ENV=test ./node_modules/.bin/mocha -b --reporter $(REPORTER)
 
lib-cov:
    jscoverage lib lib-cov
 
test-cov: lib-cov
    @TEST_COVERAGE=1 $(MAKE) test REPORTER=html-cov > coverage.html
    rm -rf lib-cov
 
test-coveralls:   lib-cov
    echo TRAVIS_JOB_ID $(TRAVIS_JOB_ID)
    @TEST_COVERAGE=1 $(MAKE) test REPORTER=mocha-lcov-reporter | ./node_modules/coveralls/bin/coveralls.js
    rm -rf lib-cov
 
.PHONY: test

テストコード

テスト対象モジュールのパスをMakefileで設定した環境変数(上記であればTEST_COVERAGE)の有無で切り替えるようにする。

var dir = process.env.TEST_COVERAGE ? '../lib-cov/' : '../lib/',
  Zaim = require(dir + 'zaim'),
  expect = require('expect.js');

この状態でローカルでmake test-covするとcoverage.htmlにカバレッジレポートが出力される。
レポートが正しく出力されるのを確認後、GitHubにpushすればtravis-ciのビルド時にtest-coverallsが実行されてバッジがREADMEみたいに出力される。

バッジかっこいいけどこれだけの為にこの手順踏むのは辛い。

水まんじゅう新着botをeXcaleで動かしてみた #yutori_history

ゆとり Advent Calendarの15日目のエントリです。

昨日は@razonさんでした?

ゆとりさん転職おめでとうございます。
ゆとりさんとは二度ほど飲みに行った仲です。初めてお会いした時に「御社は腐ってますね〜」と言われた事を今でも覚えています。
ゆとりさんとは2回しか会ったありませんが、ブログはよく読んでます。そこで大人気ブログ水まんじゅうの新着情報を呟くbotを作ってみました。


空気的にJavaかと思いきや全く触れずにNode.jsで実装しました。
ちなみにこのboteXcaleというPaaS上で稼働しています。特にステマとかではないです。
コードはこちらです。若干作り方を解説してみます。

https://github.com/hotchemi/yutori-blog-bot

rssParser.js

水まんじゅうのRSSにアクセスし、レスポンスをパースします。xmlからjsonへの変換はxml2jsonモジュールが便利でした。
前回記事のタイトルをキャッシュしておき、最新版と比較して違っていればコールバックを実行するロジックにしてあります。もちろん厳密な判定ではないですがネタ記事なのでそこら辺はご愛嬌です。

var request = require('request'),
  parser = require('xml2json'),
  config = require('../config/config'),
  http = require('http'),
  url = require('url'),
  latestTitle;

module.exports.checkNewArticle = function(callback) {
  http.get(config.url, function(res) {
    var body = "";
    res.setEncoding('utf8');
    res.on('data', function(data) {
      body += data;
    });
    res.on('end', function() {
      var json = JSON.parse(parser.toJson(body)),
        newTitle = json.rss.channel.item[0].title;

      if (newTitle !== latestTitle) {
        callback(newTitle, json.rss.channel.item[0].link);
        latestTitle = newTitle;
      }
    });
    res.on('error', function(err) {
      console.log("Error: " + err.message);
    });
  });
};
index.js

eXcaleにはcronがないのでnode-cronモジュールを使ってcronを実装します。botは1時間に1回RSSをチェックしに行く様設定してあります。

var cronJob = require('cron').CronJob,
  twitter = require('twitter'),
  config = require('./config/config'),
  rssParser = require('./lib/rssParser'),

  bot = new twitter({
    consumer_key : config.consumer_key,
    consumer_secret : config.consumer_secret,
    access_token_key : config.access_token_key,
    access_token_secret : config.access_token_secret
  }),

  job = new cronJob({
    cronTime: config.cron,
    onTick: function() {
      console.log("twitter bot process started...");
      rssParser.checkNewArticle(function(title, link){
        var word = title + " " + link + " #yutori_history";
        bot.updateStatus(word, function(data) {
          console.log(data);
        });
      });
    },
    onComplete: function() {
      console.log('bot process stopped!');
    },
    start: false,
    timeZone: "Japan/Tokyo"
  });

job.start();
そして寿司へ…

ゆとりさん転職おめでとうございます。ブログを書くと回らない寿司に連れて行ってくれると聞いています。よろしくお願いします。
16日目の明日は@zer0_uさんです。


あれ?