ページ

2013年10月17日木曜日

capistranoでmiddleman buildするまで

前回、bundle installするところまで出来たけど、その後middleman buildもして欲しかった。

capistranoでやる以前に、そもそもUbuntuでmiddleman buildしようとすると、execjsがjavascriptのruntimeが見つからないと言って泣いていた。
幾つかの依存ライブラリが足りないらしいので、Gemfileに以下を追加
gem "rb-inotify"
gem "therubyracer"

これでmiddleman build自体は出来るようになったので、今度はcapistranoでやるように、deploy.rbを編集。
capistrano-bundlerのソースとか見よう見まねで、こんな風になった。


withinとか要らなそうだったり、executeが2行に分かれてたりとか、若干気に入らないところはあるけども、ともあれこれでbundle installの直後にbundle exec middleman buildされるようになった。

2013年10月14日月曜日

capistranoでbundle installするまで

今回はいつにも増して個人の覚え書きです。

この度、初めてcapistranoを使ってみようと思ったら、ちょうど3.0.0が出たばっかりのタイミングだったらしく、ググって出てくる情報が微妙に役に立たなかった。
2.x系は使ってないのでわからないが、2から3へのアップグレードについては http://www.capistranorb.com/documentation/upgrading/ とか見ればいいと思う。

インストールは普通に、gem installするか、Gemfileに書いてbundleする。

プロジェクトの初期化的なことをする。
$ cap install
bundlerでインストールした場合はbundle execをちゃんと付ける。(後で出て来るcapistrano-rbenvを使おうとした時に、この辺の話でしばらくハマった)

cap installすると、Capfileやら何やら色々生成される。

deploy.rbやらproduction.rbやらに目を通すと、よくわからないDSLが書いてあるので、ちょっと読んで嫌な気持ちになる。

role :appとか3つぐらい書いてあるところがあるが、僕の場合サーバーは1個しかないので server で代用できる。

あとはdeploy.rbの:application、:repo_url、:deploy_toぐらいを書けばたぶん最低限のデプロイはできる。(set :scm :gitは書かなくても動いた)

$ cap
だけだと、Stageがセットされてないって文句を言われるので、
$ cap production deploy
とか、してやる。


bundle installもして欲しいので、続いてcapistrano-bundlerを使う。
gem installもしくはGemfileに書いてbundle。

Capfileで
require 'capistrano/bundler'
すれば、deploy:updatedの前にbundle installしてくれるはず。

が、エラー。
/usr/bin/env: bundle: No such file or directory

原因は、サーバーでrbenvを使っていて、capistranoはsudoでコマンドを実行するため、sudo /usr/bin/env だとrbenvのgemとパスが違ってしまうこと。
サーバーのbashrcとか/etc/sudoersとかを書き換えたり、Capfileでset :use_sudo, falseとかしても駄目だった。

そこで、capistrano-rbenvというものがあるのでそいつを使う。
rubygems.orgにホストされているのは古いので、ソースにgithubを指定してやる必要がある。
(僕の場合、前二つをgem installして、ここでGemfileに書くようにしたため、bundle execつけずに実行してワケが分からなくなった)

Usageを見ると
require 'capistrano/rbenv'

set :rbenv_type, :user # or :system, depends on your rbenv setup
set :rbenv_ruby, '2.0.0-p247'
をCapfileに書くか、rbenvのパスによってはrbenv_custom_path使え、と書いてあって、僕が使ってるUbuntuでは実際rbenvのパスがcapistrano-rbenvのデフォルトと違ったので、
set :rbenv_custom_path, '/opt/rbenv'
を、rbenv_typeの代わりに書いてやった。

これでようやく、デプロイしてbundle installされるようになった。

2013年8月11日日曜日

Chefからufwを有効にする

execute resouceを使った。

ufw enable と ufw allow sshしている。

sshでufw enableしようとすると、sshのコネクションが切れるかもしれないけどいい?(y|n) みたいな確認をしてくるので、パイプでyesを渡してやっている。
手元でvagrant使って試したらこれでいけたけど、allow sshが先に実行されるようにしたほうがいいのかもしれない。

chefはknifeとかcookbookとかの用語とDSLで、学習コストを飛躍的に高めてしまっていると思う。

