ナウなヤングのnow.js

now.js楽ちんですね。

twitter-streamとnow.jsを使ってリアルタイムにtweetを拾ってブラウザに表示したくなったのでやってみた。コード書いてる時に丁度スケットダンスが放映されていたたみたいで、twitterのトレンドに表示されてたのでこれを拾ってみた。

ちなみにジャンプは毎週読んでるけどスケットダンスはほとんど見ないのでついていけてませんな。

twst

スケルトン作成

とりあえずいつものようにコマンドを打って、スケルトンを作成

express twnow
cd twnow

package.jsonを修正して

{
    "name": "application-name"
  , "version": "0.0.1"
  , "private": true
  , "dependencies": {
      "express": "2.5.8"
    , "jade": ">= 0.25.0"
    , "ntwitter": ">= 0.3.0"
    , "now": ">= 0.8.1"
  }
}

依存モジュールをインストールする

npm install -d

コード

あとはコードを描く

app.coffee

twitter = require("ntwitter")
express = require("express")
routes = require("./routes")
nowjs = require("now")

twit = new twitter(
  consumer_key: "####"
  consumer_secret: "####"
  access_token_key: "####"
  access_token_secret: "###"
)

app = module.exports = express.createServer()
app.configure ->
  app.set "views", __dirname + "/views"
  app.set "view engine", "jade"
  app.use express.bodyParser()
  app.use express.methodOverride()
  app.use express.cookieParser()
  app.use express.session(secret: "tweetandsweet")
  app.use app.router
  app.use express.static(__dirname + "/public")

app.configure "development", ->
  app.use express.errorHandler(
    dumpExceptions: true
    showStack: true
  )

app.configure "production", ->
  app.use express.errorHandler()

everyone = nowjs.initialize(app)

app.get "/", (req, res) ->
  console.log req.session.user_profile
  res.render "index",
    title: "twitter streaming and now.js"

twit.stream(
  'statuses/filter'
  {track:['#sketdance']}
  (stream) ->
    stream.on 'data', (data) ->
      everyone.now.receiveMessage data
      console.log data
)

app.listen 3000
console.log(
  "Express server listening on port %d in %s mode"
  app.address().port
  app.settings.env
)

style.css

body {
  padding: 50px;
  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}

a {
  color: #00B7FF;
}

li.tweet {
  list-style-type:none;
  width: 500px;
}

img.tweet {
  float: left;
  padding-right: 20px;
}

hr {
  width: 500px;
  clear: left;
  border: 0;
  height: 1px;
  background-image: -webkit-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0));
  background-image:    -moz-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0));
  background-image:     -ms-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0));
  background-image:      -o-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0));
}

layout.jade

