2012年12月13日木曜日

ヨドバシで予約したiPad miniの状況をMechanizeでチェックする

12/1にiPad mini買いに行ったら全モデル完売したので入荷するまで予約で待てと言われた。
しょうがないので予約したら商品いつ手に入るかわからないし全額払わされるのにポイントが貯まらないし、入荷したかどうかは自分でWebページを見ろという散々な状況です。

気になるけど酷いUI使ってわざわざ見るのもかったるいのでMechanizeにやってもらうことにしました。
herokuにデプロイしてschedulerで毎時0分に実行しています。

2012年10月31日水曜日

PHPのスコープのお話についてのお話

こちらの記事をたまたま見て気になったので投稿。
PHPでforeachなどを使う時の注意点。ブロックスコープのお話。

確かにループで一時的に必要な変数にスコープが無いと都合が悪いのはその通りなんだけど、解決策にモヤモヤ…

スコープが欲しいところに無いなら作ればいいわけで

関数に入れればスコープが作れる。

もっと言えばクラスにすればいいと思う。

2012年10月23日火曜日

Backboneを学ぶ #0 環境構築

転職して新しい職場ではBackboneを使いそうなのに、今までこれで何も作ったことが無いので勉強することにしました。
ひと通り出来るようになるまで続けたいので連載にしてみます。まずは開発環境の構築など

  • サーバサイド
    • Sinatra (マイクロフレームワーク)
    • haml (テンプレートエンジン)
    • scss (cssメタ言語)
    • CoffeeScript (javascriptメタ言語)
    • Shotgun (開発用rackサーバ)
  • クライアントサイド
    • jquery.1.8.2.js
    • underscore.js
    • backbone.js
  • リポジトリ
  • サーバ
2012年8月24日金曜日

TextMate2の新しいタブを開くショートカットを変更した

TextMate2のNew Tabが 「option + command + N」 で左手が辛いので
以上
2012年8月20日月曜日

Rails3でクエリパラメータでルーティング(Advanced Constraints)

少し前にsendagaya.rbで発表したRails3のAdvanced Constraintsをここでも紹介。

routes.rbの中でURLを定義する時にsubdomainとかを条件に含めるときに使うのがconstraintsというオプションなんですが、これを使ってURLの「?」以降を条件にしたりもできます。

方法はrequestオブジェクトを受け付けるmatches?というメソッドを実装したクラスを定義してインスタンスをconstraintsに渡してあげるだけです。

ここではpostというリソースの集合であるindex、つまり /posts というURLにGETで ?q=hoge 等のパラメータが付いている時に posts_controller#search というアクションに紐付けるということを行なっています。

ただしこのままだと q に対するvalueが空の状態 /posts?q でもsearchアクションに処理が渡るので、コントローラ側で何かしらの対応が必要です。

基本的にはrequestオブジェクトを使って判別できるならどんな条件でもいいので、Accept-languageで振り分けるとかIPアドレスでブラックリストを作るとかもできてしまいます。

今回はindexアクションの中でifで分岐させておくことでも十分対応可能ですが、render以外はほとんど共通処理がないよとかになると、アクションそのものを分けてしまったほうが綺麗なコードになりそうですよね。

2012年8月14日火曜日

オープンソースになったTextMate2をbuildしてみた

すっかりVimに慣れてしまった今日この頃ですが、お世話になったTextMateの2がオープンソースになったのでbuildしてみました。ちなみに環境は OS X lion 10.7.4です。

  1. Githubへ行ってみる

    https://github.com/textmate/textmate.git

    READMEにbuild方法は書かれていますね。

  2. 必要なライブラリをインストール

    とりあえず brew install ragel boost multimarkdown hg ninja とやってみたのですが ninja なんてないよって怒られちゃいました

    というわけで先に brew update してから再度実行したらちゃんと入りました

  3. リポジトリをclone

    git clone https://github.com/textmate/textmate.git でホームディレクトリにcloneしました

    textmate というフォルダができているはずなのでそこに移動 cd textmate

  4. build実行

    の前に、READMEをみると git submodule update --init とやってねと書いてあるので実行

    そして ./configure && ninja 実行!したら clang が古いと言われてしまいました

    brew install --HEAD llvm --with-clang で入るはずなんですが、Error: can't convert nil into String とか言われる

    brew update も brew doctor も問題ないんだよなぁ

    Githubのbug-fixing-checklistを見るとXCodeのupdateして見た方が良さそうだなと思ったので Apple からCommando line tools for XCodeの割と最近のやつをDLした

    でやり直しても駄目だなぁ。とよく見てみたらXCode 4.4+と書いてある、手元のXCodeは4.3でした。App Storeから入れ直そう。

  5. XCodeをupdateしたので

    気を取り直して ./configure && ninja を再度実行してみた。そしたら今度は pgrep が無いよと言われた

    brew install pgrep を実行。(そろそろめんどくさくなってきた)

    ./configure && ninja よし。こんどこそうまく行ってそう。(なにやらwarningとかdepricatedが出てきてますが)

  6. build成功した

    やっと成功した。

    へー2からはPreferencesでbundleとかthemeを追加できるようになってるんですね。逆に言うと最初は何も入ってないからハイライトも何も無いのだけど。

    めでたし

