2012年6月13日水曜日

ブログを書くネタがない

うーん。ない。

2012年6月4日月曜日

herokuで(mbstring有効な)phpがすぐ動いた

herokuでphpが動くのは前々から知っていたのですが、mbstringが有効なphpがいとも簡単に動くという情報を見つけたので試してみました。

$ mkdir heroku-php
$ git init
$ vim index.php
<?php
phpinfo();

$ git add .
$ git commit -m "initial commit"
$ heroku create --buildpack https://github.com/winglian/heroku-buildpack-php -s cedar
$ git push heroku master

こんだけ!?全然難しくないですね。
heroku openしてみたらちゃんとphpinfoが表示されました。

でも気になったのがindex.phpの設置場所。
基本phpはindexに相当するものを設置しなければいけないと思うのですが、これってpublicディレクトリにしても動くのだろうか…?

$ mkdir public
$ git mv index.php public/
$ git commit -am "moved index.php"
$ git push heroku master

-----> Heroku receiving push
-----> Fetching custom buildpack... done
 !     Heroku push rejected, no Cedar-supported app detected

ガーン!…そもそもアプリのルートにindex.phpが無いと受け付けてくれないのか。
ということは環境変数DOCUMENT_ROOTとか使えないのかな?

$ heroku config:add DOCUMENT_ROOT=/app/www/public
Adding config vars and restarting app... done, v5
  DOCUMENT_ROOT => /app/www/public

まぁ無理でした。環境変数はセットできても何の意味も無いですね。ググっても情報みつからないので多分このオプションは存在しないのでしょう。
アプリそのものが公開ディレクトリなのはそれはそれでphpらしいですよね。

しかしphp速い感じする。ただのphpinfoというのもあるだろうけど、アプリの更新しても再起動が無いからか。

参考:HerokuのBuildpackを利用してmbstringが有効なPHPサーバを立ててみた - hnwの日記

2012年6月1日金曜日

CoffeeScriptでJavaScriptもクラス化しよう。テストを書きやすくメンテしやすく

CoffeeScriptを知ったのはRailsに組み込まれたからですが、Rails3.1で採用されてすぐに飛びついたわけではなく、しばらく敬遠してた時期もありました。しかし使い始めてからはもう手放せなくなりました。
そして次第にCoffeeScriptのclass構文を使えばよりよいJavaScriptの開発ができるのではないかと思うようになりました。
今回は最近CoffeeScriptを使ってどのように開発しているかを紹介したいと思います。

CoffeeScriptでのclass定義はこうやります

class Person
  constructor: (@my_name) ->

  greeting: ->
    alert "Hello! my name is #{@my_name}."

window.Person = window.Person || Person

コンパイルすると以下のようなJavaScriptになります

(function() {
  var Person;

  Person = (function() {

    Person.name = 'Person';

    function Person(my_name) {
      this.myname = my_name;
    }

    Person.prototype.greeting = function() {
      return alert("Hello! my name is " + this.my_name);
    };

    return Person;

  })();

  window.Person = window.Person || Person;
}).call(this);

※nameプロパティを使うと上書きしてしまうのでmynameとしました

例えばこのようなコードを person というファイル名で保存し、インスタンス生成は main という別ファイルで実行します。

main.coffee
$ ->
  kozo = new window.Person 'kozo'
  kozo.greeting()
main.js
(function() {
  $(function() {
    var kozo;
    kozo = new window.Person('kozo');
    return kozo.greeting();
  });
}).call(this);

こうすることでまず管理がしやすくなりますし、テストも気持ちよく書けると思います。

テストフレームワークはよく jasmine をつかっています。その前は QUnit だったんですが jasmine の方がドキュメントが探しやすいのとツールが整っている印象ですし、なによりコードが書きやすく後からでも見やすいですね。人によるかも知れませんが。
僕の場合CoffeeScript を使うときはほぼ Rails か sinatra 上ですので jasmine-headless-webkit というgemをつかってます。これを使うとCUIで実行結果が得られます。(jasmine-railsはこれに依存しています)

jasmineの諸々の設定は省略しますがテストコードはこんな感じにしています。

person_spec.coffee
describe "Person", ->

  beforeEach ->
    @person = new window.Person 'sample'

  afterEach ->
    delete @person

  describe "propaties", ->
    it "have 'my_name' string", ->
      expect(typeof @person.my_name).toBe "string"

  describe "greeting method", ->
    beforeEach ->
      spyOn window, "alert"
      @person.greeting()

    it "alert greeting text", ->
      expect(window.alert).toHaveBeenCalledWith "Hello! my name is sample."

DOMが絡むテストは jasmine-fixture というのをhelperとして読み込んで使っています。jqueryに依存しているのですが、むしろ使わない事のほうが少ないので気にしないです。affix という便利メソッドが使えるようになって、jqueryオブジェクトのprototypeにも追加されるので気に入ってます。

以上のような形で開発を進めてるのですが、クラスファイルと実行ファイルを分けてなるべくDOMの情報とかは実行ファイルに書き込むようにするといいと思います。
サイトのトップページにスライドショー的なものを設置するなら例えば以下の様な感じです。

main.coffee
$ ->
  slideshow = new window.Slideshow {
    container_id: '#hoge-slideshow'
    controller_id: '#hoge-controller'
    duration: 800
    wait: 3000
  }
  slideshow.start()

要はリテラル値をまとめて書いておくということです。

ただこのように実行ファイルに分けていてもファイル名が script とかにする人がいたりして…それはそれでわからなくはないのですが、mainの方が無難じゃないですかねぇ。