2013年6月25日火曜日

[Mac]Vagrantのインストール

Vagrantの前に、VirtualBoxをインストールする。
https://www.virtualbox.org/ からインストーラーを落としてきてインストール。

続いてVagrantのインストール。
http://docs.vagrantup.com/v2/installation/ 曰く、バージョン1.0.xの時にあったRubyGemsを使ってのインストールはもう無いらしい。もしgemでインストールされてたら先にアンインストールしておいてね、とのこと。
というわけでこちらもインストーラーを落としてきてインストール。

インストールできたら以下のコマンドを実行するとUbuntu 12.04 LTS 32-bitのイメージがダウンロードされて、立ち上がる。
$ vagrant init precise32 http://files.vagrantup.com/precise32.box
$ vagrant up

立ち上がる……はずが立ち上がらない。
VBoxManageのimportコマンドでエラーがどうこう言っている。これで貴重な日曜日の午後が失われた。

そして昨日、月曜日。VitrualBoxのバージョンを一つ下げて4.2.10で試してみたらすんなりいけた。

で、今日。このようなものを見つける。
https://github.com/mitchellh/vagrant/issues/1847
https://www.virtualbox.org/ticket/11895

というわけで近いうちに直ると思われるが、それまでは4.2.10を使っておくのが吉。

2013年6月16日日曜日

JavaScriptのテスト環境を整える その3

その1 その2

モジュール単位でファイル分割する。RequireJS使う。

前々回からのbower.jsonを編集。dependenciesにrequirejsを追加する。
{ "name": "zakuni-js-template", "version": "0.0.3", "main": "main.js", "ignore": [ "**/.*", "node_modules", "components" ], "dependencies": { "requirejs": "latest" }, "devDependencies": { "mocha": "latest", "chai": "latest" } }

色々と試行錯誤した結果、こうなった。
. ├── bower.json ├── camera.coffee ├── camera.js ├── components │   ├── chai │   ├── jquery │   ├── mocha │   └── requirejs ├── index.html ├── main.coffee ├── main.js └── test ├── test.camera.coffee ├── test.camera.js ├── test.coffee ├── test.html └── test.js
index.html用のメインと、テスト用のmainは別のファイルにする(main.jsとtest.js)。
あと、テストもモジュール単位で分ける(camera.jsのテストはtest.camera.jsを作るようにする)。
mocha.setupとかmocha.runはtest.jsで行う。

中身はこういう感じになっている。


https://github.com/zakuni/js-template/tree/v0.0.3
RequireJS使おうとしたら時間かかってしまって最終的にちゃんと整理しきれなかった感があるので、そのうちまたまとめ直すかもしれない(しないかもしれない)。

2013年6月10日月曜日

JavaScriptのテスト環境を整える その2

前回の続き。

あとやりたいことは、CoffeeScriptを使ってる時でも同じようにテストを書けるようにするのと、ファイル分割。
どちらを先にやるかだけど、後でわざわざ書き直すめんどくささもさることながら、それで動かなくなって悩むのは嫌なので、Coffee化を先にやることにした。
前回のmain.jsは
var a = 1;
だけだった。
これをCoffeeScriptで書くと
a = 1
となるわけだが、これをコンパイルしたmain.jsを使うようにするだけで、前回書いたテストは通らなくなる。

なぜかというと、CoffeeScriptから生成されるJavaScriptは、無名関数で囲われていて、グローバル汚染を防いでくれている。
つまり、先ほどのmain.coffeeをjsにコンパイルすると

こうなるので、変数aには外部からアクセスできず、ReferenceErrorになってしまう。

尚、コマンドラインからmochaを使ってテストする分には
% mocha --compilers coffee:main.coffee
みたいにすると中でうまいことやってくれてcoffeeでもテストを通すことができる。
(今回書いてるやつそのままでは通らない。-uオプションでtddを指定したり、chaiをrequireする必要がある)

前回は素のJavaScriptの話だったのでブラウザで実行することを重視したけど、CoffeeScript書いてるならnpmも使ってることが多いだろうし、それなら素直にコンソールでmochaを使えばいいような気がする。