2012年8月8日水曜日

bashでgitの現在のbranch名を表示させる

git-completionというシェルスクリプトを使えばできるということを知ったのでやってみた。

  1. gitのバージョンを調べる

    $ git --version
    $ 1.7.7.5
    
  2. github(http://github.com/gitster/git)に行きcodeのtreeを同じバージョンに切り替える(ブランチの切り替え部分と同じところです)

  3. git-completion.bashまでtreeをたどりraw表示に切り替えて保存
    自分はhttps://raw.github.com/gitster/git/v1.7.7.5/contrib/completion/git-completion.bashでした

  4. DLしたファイルに使い方は大体書いてあるのでその通りにやれば動くと思います

    $ cd ~
    $ mv git-completion.bash .git-completion.sh
    $ vim .bashrc (or .bash_profile)
    $ PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ ' を追記
    $ source .bashrc
    
  5. こんなかんじで表示されました

    [kozo@kozo-mp current_dir (master)]$ 
    
2012年7月26日木曜日

OS X Mountain Lionにアップデートした

早速OS X Mountain Lionにアップデートしたのでいくつか作業を記録します。

  1. App StoreからMountain Lionをダウンロード
  2. インストーラをコピーしておく
  3. インストールで暫し待つ(40分くらい)
  4. App StoreからXCodeをインストール
  5. iTerm2を立ちあげておもむろにgit --versionと打ってみた→消されてる!
  6. ググったらこんなの発見
  7. XCodeを立ち上げてPreferences経由でcommand line toolsをインストール
    • git --versionでインストールを確認
  8. Homebrewのアップデート
  9. imagemagickが再インストール必要みたいなので一旦brew remove imagemagick
  10. brew install imagemagick --use-gccとやるとXQuartzがないよと言われる
  11. 再度 brew install imagemagick --use-gcc を実行
    • gccがみつからないらしく失敗
    • めんどくさくなったので --use-gcc オプションを消してインストール
  12. で、何?感やばい
2012年7月19日木曜日

IE9でiframe内で遷移した場合window.parentのメソッドを呼べない

状況としては、ビデオ一覧ページから各ビデオをiframeを使ったレイヤーで立ち上げるページにて
ビデオはMediaElement.jsというのを使っていて、HTML5対応の判別して、ダメならFlashとかSilverlightとかに切り替えてくれるようになってます。(何も再生手段がなければmp4をDLさせます)

閉じるボタンを押してもビデオが再生されたまま

iframeが非表示になっただけでページ内に生きているから

レイヤーを表示させてるjsを調べる
なんだこれ誰かの自作じゃねえか!closeイベントとか取れねえよ!

親ウィンドウから子iframeにアクセスするか、
子iframeから親ウィンドウに渡すか

後者を選択して window.parent.videos.push(video)
親のレイヤーを非表示にするときの処理に

if (window.videos) {
  for (var i in window.videos) {
    if (!window.videos[i].paused) {
      window.videos[i].pause();
    }
  }
}

というのを挟むようにした。
IE、他ブラウザほぼ動く。

IE9だけ動かない!
iframe内で次の動画へ遷移できるようにしてあったんだけど
ビデオのhtmlは一本につき1ファイルなのでこれは単純にリンクを押してるだけ
親から直接ではなくiframe内で遷移後にエラーする。
(でもIEのステータスバーにはエラー表示が出ないんだけどね)

IE9のF12開発者ツールでブレークポイントつけてみる
「解放されたスクリプトからコードを実行できません」
ハァ(゚д゚)?

ググってみた。あぁそういえばIEではJavaScriptじゃなくてJScriptだったな……
つまり信頼性の低いスクリプトから親ウィンドウにあるオブジェクトのメソッドを実行できないってことですかね!!
というわけでpushじゃなくて代入にした。
window.parent.videos[window.parent.videos.length] = video;

動いた!
プロパティの参照と代入は問題ないみたいです。

2012年7月6日金曜日

CentOS 6 でRails + thin + nginxを動かした

thinってオワコンじゃないですよね?herokuで採用されているし別にいいですよね。
本当はunicorn使いたかったんですが難しい…… ><;
ぐぐると記事沢山出てきますが uninitialized constant errorで起動しない問題が解決できなくてやめちゃいました。いつかリベンジします。

CentOS 6

マシンはvagrant使ってcentos6を用意しました。
参考:http://www.ryuzee.com/contents/blog/4292
vagrantって便利ですね。元々Virtual Boxでwindows動かしてたのですんなりです。ホントに。するっと。

IPアドレスと

config.vm.network :hostonly, "192.168.33.10"

メモリとnameを設定しておきました

config.vm.customize do |vm|
  vm.memory_size = 1024
  vm.name = 'vagrant_centos6'
end

Ruby

rbenv + ruby-buildで1.9.3-p194をインストール

Thin

Gemfileのgroup :productionにgem 'thin'を追加して普通にbundle install

config/thin.ymlは

pid: tmp/pids/thin.pid
log: log/thin.log
servers: 1
port: 3000
daemonize: true
environment: production
user: vagrant
group: staff

以下で起動、停止、再起動

$ be thin start|stop|restart -C config/thin.yml

Nginx

yumでnginxをインストール(参考:http://blog.livedoor.jp/sasata299/archives/51810645.html

/etc/nginx/nginx.confは

worker_processes  1; 

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip  on;

    # include /etc/nginx/conf.d/*.conf;

    upstream backend {
        server localhost:3000;
    }
    upstream backend2 {
        server localhost:3001;
    }
    server {
        listen 80;
        server_name centos6.vag;
        location / {
            proxy_pass http://backend;
        }
    } 
    server {
        listen 80;
        server_name 2.centos6.vag;
        location / {
            proxy_pass http://backend2;
        }
    } 
}

試す

あとはmacのhostsに

192.168.33.10 centos6.vag
192.168.33.10 2.centos6.vag

を設定してブラウザでアクセス!

サクセス!

でもnginx.confの書き方冗長だなぁもっといいのあるんだろうか。

※追記

上記の状態で試しに request.url を覗いてみたら http://backend2/ とかでちゃったよ!困るよ!

というわけでnginx.confを一部修正してみたら問題なく動いた

    ...省略...
    upstream 2.centos6.vag {
        server localhost:3001;
    }
    server {
        listen 80;
        server_name 2.centos6.vag;
        location / {
            proxy_pass http://2.centos6.vag;
        }
    }
    ...省略...

request.url でhttp://2.centos6.vagが返ってきた!

※追記2

画像など静的ファイルが返らないことがわかったので以下のようにconfig修正

    server {
        listen 80;
        server_name 2.centos6.vag;

        proxy_set_header    X-Real-IP       $remote_addr;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header    Host            $http_host;
        proxy_redirect      off;
        proxy_max_temp_file_size    0;

        location ~ .*\.(jpg|JPG|gif|GIF|png|PNG|swf|SWF|css|CSS|js|JS|inc|INC|ico|ICO) {
            root /home/vagrant/sample2/public;
            ssi  on;
            break;
        }

        location / {
            proxy_pass http://2.centos6.vag;
        }
    }

※追記3

thinの再起動などダウンタイムにnginxのデフォルトエラーページが返されるのでconfig追加

     error_page   500 502 503 504  /500.html;↲
        location = /500.html {↲
        root   /home/vagrant/sample2/public;↲
     }

※追記4

マシンを再起動したときにthinも自動起動するようにした!

/etc/init.d/sampleを作成

#!/bin/sh
# chkconfig: 2345 86 25
# description: Sample
#

PATH=/home/vagrant/.rbenv/shims:/home/vagrant/.rbenv/bin:$PATH
eval "$(rbenv init -)"

APP_DIR=/home/vagrant/sample
THIN_CONFIG=$APP_DIR/config/thin.yml

case $1 in
  start)
  cd $APP_DIR
  bundle exec thin start -C $THIN_CONFIG
  ;;
  stop)
  cd $APP_DIR
  bundle exec thin stop -C $THIN_CONFIG
  ;;
  restart)
  cd $APP_DIR
  bundle exec thin restart -C $THIN_CONFIG
  ;;