あぁマシン持ち寄ってこうゆう話ししながら酒を呑む仲間がほしいなぁ…

2012年5月30日水曜日

jQueryのプラグイン limp と airy を書いた

ひょんなことからjQueryの視覚系プラグインを2つ書きました。

jquery.limp.js

ソースというかデモサイトまるごとgithubにあります。
jquery.limp.js

要素をfixed配置に変えて縦スクロールに対して少し遅れてついてくるというものです。
いわゆるパララックス効果的に使えるんじゃないかと思います。

DEMO

limpという名前はlimpbizkitからとりました。僕の青春です。

jquery.airy.js

こちらもデモサイトまるごとgithubにあります。
jquery.airy.js

要素をabsoluteで配置しておくとフワフワとその場を浮遊するというものです。
こちらは使い道が難しいですね。

DEMO

両者ともcoffeescriptで書いてsinatraでサーブしてるのですが、素のjavascript書くのしんどいですね最近……

2012年5月25日金曜日

OS X LionにbrewでAPCをインストールした

まずはFormulaを検索

$ brew search apc
josegonzalez/php/php53-apc  josegonzalez/php/php54-apc

2つありました。 phpはv5.3.10なのでphp53-apcをインストールします。

リポジトリを追加

$ brew tap josegonzalez/php
Cloning into '/usr/local/Library/Taps/josegonzalez-php'...
remote: Counting objects: 1011, done.
remote: Compressing objects: 100% (491/491), done.
remote: Total 1011 (delta 480), reused 929 (delta 416)
Receiving objects: 100% (1011/1011), 140.43 KiB | 109 KiB/s, done.
Resolving deltas: 100% (480/480), done.
Tapped 48 formula

インストール実行

$ brew install php53-apc
......
To finish installing php53-apc:
  * Add the following lines to /usr/local/etc/php.ini:
    [apc]
    extension="/usr/local/Cellar/php53-apc/3.1.10/apc.so"
    apc.enabled=1
    apc.shm_segments=1
    apc.shm_size=64M
    apc.ttl=7200
    apc.user_ttl=7200
    apc.num_files_hint=1024
    apc.mmap_file_mask=/tmp/apc.XXXXXX
    apc.enable_cli=1
  * Restart your webserver.
  * Write a PHP page that calls "phpinfo();"
  * Load it in a browser and look for the info on the apc module.
  * If you see it, you have been successful!
  * You can copy "/usr/local/Cellar/php53-apc/3.1.10/apc.php" to any site to see APC's usage.
......

指示通りphp.iniに設定を追加して、php-fpmを再起動 (これがいまいちまだよくわかってない…)

$ ps ax | grep php
  493   ??  Ss     0:00.17 /usr/local/Cellar/php/5.3.10/sbin/php-fpm
  494   ??  S      0:01.15 /usr/local/Cellar/php/5.3.10/sbin/php-fpm
  495   ??  S      0:01.37 /usr/local/Cellar/php/5.3.10/sbin/php-fpm
$ kill -TERM 493
$ php-fpm

↑とりあえずkillしてから実行してみてる phpinfo()で確認OK!

2012年5月18日金曜日

WebGLに感動したのでThree.jsを触ってみた

このギャラリーの作品はどれもレベル高くてすごい

Chrome Experiments - WebGL Experiments

見てたらWebGLをかじってみたくなったのでThree.jsというのを試してみた。

mrdoob/three.js

リポジトリを落としてきてsinatraに乗っけてherokuにアップしときました。
Three.js Learning
トップページはexamplesの一覧です。

とりあえず本家のGet Starttingで試してみたけど、動かないとつまらないのでマウスの動きに反応するようにした。

うーん道のり長そうだなぁ

iPhoneだと動かないのかな?

2012年5月2日水曜日

railsのform_forに渡すモデルオブジェクトでurl生成する場合の話

railsのform_forヘルパーは以下のように使いますよね

= form_for(@post) do |f|
  = f.label :title
  = f.text_field :title

こう書いておけば出力されるhtmlは

大体こんな感じになるかと。
でrailsの便利なところはform_forに渡してるモデルオブジェクトが、空なのかDBのレコードから生成されたのかを判別して、actionの属性値をよしなに変更してくれるところですよね。

つまりroutesに

resouces :posts do
end

と書いてあれば 新規作成時は action="/posts" だし編集画面では action="/posts/1" になると。 でもこれが namespace 付きのroutesだとうまく行かなくて困りました。
管理画面を作る場合とかだと /admin/posts にしたくて

namespace :admin do
  resources :posts do
  end
end

と定義しておいて、form_for で生成したフォームを上記のままにしておくと、undefined method `posts_path' と怒られてしまう。 一瞬下記のやり方?とか思ったんですがrailsに限ってそんなことないよね…

= form_for params[:action] == 'new' ? admin_posts_path : edit_admin_post_path(@post) do |f|
  = f.label :title
  = f.text_field :title

ぐぐったら出てきた。

Rails Routes Namespaces and form_for - Stack Overflow
= form_for [:admin, @post] do |f|...

だってさ!
配列で指定するんですか。なるほどこれで admin_posts_path と edit_admin_post_path を切り替えてくれるんですね。

ということは…やってみた。

namespace :hoge do
  namespace :fuga do
    namespace :foo do
      namespace :bar do
        resources :hellos do
        end
      end
    end
  end
end
= form_for [:hoge, :fuga, :foo, :bar, @hello], do |f|
  = f.label :name
  = f.text_field :name

成功\(^o^)/