そして気づいたけど、前回使ったbowerはインストールするのにnpm使ってるだろうから、ブラウザにこだわる必要はないような気もしてきた。
ただ、mochaとかchaiをファイルでダウンロードしてきて使う人とかもいるだろうと思えば、意味はあるので一応続ける。

無名関数の中で宣言されているのでアクセスできないことについては色んな解決方法があると思う。
簡単な方法の一つは、windowオブジェクトのプロパティにしてしまうこと。
window.a = 1
テストコードは変えないままグリーンになる。

というわけでこういう風に書ける

ここではやってないけど、テストもcoffeeで書けばいいと思う。

そしてひと区切り。あとはファイル分割する。

ここまでまとめたやつ。
https://github.com/zakuni/js-template/tree/v0.0.2

2013年6月9日日曜日

JavaScriptのテスト環境を整える

クライアントサイドJavaScriptでBackbone.jsとかのフレームワーク使いつつrequire.jsでファイル分割しつつ、更にそれらをCoffeeScriptで書いていた場合にテストを書こうと思ったら軽く発狂しそうになったので、一つずつ解決していくことにした。

個人的な趣味等を鑑みて前提条件は以下のような感じになった。
・CoffeeScriptでも同じような構成で使える
・ファイル分割できる
・テストがブラウザ上でも動作する

自動化は今回の範疇にはない。

後からテストが書きづらかったということに端を発するので、テスト駆動で開発する。
% bower install mocha
mochaを選んだ理由は、expect.jsとかQUnitとかと組み合わせやすそうなことと、ブラウザとコンソール両方で動かせるのと、Nodeでも使えるから。
npmじゃなくbowerでインストールしているのは、クライアントサイドのことはなるべくクライアントサイドで完結させたいので、なるべくNodeと切り離したいのがあるから。

mochaのサンプルを見ながらテスト用ページのひな形を作る。mocha.setupをbddでなくtddにしたのは趣味の問題。

これをブラウザを開いてみると、passes: 0 failures: 0 duration: 0s とか出てるはず。

assertionのために別のライブラリを使う。色んな書き方に対応してるChaiを使ってみることにした。
あと、ここでbower.jsonを作った。
% bower init
ちょっと編集する。
mochaもchaiもテストで使うものなのでdevDependenciesに入れた。
{
  "name": "zakuni-js-template",
  "version": "0.0.1",
  "main": "main.js",
  "ignore": [
    "**/.*",
    "node_modules",
    "components"
  ],
  "dependencies": {
  },
  "devDependencies": {
    "mocha": "latest",
    "chai": "latest"
  }
}

HTMLを編集して、テストを書く。

これでブラウザリロードして、グリーンになってればOK。

namespace的なこととか考えないならたぶんこれで充分テストを書いていける。
ひとまずここで一区切り。

ここまでをまとめたのが以下のもの。
https://github.com/zakuni/js-template/tree/v0.0.1

2013年6月4日火曜日

chef-solo使い始める

さくらのVPSで使ってるUbuntuをまた壊してしまって直らない。
それならいっそ何度再インストールしようが痛くないようにchef使っておくことにした。

knife-soloを入れる。

% gem install knife-solo
何故かやたら時間かかった。

Chefレポジトリを作成する。
% knife solo init chef-repo

作成はされたけどwarningが出てた。
WARNING: No knife configuration file found

設定しておく。
% knife configure
色々聞かれたけどとりあえずreturnを連打してデフォルト設定にした。

とりあえず練習を兼ねてnginx用のクックブックを作る。
% cd chef-repo
% knife cookbook create nginx -o site-cookbooks
そうすると site-cookbooks以下にnginxフォルダとか出来る。

site-cookbooks/nginx/recipes/default.rbを編集して、
package "nginx" do
    action :install
end
とか書くと、サーバーにこのレシピを適用したときにOSの違いとか吸収してnginxをインストールしてくれるはず。

クライアント側からサーバーにchefをインストールさせることができる。
knife solo prepare user@host
sshと同じように -i とか -pとか -Pを付けて実行できる。

この時のユーザーはsudoできるユーザーじゃないといけない(たぶん)。

上の例だとクライアント側のnodesフォルダ内にhost.jsonっていうJSONファイルが生成されているはず。
こいつを編集してやって、どのレシピを使うかを指定する。
{"run_list":[]}
とかなってると思うので、こうする。
{"run_list":["nginx"]}