esac

exit 0

登録する

$ sudo /etc/init.d/sample start
$ sudo chkconfig sample on

2012年6月20日水曜日

jQuery.fn.loadのcallbackで受け取るjQuery.Event.targetはIEでDOM要素をとれない時がある

タイトルで大体言いきりました。

写真のスライドショーを作成していて、画像タグはJavaScript側で作成してDOMに追加するようにしていました。 何故こうしたかというと、環境によって画像の読み込みが終わらないうちにスライドショーの自動再生が始まってしまうのを防ぐためです。

具体的には以下のようなコードで画像の読み込み完了を待ってDOMに追加しています。

$('').attr(src: '/images/hoge.jpg?' + new Date().getTime()).load (e) =>
  $img = $ e.target
  $('#container').append $img

'?' + new Date().getTime() の部分ですが、コレをしておかないとIEがonloadイベントをサボるんですよね。。
必ずイベントを発火させるようにしています。

でIMG要素を $ e.target でjQuery化してappendという流れですが、実はこれだとIEでIMG要素がとれていないんです!
気づかずにそのまま処理を進めると画面真っ白になってお馴染みのわかりづらいエラーメッセージにかなり困惑しました。

IE8で以下の様に検証してみました。

A) e.targetでIMG要素が取得できない

$('').attr(src: '/images/hoge.jpg?' + new Date().getTime()).load (e) =>
  console.log e.target.nodeName # => #document