!!!
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
    script(type="text/javascript", src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js")
    script(src="/nowjs/now.js")
  body!= body

index.jade

h1= title
p sample apps
ul#messages
script
  $(document).ready(function() {
    now.receiveMessage = function(data) {
      $("#messages").prepend(
   '<li class="tweet"><img class="tweet" src=\"' + data.user.profile_image_url +'\">'+ data.text + '<hr></li>');
    }
  });

now.jsは抽象度が上がりすぎてて、裏で何が行われているかよく理解できないんだが、使うぶんには簡単ですね。IE7対策をしなくてもとりあえず動くので、それもお気に入りポイント(企業のブラウザはIEでしかも古いからねー)

ProductName 徹底解説 HTML5 APIガイドブック コミュニケーション系API編
小松 健作
秀和システム / 2730円 ( 2010-12 )


CoffeeScriptのnew @(objects)

spineのソースコードでわからないとこがあって、なんで@をnewしてんの?っていう。

class Test
  constructor: (@name)->

  @test:(name) ->
    new @ name

test1 = new Test 'xxx'
test2 = Test.test('yyy')

console.log test1
console.log test2

new @ nameはTestクラスのコンストラクタ関数を指しているという理解をした。

CoffeeLintでflymakeするように設定した

最近順調にバージョンが上がっているCoffeeLintを使ってみた。CoffeeLintのサイトから辿れるcoffeelintnodeはサバクラの構成っぽくてちょっと使いづらそうだったので、flymakeの設定を書いてみた。

flymake-cursorにも対応させてあるので下のスクリーンショットのミニバッファーにエラー内容が表示されてる。

flymake_coffee

自分でelispを書く場合、この本はとても良かった。この本を片手に他の人の書いたelispを読むのも楽しい。

ProductName Emacs Lispテクニックバイブル
るびきち
技術評論社 / 3129円 ( 2011-11-26 )


それからcoffeelintのパスがnvmのちょっとアレなパスで直書きしたくなかったのと、coffeelintが結構死ぬので、flymakeが巻き添えを食わないようにする設定のやり方を参考にさせてもらった。

昨日書いたpythonのflymake部分を切り離してinit-flymake.elに統合したので、coffeescriptだけ設定したい場合は下のelispからpythonの設定を削除すれば動くと思います。

(defadvice flymake-post-syntax-check (before flymake-force-check-was-interrupted)
  (setq flymake-check-was-interrupted t))
(ad-activate 'flymake-post-syntax-check)

(add-hook 'find-file-hook 'flymake-find-file-hook)

(when (load "flymake" t)
;; flymake+pyflakes+pep8
; http://d.hatena.ne.jp/cou929_la/20110525/1306321857
  (defun flymake-pyflakes-init ()
    (let* ((temp-file (flymake-init-create-temp-buffer-copy
                       'flymake-create-temp-inplace))
           (local-file (file-relative-name
                        temp-file
                        (file-name-directory buffer-file-name))))
      (list "pycheckers" (list local-file))))
  (add-to-list 'flymake-allowed-file-name-masks
               '("\\.py\\'" flymake-pyflakes-init))
;; flymake+coffeelint
; http://blog.kzfmix.com/entry/1334315825 
  (defun flymake-coffeelint-init ()
    (let* ((temp-file (flymake-init-create-temp-buffer-copy
                       'flymake-create-temp-inplace))
           (local-file (file-relative-name
                        temp-file
                        (file-name-directory buffer-file-name))))
      (list "coffeelint" (list "--csv" local-file))))
  (add-to-list 'flymake-err-line-patterns
                 '(".+,\\(.+\\),\\(.+\\),\\(.+\\)"
                   nil 1 nil 3)) 
  (add-to-list 'flymake-allowed-file-name-masks
               '("\\.coffee\\'" flymake-coffeelint-init)))

(load-library "flymake-cursor")

magitの使い方も覚えたので、Flask+Spineのコーディングが快適にできそう。

Backbone.jsとSpineの違い

ここのところbackbone.jsを触っていたので、Spineとの違いもなんとなくわかってきた。

todoをcoffeescriptに変換(backbone-todo)したものとspine-todoの違いを比較した。

モデル

backboneのモデルはmodelとcollection(modelの集合)にわかれているが、Spineではこの区別はない。両方いじってみたのでsofの比較がよく理解できた。

class Task extends Spine.Model
  @configure "Task", "name", "done"

  @extend Spine.Model.Local

  @active: ->
    @select (item) -> !item.done

  @done: ->
    @select (item) -> !!item.done

  @destroyDone: ->
    rec.destroy() for rec in @done()

Element patternでいいんじゃないかねという立場かな。

ViewとController

Backbone.jsのviewがSpineのcontrollerになる感じ。SpineのviewはBackboneのテンプレートになる。

Spineはドキュメントが少ないので、もっと充実して欲しいなぁと。

ProductName JavaScript Web Applications
Alex Maccaw
Oreilly & Associates Inc / 3020円 ( 2011-08-30 )


Backbone.jsみたいな注釈付きのソースコードをつくるやつ(docco)

Backbone.jsのannotated source読みやすいわと。

いつものようにsofを探した。

doccoを使えばいいらしい。ちなみにpythonだとPyccoがあるのでどちらかを使えばいいかな(両方入れたが)。

今、spinehemのソースコードを読んでいるので、明日のつくる会ではdoccoを使った黙々注釈付けをやろうかな、というかやる。

というわけで、明日は静岡デベロッパーズつくる会#5です。一人だと作業に集中できないわーとか、つけナポリタン気になるわーというヒトは気軽にフラッと寄ればいいと思います。

ちなみにお菓子の持ち込み可です。菓子をつまみながらコーディングしましょう。

Ace - Sinatra for Node

Spineの作者製なのでCoffeeScriptで書けていい感じっぽいんだけど、Expressと比べてどうなんだろうか。 少し触ってみないとそこらへんがよくわからん。

この本は面白かった。

ProductName JavaScript Web Applications
Alex Maccaw
Oreilly & Associates Inc / 3020円 ( 2011-08-30 )


ちなみに今はExpress+nowjsっていう組み合わせでイントラサイトを作っているけど、調子いいのでなかなか気に入っている。

再来月に二回目の三島バルがあるらしいので、それまでにつくる会が開ければExpressかAceでこんなの作ってみようかなぁと思っている(自分のために)。多分俺のバルっていうタイトルのサイトで、酒を飲んでふらふらしながら自分探しの旅をするっていう設定のリアルタイムウェブなサイトにしようかなぁと。

Node.jsのalwaysモジュールを見てcoffeeにはwatchオプションがあるよなと思った。

node.jsの開発時に。ファイル変更でサーバプロセスを自動再起動「Always」を読んで、Expressの開発に使えるかも!?と思ったが、よくよく考えたら自分はいつもcoffeescriptで書いてるんだった。

あとcoffeeコマンドには--watchってオプションがあるからモジュールに頼らなくてもいいのだよなぁ。

CoffeeScriptのsplatsの挙動がわからないと思ったがやっぱわかった。

コッココッココココココッヒーな脳になってます。

splatsとはこれです。

最大値を返す関数を例にとります。

まずはNode.jsで

> Math.max(1,9,7,4,2,6)
9
> Math.max([1,9,7,4,2,6])
NaN
> Math.max.call(null,1,9,7,4,2,6)
9
> Math.max.apply(null,[1,9,7,4,2,6])
9

これはOKですね。同様にcoffeeでも

coffee> Math.max 1,9,7,4,2,6
9
coffee> Math.max.call @, 1,9,7,4,2,6
9
coffee> Math.max.call null, 1,9,7,4,2,6
9
coffee> Math.max.apply @, [1,9,7,4,2,6]
9
coffee> Math.max.apply null, [1,9,7,4,2,6]
9
coffee> Math.max.apply [1,9,7,4,2,6]
-Infinity
coffee> Math.max.apply()
-Infinity

最後の2つは第一引数にthisもnullも入れてないからですね。

さてsplatsを使います。

coffee> ary = [1,9,7,4,2,6]
coffee> Math.max ary...
9

なんでMath.max @, ary...じゃないのよ?と思ったがエントリ書いてたら理解してしまった。

coffee> Math.max.call @, ary...
9

こういうことね。

ProductName みいつけた!ぬいぐるみM コッシー

セガトイズ / 2623円 ( 2010-04-30 )


恋するプログラムをCoffeeScriptで書いてみた

8章のマルコフモデルの実装までやった。ちなみに二単語のプレフィックスによるモデルを作ってた。ちなみにNodeで作る人工無脳は一単語ですね。こっちはリアルタイム化させているので面白いです。

9章はググらせるだけなのでこれでおしまいでいいやと。

ProductName 恋するプログラム―Rubyでつくる人工無脳
秋山 智俊
毎日コミュニケーションズ / ?円 ( 2005-04 )


いい本だと思うんだけどなかなか復刊しないですね。

coffeescriptでディープコピーをやる方法を探していたらCoffeeScript Cookbookを見つけたので、Smooth CoffeeScriptとあわせて読んでみる予定。

化合物の合成ストーリーはケミスト言語による文章構築

ところで、人口無能はつくってて楽しいですね。とか書いていて、ふとケミストの合成の流れもマルコフ性があるんじゃないかなぁと思った。思ったというより確信に近い。プレフィックスに構造とイシュー(活性改善とか代謝よくするとか)を入れてやれば、次に修飾したがるところって容易に想像できるよね。実際ベースラインとしてのファーマコフォアをたもちながらっていうよりは、直近の結果にものすごい左右されやすいという性格があってだなぁ(略)。

例えば、ある文章中の単語をランダムに並べ換えて、それをもとの文章に戻すっていう問題を考えた場合マルコフ性をうまく利用すればどの位うまく解けるんだろうかね?

そういう風に考えると、特許化合物のリストっていうのはランダムな単語リストと同じになるわけで、合成のマルコフ性を利用して合成の流れを再構築しなおすってのは面白いかもしれんなぁと思った。

そのうちもう少し良く考えてみようっと。

RubyのgsubをCoffeeScriptで

Rubyのgsubはblockを受け取ってマッチするたびにブロック内の処理内容を変えられるので便利。

irb(main):002:0> i = 0
=> 0
irb(main):003:0> 'a-a-a-a'.gsub(/a/){i += 1}
=> "1-2-3-4"

Node.jsでも同じようなことがやりたかったのでRuby's String gsub in Javascriptをちょっと変更して配列を受け取れるようにしてみた。

gsub = (source, pattern, replacements) ->
  unless pattern? and replacements?
    return source

  result = ''
  while source.length > 0
    if (match = source.match(pattern))
      result += source.slice(0, match.index)
      result += replacements.shift()
      source = source.slice(match.index + match[0].length)
    else
      result += source
      source = ''
   result

console.log gsub('a-a-a-a', /a/, [1..4])