そしてサーバーにレシピを適用する。
% knife solo cook user@hoge
prepareの時と同じで、ここでもsshで接続するときと同じようにオプションを指定する。

ここまで正しくできてればnginxがインストールされる。
同じように他のレシピも作っていく。

2013年3月23日土曜日

Play2.1でHTTPのGETする

Playにはplay.api.libs.ws.WS(Web Service、WebSocketではない)というライブラリがあってHTTP通信をすることができる。
非同期にやってくれるので、レスポンスを同期的に使うには返り値をちょっとゴニョゴニョしないといけない。

で、Play2.0系のときはPromise[ws.Response]で返ってたんだけど、2.1からはFuture[ws.Response]で返ってくる。
ググって上の方に出てくるやつは大体2.0系の話なのでそのままでは動かない。

なので2.0系で以下のように書いていたものは

2.1系では以下のように書く必要がある。

本来これでいいと思うのだけど、
http://grokbase.com/t/gg/play-framework/131rzk6wcm/possible-ws-response-encoding-bug
とかで言及されているように<meta charset="utf-8">とか書かれてるHTMLでもISOで返ってきちゃう。

なので、文字コードを変換してやる

ちゃんと探してないけど、もしかしたらWSのオプションとかでエンコードを指定してやったりできるのかもしれない。

2013年2月27日水曜日

認証付きProxy環境下でHomebrewのインストール

export http_proxy=http://USER:PASS@PROXY:PORT
export ALL_PROXY=$http_proxy
してから
ruby -e “$(curl -fsSkL raw.github.com/mxcl/homebrew/go)”
する。

brew install等するときにも同様なので、上の2行をシェルの設定ファイルに書いておくのがよかろう。

BundlerでSSLの証明書エラー

Gemfileのsourceにhttps://rubygems.orgを指定してbundle updateとかすると
Unfortunately, a fatal error has occurred. Please see the Bundler
        troubleshooting documentation at http://bit.ly/bundler-issues. Thanks!

とか出てエラーになる。Thanks!じゃねえよ。

homebrewで入れたopensslには証明書が入っていないとかで、いれてやることで解決した。
% brew install curl-ca-bundle
% brew list curl-ca-bundle
/usr/local/Cellar/curl-ca-bundle/1.87/share/ca-bundle.crt
% cp /usr/local/Cellar/curl-ca-bundle/1.87/share/ca-bundle.crt /usr/local/etc/openssl/cert.pem

参考: http://qiita.com/items/12457815d5cee3723b97

今まで気づいてなかっただけで1.9とかの頃から出てたのかもしれない。

2.0rc2からはrbenv installするだけでopensslもコンパイルされるという話もあるが、未確認。(http://qiita.com/items/f95c6f0a297d7b8edbd5)

2013年2月16日土曜日

MacRubyにおけるnilの扱い

参考: https://github.com/MacRuby/MacRuby/wiki/Common-Issues

Rubyでは、nilに対して定義されてないメソッド呼び出しをするとNoMethodErrorになる。一方、Objective-Cではnilに対してメッセージを投げても実行時エラーになることはなく、nilが返ってくる。

さて、MacRubyではどうなっているかというと、(少なくとも現状は)Rubyに合わせた仕様になっているらしく、NoMethodErrorになる。

ただ、既存のObjective-Cのコードを置き換えるとか、Cocoa的に書くとnilにメッセージを投げたい場合も出てくると思うので、そういうときは

framework 'Foundation'

しておけばいい。

RubyMotionとかMobiRubyではこの辺どうなってるんだろう。

2013年1月6日日曜日

MacRubyでCocoaPodsのインストールができなかった

CocoaPodsをインストールする。

普通のrubyでもいいらしいが、macrubyのほうが相性が良さそうな気がするのと、元々macrubyで使おうと思っているのでrbenvでmacrubyに切り替えてgem installする。
尚、rbenvとかrvmじゃないときはmacgem installする。
% gem install cocoapods
 あとこれも必要
% pod setup
 そしたらエラーが出た。

fork() function is unimplemented on this machine
とか出てる。ええー?

よくわからんので一回普通のruby1.9.3でgem installとpod setupしたらすんなりいけた。ええー?