B) e.targetでIMG要素がとれる

$img = $ 'img.sample'
$img.attr(src: $img.attr('src') + '?' + new Date().getTime()).load (e) =>
  console.log e.target.nodeName # => IMG

違いはJSで要素を作成するか、htmlに記述されている要素を取得するかですね。

まぁぶっちゃけ loadのcallback内でthisが対象のIMG要素なのでコレ使えばいいんですよ。
でもCoffeeScriptつかってclass化したオブジェクトの中だと @(this) は常にクラスそのものとして使いたいので、 関数のthisにバインドしてくれる => を使いたいんですよね。

というわけで jQuery.Event オブジェクトの出番なわけです。
Aの方法だとIEで期待通りでないことがわかったので調べたところ、jQuery.Event.currentTarget というのがありました。
console.log e.currentTarget.nodeName でちゃんとIMGが返ってきたよ〜!

今後調べたいこと

  • $('<img />') と書いた時にブラウザ別に何が行われているのか
  • jQuery.Eventのコンストラクタを読む

追記:

  • jQuery APIの.load()を見たらDeprecatedのタグが付いてたのでbindでも試してみたけど、結果は一緒
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^)/

2012年4月27日金曜日

[ruby]最初に知っておけば良かったbundlerの使い方 sinatra編

rails編は以前書いたのでsinatraでやってみる
用途としてはDBとかいらないスタティックなサイトの構築で、でもhtml、css、jsを生で書くのとか耐えられない。phpはマジ勘弁みたいなときにこうしてますよって感じのことを書きます。

(bundlerの使い方ってゆうかrubyでのweb制作全般って感じですね…)

まず適当な場所にプロジェクトのディレクトリを作ります。
hogeとかもアレなんでポートフォリオにしときます。

$ cd ~/Web
$ mkdir portfolio
$ cd portfolio

でプロジェクトのルートでGemfileをつくる

$ bundle init
Writing new Gemfile to /Users/kozo/Web/portfolio/Gemfile

中身はこんな感じだから...

$ vim Gemfile
# A sample Gemfile
source "https://rubygems.org"

# gem "rails"

以下に書き換えます

source "https://rubygems.org"

gem "sinatra"
gem "sass"
gem "haml"
gem "coffee-script"
gem "shotgun"

自分はnode.jsを入れてるんでアレですが、環境によってはjavascript実行環境が無いと怒られるかもしれないんで、そんときは以下のgemを足してみてください。

gem 'therubyracer'

でgemをインストールします。

bundle install --path vendor/bundle --without production

