Rubyの::演算子について
ruby*1では、A::B
という形式の式は、NODE_COLON2
という名前になる。::
という演算子の式なので、コロンが二つでCOLON2だろうか。とても素直な名前である。::
の両端には普通はA
とかB
とかの定数名を書くが、call
メソッドを呼ぶための構文でも使う。
irb(main):001:0> self::(3) NoMethodError: undefined method `call' for main:Object irb(main):002:0> (:succ.to_proc)::(3) => 4
これいつからある機能なんだろ……
さて、rubyのソースコードを見ていると、NODE_COLON3
という定義もある。これはコロンが三つ並んだ演算子ではなく、トップレベルの定数を参照するための演算子で、::Object
とか書くと作ることができる。なんで3にしちゃったのかあまり合理的な理由がなさそうな気がする、とても投げやりな感じの、見つけると楽しくなる名前である。*2
なんで、NODE_COLON2
を流用するのではダメかというと、
node.h:#define NEW_COLON2(c,i) NEW_NODE(NODE_COLON2,c,i,0) node.h:#define NEW_COLON3(i) NEW_NODE(NODE_COLON3,0,i,0)
となっていて、さらに
parse.y: $$ = NEW_COLON2(0, $$);
というのがあって、つまりNEW_COLON3(n)
とNEW_COLON2(0, n)
を区別するためなんだけど、なんで区別する必要があるのかはよくわからない。NODE_COLON2
を流用しようとしていろいろ試行錯誤したけどうまくいかなくて、力尽きて良い名前も思いつかずにいつのまにかNODE_COLON3
になったんだろうと想像している。
ちなみにNODE_COLON
やNODE_COLON1
は定義されていない。Rubyではコロンはシンボル:symbol
やハッシュ{ key: value }
に使われるが、それらは字句解析か構文解析の時点で、他の構文に取り込まれてしまう。
Rubyの定数は難しい
ネストしたモジュールとかクラスの定義方法には、まあ二つくらい書き方がある。
バカ正直にネストしたモジュールを並べる方法。
module A module B module C ... end end end
::
演算子を使う方法。
module A::B::C ... end
この二つは同じだと思っていたのだけど、同じではなかったことに気付いたという話。
私は、これまでは後者の方を好んで書いていた。なぜかというと、定数のネストの途中に出てくるA
やA::B
がモジュールなのかクラスなのかを考えなくて良いからだ。純然たる名前空間として使うときはモジュールが使われるが、クラスのこともある。考えたくない。
この二つの違いは、定数を参照するときである。具体的に言うと、次のような定数A::B::X
を参照するときに違いが生まれる。
module A module B X = "A::B::X" end end module A module B module C p X # => ちゃんと動く end end end module A::B::C p X # => const_missing end
これはかなり難しい……
- 定数はネストした構造を持つことがある(これは実行時に値から参照できる構造)
- 一方でプログラム中の定数の参照は、構文的な構造に依存するもので、実行時の構造は関係がない(Lexical scopeというやつであってる?)
A
の中のB
の中のC
の中に書いたX
は、それぞれのモジュール式をさかのぼっていって、A::B::C::X
かA::B::X
かA::X
か::X
が探索されて、この場合はA::B::X
に解決される- 一方で
A::B::C
という名前のモジュール式の中に書いたX
は、モジュール式をさかのぼることができないので、A::B::C::X
か::X
のどちらかになるのでconst_missing
うーむ。
- 作者: Peter J.Jones
- 出版社/メーカー: 翔泳社
- 発売日: 2015/01/19
- メディア: Kindle版
- この商品を含むブログ (1件) を見る
これはRailsアプリを書いている最中に発生した問題でなぜか、なぜかモジュールのautoloadに失敗するという問題で、普通に二晩くらい悩んだ結果*1、そういえばEffective Rubyに「定数の参照はレキシカルスコープだ」って書いてあった話を思い出したりとかして問題が解決したので、これはとても良い本であると言える。*2
ヒラギノの縦位置を揃えるちょうべんりなSketchプラグインの紹介
Sketch 3 Advent Calendar 2014の18日目の記事です。
Sketchでボタン的なものを作ろうとすると、テキストレイヤーの位置決めに苦労するのはよく知られた話だと思います。ボタンの外側を作って、内側にテキストレイヤーを追加して、Align Horizontallyして左右を揃えるところまでは良いのですが、次に縦を揃えようとしてAlign Verticallyすると、テキストレイヤーが意味不明な位置に移動して、悲しい思いをすることになります。
なにが起きているかというと、テキストレイヤーの形がおかしくなっていて、文字の下に謎の空白ができています。
これは多分ヒラギノの余白の計算が壊れているのだと思います。下の余白が予想外の大きさになった結果として、テキストレイヤーの矩形が意図しない感じになり、矩形同士を中央に合わせたら文字がすごい上に表示された。
ちなみに、欧文のフォントは全体的にちゃんと処理されていて、いい感じになります。テキストレイヤーを挿入した時点で、矩形の中心にテキストがくるように行の高さ(Lineの項目)が設定されてるように見えます。下の画像はAlign Verticallyしただけ。
いずれにせよ、私たちは日本語を書きたいので、この問題をなんとかしないといけません。なんとかするプラグインを作りました。
テキストレイヤーと外側のレイヤーを選択して、プラグインを実行すると、テキストレイヤーを中央に移動させます。ただし、テキストレイヤーの矩形を見て位置を揃えるわけではなく、フォントの設定を見て文字の位置を揃えます。ヒラギノでもいい感じに中央に来るようになっています。(なんか見てたらもう1px上でもいい気がしてきたけど。)
このエントリを書きながら、じっくり欧文フォントの振る舞いを確認したところ、このプラグインは日本人しか嬉しくないことに気づきましたが、でも日本人は嬉しいと思うので、みなさん試しに使ってみてください。
明日のSketch 3 Advent Calendar 2014のご担当はnukos_さんです。
PebbleからNew RelicでWebサービスの状態が確認できるWatchfaceを作りました
インストールはこちらから。ただし、あなたのスマートフォンがiPhoneの場合は、まだインストールできません。自分でPebble用のアプリをビルドできる場合は、GitHubリポジトリからソースコードをアレして$ pebble build
ってやってください。
- https://apps.getpebble.com/applications/54703777762f64feae000039
- https://github.com/soutaro/magellan
先週、東銀座Pebbleハッカソンっていうイベントがあって、そこで開発の一部を行いました。
スマートウォッチについて
iPhone 6 plusとかを使っていると感じるんだけど、明らかにポケットに入れるには大きすぎるので鞄に入れたりすることになって、これまでよりもスマートフォンとの距離が遠くなってしまう。その距離を埋めるためのものとして、スマートウォッチという存在は自然な拡張だと思う。
Watchfaceについて
Pebbleでは常に画面に出てる時計文字盤に対応するWatchfaceという種類のアプリを開発することができる。
これはすばらしい機能だと思うんだけど、多分ちゃんと理解している人が少なかった。大体みんな時間や天気を表示したり、ミッキーマウスとかポケモンとかの画像を背景に入れるくらいしか使ってないくて、とてももったいない。サーバの情報はかなりエクストリームだと思うけど、多分だけど気温よりももっと表示するべき情報がある。*1
この常時表示されている時計の画面は、スマートウォッチを確認するときとか見せびらかすときとかに常に目に入る部分で、ユーザー体験の一等地として熾烈な争いが勃発するべき場所だと思う。ちまちまボタンや画面を操作するのではなく、手首を見るだけでなにか良いことが起きるというシステムは、腕時計くらい自然に確認できるデバイスだと、かなり本質的だと思うんだけど。
そう思っていたけど、まあ誰も活用しているように見えなかったので、実はそうでもないのかなーと思って、試しに作ってみたのだった。
感想
文字盤にいきなりサーバの状況が出てるのはかなり面白い状況で、オフィスのでかいディスプレイに表示するよりもはるかに気軽に確認ができる。僕の場合サーバの健康状態を確認する頻度が10倍くらいに上がったし、確認できなくて不安に思うことが減った。
最初は時間を表示してなかったんだけど、腕時計を見たときに時間がわからないというのが、なんか良くわからないんだけどなんだかストレスを感じる状況だったので、小さく表示することにした。生まれたときから携帯電話があって、腕時計をつけたことがない人だと、こういうストレスは感じないのかもしれない。
Apple Watchについて
Apple Watchは、その辺が残念で、文字盤はユーザーから手が出せないようになっている*2。Glanceと呼ばれる種類のアプリがそれを補完するものとして機能する様に見えるので、そこに期待するしかない。Appleの社内でこういう考察がされていないというのはさすがに考えづらいので、いろいろとバランスを考えた結果、こうなったのだろう。
とはいえ、ロック画面をカスタマイズさせることを頑なに拒んできたチームの製品なので、あまり期待していない。ロック画面よりもユーザー体験の向上にはるかに直結しているところだと僕は思っていて、なのでカスタマイズできるようになると良いなーと思う。
一方で画面がカラーなのはすばらしいと思う。Pebbleは白黒なので、黒で「Green」とか「Red」とか書くはめになってて、もうちょっとなんとかなって欲しい。
Pebbleについて
- 今なら$77なので、2個買って右手用と左手用にすると良いと思います https://getpebble.com
- 基本的に日本語が出ないのでそこは諦めましょう http://www.texpress.co.jp/pebble_hiragana
4時間かかるバッチ処理に失敗していた
#!/bin/bash set -e PWD=`pwd` cd /var/tmp/data/... ${PWD}/do_something.sh ...
${PWD}
って、シェルの組み込みの変数で常にカレントディレクトリを返す子。先頭で代入した変数名が悪い。
#!/bin/bash set -e basedir=`pwd` cd /var/tmp/data/... ${basedir}/do_something.sh ...
これなら大丈夫。
WordPressを使いこなせる上司になろう
WordPressは辛い。何が辛いか。
- ふとアップデートすると壊れる
- こまめにアップデートしていると割と大丈夫だけど、ちょっと期間が空くと壊れる
- WordPressでCSSの変更したら壊れた画面が全世界に配信された
- プラグインを入れたら画面が見れなくなった
基本的にはWordPress使いたくないんだけど、そうはいってもBlogとかをいちいち自分で作るのは明らかにばかげているので、しぶしぶWordPressを使います。でも辛い。辛いのはできるだけ避けたいので、できるだけ辛くなくWordPressを使う方法を考えました。
基本的な戦略
普通に記事を書くときは別ですが、CSSとかプラグインとかを変更するときは、いきなり本番環境に適用するのではなくて手元の環境でちゃんと確認するべきです。
つまり、普通のWebアプリケーションを開発するときの流れをそのまま適用したい。普通どうするかというと、手元のPCに開発用の環境を作って、そちらで開発をします。また、Gitなどのバージョン管理ツールを使って、変更を追跡します。手元でちゃんと動作することを確認できる状況になったら、その時点でGitに変更を記録して、Productionのサーバにデプロイする。それでもぶっ壊れたらGitから古いちゃんと動作するバージョンを取ってきて元に戻す。これが基本的な流れです。
WordPressで作るサイトでも、この流れに乗りたい。もちろん、WordPressで記事を書くときはWebのUIをそのまま使うべきです。しかし、プラグインを入れたり、PHPを書いたり、CSSを書いたりしているときには、そうではない。
開発環境と本番環境を使い分ける
まず、開発環境と本番環境で、いくつか違うことをやらないといけない場面がありますので、それを切り替えられるようにします。切り替えないといけないことというのは、
- トップページのURL
- データベースの設定
などがあります。Railsではdatabase.yml
に書いたり、config/environments/development.rb
とかに書いたりするやつのことですね。また、例えばThe Twelve-Factor Appなんかでは、設定は環境変数に入れろと書いてあります。が、ここでは面倒なのでソースコードにそのまま書きます。
wp-config.php
にこんな感じで書きます。
if ( !defined('ABSPATH') ) define('ABSPATH', dirname(__FILE__) . '/'); if ($_SERVER["WPEnv"] == "development") { if (file_exists(ABSPATH . "development-config.php")) { require_once(ABSPATH . "development-config.php"); } } else { define('DB_NAME', ...); define('DB_USER', ...); define('DB_PASSWORD', ...); define('DB_HOST', ...); define('WP_SITEURL', 'http://blog.ubiregi.com'); define('WP_DEBUG', false); }
WPEnv
という環境変数にdevelopment
とか入れておくことにして、それで設定を切り替えます。本番環境用の設定はソースコードにそのまま書いていますが、開発環境用の設定はファイルから読み込みます。これは、開発環境では、個々の開発者・計算機によって、適切な設定が変わるからです。具体的にはMySQLの設定とかがホスト名によって変わります。あと、WPEnv
は、Apacheの設定ファイルで設定します。
多分、設定しておいたほうが良いのは、
- WP_SITEURL
- DB_NAME
- DB_USER
- DB_PASSWORD
- DB_HOST
- WP_DEBUG
くらいだと思います。
ApacheとMySQLをセットアップする
Apacheは手元のMacで動かしたくないので、Vagrantを使います。MySQLは、弊社で開発しているRailsアプリでも使うので、全部のMacにインストールされているので特に問題になりません。MySQLが無い人はがんばってインストールしてください。
なぜMySQLをVagrantに含めないのかというと、データベースは開発の全行程を通して使い回したいことの方が多いからです。Vagrantに入れておくのも一つの方法ですが、その場合vagrant destroy
するたびに全部データが消えます。消えてもいい人はそっちの方が設定が簡単になるので良いかもしれませんね。
適当にVagrantの設定を作ってあるので、見てみてください。
それぞれ設定のポイントを列挙します。
ネットワーク関連
VagrantからMacにアクセスできるようにVagrantfile
で設定しています。多分これはVirtualBoxのみの設定なので、VMWareとか使う人は適宜書き換えてください。起動時に必ずネットワーク設定を確認されるので、それがうざい人もまあ各自でなんとかすること。
avahi-daemon
をインストールしてあるので、VMからMacに名前でアクセスできるようになっています。上述のdevelopment-config.php
を作るときに、MySQLのサーバ名を名前で設定できて便利。なはず。
また、localhost:8080
にアクセスしたときに、VMのポート80に繋がるように設定しています。開発中のWordPressサイトにアクセスするときは、http://localhost:8080
にアクセスすれば良い。
Apacheの設定
Apacheの設定はwordpress.conf
に書いてあります。ここでWPEnv
を設定するようになっています。
あとはログとかの設定は、VMの中と共有されたlog
ディレクトリに書き出すように設定しています。
MySQLの設定
MySQLは、次の2点を設定します。
- ローカルホスト以外の接続を受け付けるように設定すること
- ちゃんとユーザを作っておく
VMで動いているWordPressから実機のMacで動いているMySQLに接続することになるので、別の計算機からログインできるようになっている必要があります。試すには、Macで、
$ mysql -h `hostname` <その他のオプション>
などとして、ちゃんと繋がるかどうかを確認します。
開発用のデータベースなので、できるだけ簡単になにも考えずに接続できる設定にする、という場合は、
bind-address=*
GRANT ALL PRIVILEGES ON *.* TO root@'%';
などとします。どこからでも接続できて、ユーザー名
root
でパスワード無しでログインできる設定です。私は開発用マシンならばこれで良いと思いますが(本番用はもちろんちゃんとパスワード設定します)、いろいろポリシーがあると思います。
開発を始めるときの手順
こんな感じで設定するようにすると、開発を始めるときの手順はこんな感じになります。
local-wordpress
のリポジトリを$ git clone
してくる- リポジトリの
site/wordpress
以下に、WordPressのアーカイブを展開する $ vagrant up
するhttp://localhost:8080
にアクセスしたときにWordPressサイトに繋がるようになっているので、いろいろサイト作成の作業を行うwp-config.php
を編集して、ついでにdevelopment-config.php
を作るwp-config.php
には、上のPHPのコードをコピペして、本番環境の設定を書く(後回しでもok)development-config.php
には、開発環境用の設定を書いておく
- サイト用のリポジトリを作る
今後の課題と想定される質問
デプロイをどうするのかまだ考え中。一番素朴にやると、普通にSSHでサーバにログインして$ git pull
するとかになるけど、ちょっと悲しいのであんまりやりたくない。Capistranoとかでうまいことできるはず。
- Vagrantがちゃんと動かない
- ネットワークの設定がちゃんと動かない事件が発生したことがあります。VMWareを使うようにすると、ちょっとは安定するようになります。
- データベースの内容に依存するようなコードを書かざるを得ないけどどうしたものか
- どうしたもんか……カテゴリとか記事のIDとかが、HTMLに出てくる問題には困っている。開発開始時とか、デプロイ時にMySQLのデータをコピーする戦略くらいしか思いつきません。
- Vagrantpressって知ってる?
- 知ってるけど、あれはプラグインを作るための環境なので、ちょっと今回の用途には合わない。これはサイトを作りたいときの話。具体的には、VagrantpressだとVagrantを起動するたびにMySQLの内容が消えたりするところが、使いにくい。
- デプロイがめんどうならHerokuとか使えば?
- ちょっとやってみるとすげええ面倒くさいので、お勧めしません。面倒くさいというのは、実際にサイトを運用する手順の話なので致命的である。画像アップロードとかはWordPressはかなり良い感じの実装が(クライアントサイド的には)されているのですが、それを全て捨てて、変なプラグインを使うことになります。お勧めはしない。
ユビレジのサービス状況を監視するためのモニタを作りました
ユビレジではNew RelicとかLogglyとか使ってサービスに問題が生じていないかを監視しているのですが、そうはいってもあんまりちゃんと監視できていないのが問題になっていました。簡単に言うとWebブラウザでいちいちアクセスするのは、明らかにめんどくさいわけです。具体的にNew Relicを見ようと思ったとすると、
- New Relicを見ようと思う
- ブラウザの新しいタブにrpm.newrelic.comと入れる
- パスワードを入れる
- アプリケーション一覧からUbiregiを選ぶ
- やっとモニタにたどり着く!
という手順が必要になります。全体的に面倒くさいのですが、この中で一番問題になるのは1の「New Relicを見ようと思う」ということです。あんまり思いません。そして、問題が発生するのは、問題が発生すると思いもしなかったタイミングです。メール通知なんかもありますが、わりと簡単に他のものに埋もれます。
そういうわけでこうなりました。
- 上半分はNew Relicの画面(レスポンスタイム、スループット、エラー率、Apdexが表示されている)
- 左下はHerokuのDyno数を表示(ユビレジではHireFireを使って自動でWeb Dynoを増減しています)
- 右下はTwitterでエゴサーチした結果
これを開発チームのデスクからお菓子エリアの動線に接するように設置したところ、お菓子を食べるタイミングで必ず目に入るようになりました。割と良い感じです。
作り方(ハードウェア)
iPad miniと、Apple TVと、DELLで買った19インチのディスプレイと、ディスプレイアームを使っています。ディスプレイはもっと大きくても良かったかもしれない。iPadが余っていたので使いましたが、別にMac miniとかでも良かった気もします(次で補足します)。
CI用の計算機やテスト用のレシートプリンタなどを配置してあるメタルラックにディスプレイアームでくっつけました。
作り方(ソフトウェア)
まず、Panicが公開しているStatus BoardというiPadアプリを使います。いまいち使いどころが難しいアプリだなーと思っていましたが、こんなぴったりの使い道があったなんてびっくりです!有料オプションのHD出力を購入すると、良い感じのアスペクト比で出力してくれます。
New Relicの画面は、Webページを表示する機能を使います。New Relicのチャート埋め込み機能を使うとiframeのスニペットができるので、それを並べてサイズ調整したHTMLを作り、Dropboxに置いて、それを表示しています。サイズ調整は、現物あわせでがんばります。
- New Relicの埋め込みチャートのiframeの先を、直接Status Boardに表示することも考えましたが、サイズ調整が難しかったので諦めました
- New RelicのiPadアプリもありますが、ちょっと今回の用途には使えない感じの機能でした
HerokuのDyno数は、グラフを表示する機能を使います。CSVファイルを作れば、それを適当にグラフに表示してくれます。本当は24時間分あるのですが、12時間分しか表示されなくて残念。Dyno数は、Mac miniが1時間毎にherokuコマンド経由で数えます。Dropboxで共有されているフォルダにCSVを書き出せば、後は自動でStatus Boardまで繋がります。
Twitterのエゴサーチは、Status Board組み込みの機能。
その他に注意したことと言えば、iOSのアクセスガイドを使っています。アクセスガイドは特定のアプリしか実行できないようにする機能ですが、今回はStatus Boardがクラッシュしたときに自動で再起動するために使っています。
ずっと見ていたわけではないのでクラッシュしたことがあるかどうかはわかりません。アプリがクラッシュするというのは一般的な心配事であって、Status Boardの安定性に関するなんらかの言明ではありません。