Fetching gem metadata from https://rubygems.org/.....
Installing coffee-script-source (1.3.1) 
Installing multi_json (1.3.2) 
Installing execjs (1.3.0) 
Installing coffee-script (2.2.0) 
Installing haml (3.1.4) 
Installing rack (1.4.1) 
Installing rack-protection (1.2.0) 
Installing sass (3.1.16) 
Installing tilt (1.3.3) 
Installing sinatra (1.3.2)
....

よしこれでgemが揃いました。
さらに作業環境を整えます。

sinatraを動かすアプリが必要なので app.rb と config.ru
sassやhamlを入れておくviewsディレクトリ、
ドキュメントルートになるpublicディレクトリをつくります。

$ touch app.rb
$ touch config.ru
$ mkdir views
$ mkdir public

アプリケーションのコードはこんな感じです

$ vim app.rb
require "sinatra/base"
require "sass"
require "haml"
require "coffee-script"

module Portfolio
  class App < Sinatra::Base
    get '/' do
      'hello'
    end
  end
end
$ vim config.ru
require "./app"
run Portfolio::App

でアプリがちゃんと動くかどうか確認してみる
shotgunを入れておいたので

$ bundle exec shotgun
== Shotgun/WEBrick on http://127.0.0.1:9393/
[2012-04-26 23:49:20] INFO  WEBrick 1.3.1
[2012-04-26 23:49:20] INFO  ruby 1.9.2 (2011-07-09) [x86_64-darwin11.2.0]
[2012-04-26 23:49:20] INFO  WEBrick::HTTPServer#start: pid=457 port=9393

localhost:9393にアクセスして hello が表示されればOKです
そしたらこっからガシガシコード書いていくんですが、shotgun使ってるのでapp.rbを編集してもサーバの再起動が必要ありません。
home、about、galleryの3ページと仮定して以下のように書き換えました

$ vim app.rb
module Portfolio
  class App < Sinatra::Base
    before do
      @site_name = 'My Portfolio'
      @nav = ['home', 'about', 'gallery']
    end
    
    get '/' do
      haml :index
    end

    get '/about/?' do
      haml :about
    end

    get '/gallery' do
      haml :gallery
    end
  end
end

before do ... end の中で共通の処理を記述できます。
site_nameとnavを用意しておきました。変数に@をつけておくとインスタンス変数と言ってviewに渡せるようになります。
htmlはhamlで書くので以下のようにします。

$ vim views/index.haml
%h1= @site_name
%nav
  %ul
    - @nav.each do |n|
      %li
        %a{href:"/#{n}"}= n
%p welcome to my portfolio site

でもこれだとheadとかないので layout を作成します

$ vim views/layout.haml
!!! 5
%html
  %head
    %meta{charset:'utf-8'}
      %title= @site_name
  %body
    = yield

yieldの部分に各ページの内容が入ります。
次はsassというかscssを使ってみます。
まずはapp.rbを編集して、

$ vim app.rb
get '/stylesheets/base.css' do
  scss :base
end

galleryの下に追記しておきました。
ここまで出来たら後はviews内にscssファイルを作って作業していくだけです。
簡単ですね!

ちなみにrubyのシンボル(:で始まる文字列)は " で囲めば / とかも使えるので
views内でファイルが平置きになってるのが嫌な人は views/haml や views/scss を作っておいて
app.rbで

haml :"haml/index"

と指定すればちゃんと呼び出せますよ!

sinatraとかhamlとかscssとかcoffeescriptの詳しい使い方はドキュメントを読もー

2012年4月19日木曜日

トマト栽培

今朝は芽が3つになってました!


しかも結構な成長速度。昨日よりかなり成長してる気がするなぁ。

日付
2012.04.19
気温
17℃
天気
曇り
2012年4月18日水曜日

トマト栽培

やっと芽が出ました!


なんの変化もないプランターを写真撮り続けるのは、マジで精神的にきついなと思ってたんでしばらくお休みしてましたが、やってくれましたよ〜。
植物を育てるってこんなに嬉しいんですね。芽が出た後の育て方も調べよう。

日付
2012.04.18
気温
19.9℃
天気
晴れ

分かりづらいけど、左右二ヶ所に芽がでた…!

2012年4月16日月曜日

OS X lion にhomebrewでnginxとphpをインストールした

まずはnginxのインストール。

$ brew options nginx
nginx
--with-passenger
 Compile with support for Phusion Passenger module
--with-webdav
 Compile with support for WebDAV module

今回はどちらもいらないので普通に brew install nginx で設定をいじる。

$ cd /usr/local/etc/nginx
$ vim nginx.conf
#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
    include /usr/local/etc/nginx/sites-enabled/*;
}
こうしておいた
$ mkdir sites-enable
$ mkdir sites-available

このディレクトリ必要なの?って思ったけど、シンボリックリンクの作成/削除で複数ファイルの管理ができるよってことなんですね。なんかかっこいいですね。

で、availableの方に…

$ vim sites-available/localhost
server {
    listen 8080;
    server_name localhost;
    root /Users/kozo/Web/nginx/localhost/public;

    access_log  /Users/kozo/Web/nginx/localhost/logs/access.log;
    error_log  /Users/kozo/Web/nginx/localhost/logs/error.log warn;

    location / {
        index index.html index.htm index.php;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    }
}

とした。

続いてphpのインストール。

$ brew options https://raw.github.com/ampt/homebrew/php/Library/Formula/php.rb
php
--with-mysql
 Include MySQL support
--with-pgsql
 Include PostgreSQL support
--with-mssql
 Include MSSQL-DB support
--with-fpm
 Enable building of the fpm SAPI executable
--with-apache
 Build shared Apache 2.0 Handler module
--with-intl
 Include intl extension
--with-readline
 Include readline extension

適当にオプション付けて

$ brew install https://raw.github.com/ampt/homebrew/php/Library/Formula/php.rb --with-mysql --with-pgsql  --with-fpm --with-intl --with-readline

そしたらエラー!
ココでも見てなんとかしろや的なこと言われたので見てみる
https://github.com/mxcl/homebrew/wiki/checklist-before-filing-a-new-issue

brew updateか。

$ brew update

またエラー。というかgitのリポジトリでconflict的なことが起きてるのかな?

$ cd /usr/local/
$ git fetch origin/master
$ git reset --hard origin/master
$ brew update
Already up-to-date.

OK! phpのインストール出来ました。 このままだとcliがMacにプリインストールされてる方を見ちゃうので

$ vim ~/.bash_profile
$ export PATH="$(brew --prefix)/bin:$PATH" 

上記を追加しました。

$ php -v
PHP 5.3.10 (cli) (built: Apr 16 2012 17:15:01) 
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies
    with Xdebug v2.1.2, Copyright (c) 2002-2011, by Derick Rethans

よし。で、fpmの起動用plist作成

$ vim ~/Library/LaunchAgents/php-fpm.plist
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd" >
<plist version='1'>
  <dict>
    <key>Label</key><string>org.php.php-fpm</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/sbin/php-fpm</string>
      <string>--fpm-config</string>
      <string>/usr/local/Cellar/php/5.3.10/etc/php-fpm.conf</string>
    </array>
    <key>Debug</key><false/>
    <key>RunAtLoad</key><true/>
    <key>KeepAlive</key><false/>
    <key>UserName</key><string>kozo</string>
  </dict>
</plist>

※.plistの拡張子付けないと後のlaunchctl loadで怒られました

php-fpm起動!

$ launchctl load -w ~/Library/LaunchAgents/php-fpm.plist

最終確認

$ cd ~/Web/nginx/localhost/public/
$ vim index.php
<?php echo 'Hello' ?>

と書いて http://localhost:8080/ を開いて Hello でました! 思ってたより簡単だったけどちょっと戸惑った。

参考にしたサイト

  • http://aoyagikouhei.blog8.fc2.com/blog-entry-195.html
  • http://d.hatena.ne.jp/YuhoYo/20110528/1306547056
  • http://labs.uechoco.com/blog/2011/12/php-homebrew-how-to-compile-intl-enabled-php.html
  • http://www26.atwiki.jp/nginx/pages/13.html
  • http://www.1x1.jp/blog/2011/05/yum_install_nginx_php-fpm.html

※追記 2012/04/17

再起動はこうすればいいらしい:

$ sudo nginx -s stop && sudo nginx
2012年4月13日金曜日

トマト栽培

日付
2012.04.13
気温
21℃
天気
晴後曇

変化なし

2012年4月12日木曜日

トマト栽培

日付
2012.04.12
気温
23℃
天気
晴れ

全く変化なし

2012年4月11日水曜日

トマト栽培

日付
2012.04.11
気温
18℃
天気
曇り

変化なし

2012年4月10日火曜日

トマト栽培

日付
2012.04.10
気温
19℃
天気
晴れ
2012年4月9日月曜日

トマト栽培

日付
2012.04.9
気温
23℃
天気
晴れ

特に変化なし。

2012年4月8日日曜日

トマトの栽培をしてみることにした

自分にはテック系の記事は書けない(&続かない)ことがわかったし、一人暮らしが2年目に入って、寂しさを紛らわす意味もあってトマトの栽培を始めることにしたから、とりあえずトマトを記事にしてみることにした。

第一回目は買ってきたものとその準備。

◆買ってきたもの

  • プランター(木製の桶型のもの)
  • 水差し
  • スコップ
  • 培養土
  • 赤玉土
  • 肥料

  • トマトの種(イタリアントマト)

この品種のトマトは支柱が要らないタイプ(パッケージの説明書きに書いてあった)なのでお手軽に出来そうだからこれにした。

◆土の準備と種蒔き

全くの初心者だから何一つ自信ないけど、土のパッケージとか参考にしながら土を準備。
写真は赤玉土を底に敷いて、培養土を3〜4cm敷いたら肥料を混ぜて、また培養土を重ねる感じでつくってみた。

白いのは種の袋。種を袋から出してみてびっくりしたんだけど、普段食ってるトマトと何も違わなかった。そりゃ当然だよねトマトなんだから。


それにしても種あまりすぎ…こんなちっちゃいプランターじゃ全然減らない。これ保存が効くのだろうか……?
3つ穴をつくって種まいてみた(暗くて見えない)

で、発芽するまでは土を乾燥させすぎない暖かい所がいいらしいんだけど、今年は4月に入ってもなかなか気温が上がらない。
なのでゴミ袋でビニールアウス的にしてみることにした。

あまった土をまとめた袋と並べて置いたらゴミにしか見えない…


初日はこんなところ

日付
2012.04.08
気温
11℃
天気
晴れ
2012年2月2日木曜日

[jQuery]文字列内の式展開を書いてみた

で、式展開ってこれでいいのかな?
気になってるのは該当のする#{}がすべて置き換わった後もループを続けてしまうところ。

まだまだブラッシュアップできる気がするなぁ。

2012年1月31日火曜日

[ruby]最初に知っておけば良かったbundlerの使い方 rails編

PHPの代わりというか、次のレベルとしてRubyを使うならまず最初にbundlerの使い方を知っておきたかった。 以下自分なりに覚えたbundlerの使い方を記録しておく。

作業ディレクトリを作る。

$ mkdir hoge_project

railsなんかはディレクトリ名がそのままアプリ名になっちゃうから気をつける
(これってオプションでディレクトリ名と別の名前渡せるのかな??)

作業ディレクトリでbundlerのinitを実行する。

$ cd hoge_project
$ bundle init
Writing new Gemfile to /Users/username/hoge_project/Gemfile

これでサンプルのGemfileが作られる。
▼内容

# A sample Gemfile
source "http://rubygems.org"

# gem "rails"

▼一行目を削除し、四行目のコメントアウトを外してバージョンを3.1.3に指定

source "http://rubygems.org"

gem "rails", "3.1.3"

プロジェクトローカルな状態でgemをインストール

$ bundle install --path vendor/bundle

地味にbundlerの便利なところはこの時点でvendorフォルダの有無に関わらずインストール出来ちゃうところ。

Fetching source index for http://rubygems.org/
Installing rake (0.9.2.2) 
Installing multi_json (1.0.4) 
Installing activesupport (3.1.3) 
Installing builder (3.0.0) 
Installing i18n (0.6.0) 
Installing activemodel (3.1.3) 
Installing erubis (2.7.0) 
Installing rack (1.3.6) 
Installing rack-cache (1.1) 
Installing rack-mount (0.8.3) 
Installing rack-test (0.6.1) 
Installing hike (1.2.1) 
Installing tilt (1.3.3) 
Installing sprockets (2.0.3) 
Installing actionpack (3.1.3) 
Installing mime-types (1.17.2) 
Installing polyglot (0.3.3) 
Installing treetop (1.4.10) 
Installing mail (2.3.0) 
Installing actionmailer (3.1.3) 
Installing arel (2.2.1) 
Installing tzinfo (0.3.31) 
Installing activerecord (3.1.3) 
Installing activeresource (3.1.3) 
Using bundler (1.0.21) 
Installing json (1.6.5) with native extensions 
Installing rack-ssl (1.3.2) 
Installing rdoc (3.12) 
Installing thor (0.14.6) 
Installing railties (3.1.3) 
Installing rails (3.1.3) 
Your bundle is complete! It was installed into ./vendor/bundle

こんな感じでインストール完了。
最初はrails以外のgemがわんさかインストールされちゃってる事にかなりびっくりしました。
今なら依存関係があるから当たり前やんって思うけど、この辺のニュアンスってなかなか初心者には分かりづらい。

ここまでだとrailsアプリはまだ出来てないのでスケルトンを作る

$ bundle exec rails new . -T -d mysql

このコマンドの意味するところは
プロジェクトローカルのgemを使い、
railsの新しいアプリケーションをこのディレクトリで作成し、
かつtestディレクトリを省略し、
DBはmysqlを選択
ということです。

▼で実行するとこんな問いかけをくらう

       exist  
      create  README
      create  Rakefile
      create  config.ru
      create  .gitignore
    conflict  Gemfile
Overwrite /Users/username/hoge_project/Gemfile? (enter "h" for help) [Ynaqdh] 

既存のGemfileをrails仕様に上書きしてもいいか?ということで問題ないので enter

       force  Gemfile
      create  app
      create  app/assets/images/rails.png

          ... 省略 ...

         run  bundle install

でここでエラーが発生するんですよねぇ…
/Users/username/.rvm/gems/ruby-1.9.2-p290@global/gems/bundler-1.0.21/lib/bundler/resolver.rb:280:in `resolve': Could not find gem 'jquery-rails (>= 0) ruby' in any of the gem sources listed in your Gemfile. (Bundler::GemNotFound)

でも気にせずrspecをGemfileに追加

group :development, :test do
  gem 'rspec-rails'
end

でbundle installに再チャレンジ

$ bundle install
Fetching source index for http://rubygems.org/
Installing coffee-script-source (1.2.0) 
Installing execjs (1.3.0) 
Installing coffee-script (2.2.0) 
Installing coffee-rails (3.1.1) 
Installing diff-lcs (1.1.3) 
Installing jquery-rails (1.0.19) 
Installing mysql2 (0.3.11) with native extensions 
Installing rspec-core (2.8.0) 
Installing rspec-expectations (2.8.0) 
Installing rspec-mocks (2.8.0) 
Installing rspec (2.8.0) 
Installing rspec-rails (2.8.1) 
Installing sass (3.1.12) 
Installing sass-rails (3.1.5) 
Installing uglifier (1.2.3) 
Your bundle is complete! It was installed into ./vendor/bundle
※既にインストール済みの行は省きました

よし!
これでrailsアプリのスケルトン出来ました。
後はrailsコマンドとかrakeするときに常に bundle exec を付けておけば
プロジェクトローカルのgemで実行されます。

アプリケーション毎のbundlerの設定は bundle config で確認できる(.bundle/configファイルの中身を見てる)

$ bundle config
Settings are listed in order of priority. The top value will be used.

path
  Set for your local app (/Users/username/hoge_project/.bundle/config): "vendor/bundle"

disable_shared_gems
  Set for your local app (/Users/username/hoge_project/.bundle/config): "1"

開発用サーバを起動

$ bundle exec rails s
=> Booting WEBrick
=> Rails 3.1.3 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2012-01-31 17:06:22] INFO  WEBrick 1.3.1
[2012-01-31 17:06:22] INFO  ruby 1.9.2 (2011-07-09) [x86_64-darwin10.8.0]
[2012-01-31 17:06:22] INFO  WEBrick::HTTPServer#start: pid=1895 port=3000

ちなみにこの時に -p (ポートオプション)を付ければ好きなポート番号でWEBrickを起動できますね

まだ初心者が知っておいたほうがいい事があって、
バージョン管理している場合気を付けなくちゃいけないのは vendor/bundle ディレクトリは管理の対象にしないこと。
これって本業のプログラマーさんなら当たり前なんだろうけど。
mysql2とか、環境に依存するgemもあるから環境毎にbundle installするべきだってことに気づくのが大分遅かった…

2012年1月6日金曜日

Nokogiriでページタイトルを取得する

これがあんまりうまく行かない場合が多い。ローカル(Mac)では取得できるけどherokuでダメってことも多い。
ということで今のところ以下のように落ち着いてる。 取得先のHTML構造が壊れていたり、URLに日本語がそのまま含まれていたりすると厄介。