2013-04-05

chef-solo を Ruby-2.0.0 で試す —— 例: Objective-C コンパイル環境の用意

Ruby の Gem で chef というのが流行しているらしい。chef は、環境構築を自動化するプログラム。Shell Script を環境構築用に最適化して、スクリプト (レシピと呼ぶらしい) を ruby の文法で書けるようにしたもの、と理解すれば良いかな。

Software Design (ソフトウェア デザイン) 2012年 10月号 [雑誌]
Software Design (ソフトウェア デザイン) 2012年 10月号 [雑誌]
入門Chef Solo - Infrastructure as Code
入門Chef Solo - Infrastructure as Code

先日、Objective-C 用の環境を構築した。忘れないように、chef のレシピに残してみる。

Ruby の環境

rvm で管理している ruby-2.0.0 上で作業する:

$ rvm list

rvm rubies

   ruby-1.9.3-p392 [ i686 ]
=* ruby-2.0.0-p0 [ i686 ]

# => - current
# =* - current && default
#  * - default

chef のインストール

chef は複数のレシピを保持する chef サーバーと、そのクライアントたる chef クライアントの二つから成る。ただ、自分のマシンにレシピを持っておく (もしくは github などに保存しておく) なら chef サーバーは不要。

入門から入りたいので、難しい chef サーバーは使わない。chef クライアントだけ使ってみる。chef クライアントのインストールは次の通り:

$ gem install chef

これで、chef-solo コマンドや knife コマンドという主要コマンドがインストールされる。

format.rb の解決

chef-solo -v でバージョンを見ようとすると、format.rb がないというエラーが出て止まる。Ruby 2.0 になった時に RubyGems のディレクトリー構成が変わったのが原因とのこと。

上記ページがダミーの rubygems/format の作り方を書いているので真似をした:

$ cd ~/my-project
$ bundle gem rubygems-format-dummy
      create  rubygems-format-dummy/Gemfile
      create  rubygems-format-dummy/Rakefile
      create  rubygems-format-dummy/LICENSE.txt
      create  rubygems-format-dummy/README.md
      create  rubygems-format-dummy/.gitignore
      create  rubygems-format-dummy/rubygems-format-dummy.gemspec
      create  rubygems-format-dummy/lib/rubygems/format/dummy.rb
      create  rubygems-format-dummy/lib/rubygems/format/dummy/version.rb
Initializating git repo in /home/ataka/my-project/rubygems-format-dummy
$ cd rubygems-format-dummy
$ touch lib/rubygems/format.rb
$ git add lib/rubygems/format.rb
$ git commit -m 'initial commit'
$ emacs -nw -q rubygems-format-dummy.gemspec
 (TODO とあるところを適当に書き換える)
$ rake install

以上。

もう一度、chef-solo でバージョン確認。

$ chef-solo -v
Chef: 11.4.0

上手くいった。

設定ファイル

まず、knife configure コマンドを実行する。chef-repo 以外は全てデフォールトのままで良いのかな?

$ sudo knife configure -i
sudo: knife: コマンドが見つかりません

ありゃ、knife が見つからない。ああ、PATH の問題か。

$ sudo env PATH=$PATH knife configure -i

chef-repo は /var/chef-solo にした。

chef-solo には 2 つの設定ファイルがある。なくても動くけど、小さな設定ファイルなので書いちゃう。

1 つ目は /var/chef/solo.rb:

file_cache_path "/var/chef-solo"
cookbook_path ["/var/chef-solo/cookbooks"]

キャシュと cookbook の置き場所を指定する。ちなみに cookbook の下に recipe というスクリプトを置く。recipe は後で書く。

2 つ目は /var/chef/node.json:

{
  "run_list": [ "recipe[objc]" ]
}

Recipe を書く

シンプルな Recipe を一つ。

knife コマンドでレシピの用意をする。

$ sudo env PATH=$PATH knife cookbook create tmux
WARNING: No knife configuration file found
** Creating cookbook tmux
** Creating README for cookbook: tmux
** Creating CHANGELOG for cookbook: tmux
** Creating metadata for cookbook: tmux

WARNING が出たけど無視。

/var/chef-solo/cookbooks/tmux/recipes/default.rb に以下のコードを追記:

package "tmux"
  action :install
end

これでインストール・コマンドを行ってくれるはず。

chef-solo でレシピを指定して実行。

$ sudo env PATH=$PATH chef-solo -o tmux
Starting Chef Client, version 11.4.0
[2013-04-05T10:24:49+09:00] WARN: Run List override has been provided.
[2013-04-05T10:24:49+09:00] WARN: Original Run List: []
[2013-04-05T10:24:49+09:00] WARN: Overridden Run List: [recipe[tmux]]
Compiling Cookbooks...
Converging 1 resources
Recipe: tmux::default
  * package[tmux] action install
    - install version 1.6-2 of package tmux

Chef Client finished, 1 resources updated

成功。

Objective-C の開発環境構築

過去記事を参考に... 基本、必要なパッケージさえインストールすればいいだけ。

knife コマンドで objc レシピを作る。

$ sudo env PATH=$PATH knife cookbook create objc

/var/chef-solo/cookbooks/objc/recipes/default.rb に追記。


%w{build-essential gobjc libgnustep-base-dev gnustep gnustep-devel}.each do |pkg|
  package pkg do
    action :install
  end
end

Ruby の文法を使えるのがありがたい。

インストール。今回、node.json をちゃんと書いているので、そちらを指定する。

$ sudo env PATH=$PATH chef-solo -j /etc/chef/node.json
Starting Chef Client, version 11.4.0
Compiling Cookbooks...
Converging 5 resources
Recipe: objc::default
  * package[build-essential] action install (up to date)
  * package[gobjc] action install
    - install version 4:4.7.2-1ubuntu2 of package gobjc

  * package[libgnustep-base-dev] action install
    - install version 1.22.1-4ubuntu1 of package libgnustep-base-dev

  * package[gnustep] action install  
    - install version 7.7 of package gnustep

  * package[gnustep-devel] action install
    - install version 7.7 of package gnustep-devel

Chef Client finished, 4 resources updated

成功。システム全体のレシピを扱う場合は node.json に複数のレシピ (今回は一つだけだったけど) を書いて -j オプションで指定。レシピを選択して実行する場合は、-o オプションでレシピ名を指定する。

あとがき

今回はインストールだけだったけど、chef を使えば /etc ディレクトリー下のファイルを環境に応じて作成したり (template)、ユーザーやグループを作成したりできる。

最後に感想。knife configure が、ちと分からない。chef は日々進化しているようなので、最新の情報を探すのが大変だった。はたして、この情報もどれ位い最新に沿ったものなのか...

2013-04-03

小さな Objective-C コードを書いてみた

最初の敗北: Object 編

Objective-C入門を一読して、小さな Objective-C のソースコードを書いてみた。以下の通り:

#import <objc/Object.h>
#import <stdio.h>

@interface Point : Object
{
        int x;
}
-(id) setX :(int)x;
-(int) getX;
@end

@implementation Point
-(id) setX :(int)x
{
  self->x = x;
  return self;
}
-(int) getX {
  return x;
}
@end

int main(void)
{
  id point = [Point alloc];
  [point setX: 10];
  printf("Point X is %d\n.", [point getX]);

  return 0;
}

このコードを前エントリーの Makefile (必要部分だけ抜粋) を使ってコンパイル。

#
# Makefile for hello
#
TARGET = hello

OBJC = gcc
OBJCFLAGS = -W -Wall
LIB = -lobjc

all: $(TARGET)

$(TARGET): main.o
 $(OBJC) $(OBJCFLAGS) $^ $(LIB) -o $@

%.o: %.m
 $(OBJC) $(OBJCFLAGS) -c $< -o $@

実行結果は次の通り。Warning は出ているけど、エラーは出てない。

$ LANG=C make -k
gcc -g -W -Wall -c main.m -o main.o
main.m: In function '-[Point setX:]':
main.m:15:3: warning: local declaration of 'x' hides instance variable [enabled by default]
main.m: In function 'main':
main.m:25:3: warning: 'Point' may not respond to '+alloc' [enabled by default]
main.m:25:3: warning: (Messages without a matching method signature [enabled by default]
main.m:25:3: warning: will be assumed to return 'id' and accept [enabled by default]
main.m:25:3: warning: '...' as arguments.) [enabled by default]
gcc -g -W -Wall main.o -lobjc -o hello

Compilation finished at Wed Apr  3 12:15:28

で、これを実行すると失敗。

$ ./hello
Segmentation fault (コアダンプ)

次のトライ: NSObject 編

色々試して行き詰まったので、Ubuntu LinuxでObjective-C - Tomute’s Notes の記事を参考に NSObject を使う方向に方針転換。

インストール

NSObject を使うためのインストールを実行

$ sudo apt-get install libgnustep-base-dev
$ sudo apt-get install gnustep
$ sudo apt-get install gnustep-devel
Makefile の編集

OBJCFLAGSLIBS に NSObject 用の設定を追記。面倒なので全部コピペしちゃう。

#
# Makefile for hello
#
TARGET = hello

OBJC = gcc
OBJCFLAGS = -I/usr/include/GNUstep -fconstant-string-class=NSConstantString -W -Wall
LIB = -lobjc -lgnustep-base

all: $(TARGET)

$(TARGET): main.o
 $(OBJC) $(OBJCFLAGS) $^ $(LIB) -o $@

%.o: %.m
 $(OBJC) $(OBJCFLAGS) -c $< -o $@

#
# clean
#
RM = rm -f

clean:
 $(RM) *~
 $(RM) *.o
distclean: clean
 $(RM) $(TARGET)

ソースコードの編集

こちらの変更は小さい。#import <objc/Object.h>#import <Foundation/NSObject.h> に変えて、スーパークラス ObjectNSObject に変更する。

これでコンパイルが通るはず... と思ったら、setX メソッドでエラー。

self->x = x;

このコードがインスタンス変数 x を遮蔽しているという。Object を使った時にも同じ文言が出たけど、その時は「エラー」じゃなくて「警告」だったのに... 何故?

とりあえず、ベタな修正をかけて、ハイ完成。

#import <Foundation/NSObject.h>
#import <stdio.h>

@interface Point : NSObject
{
  int x;
}
-(id) setX :(int)x_;
-(int) getX;
@end

@implementation Point
-(id) setX :(int)x_
{
  x = x_;
  return self;
}
-(int) getX {
  return x;
}
@end

int main(void)
{
  id point = [Point alloc];
  [point setX: 10];
  printf("Point X is %d\n.", [point getX]);

  return 0;
}

これでコンパイルして実行すると、めでたし Objective-C のプログラムが実行できた。

$ ./hello
Point X is 10

あとがき

もしかして、Object を使ってた時も self がいけなかったんじゃないかと、NSObject と同じ様にコードを修正してみたものの、再び Segmentation fault になった。何故? 何が足りないの?

あと、self は使えないの? 色々悶々と悩みながら Objective-C のプログラミングを勉強中。ああ、なんか釈然としない。

初めての Objective-C (in Ubuntu Linux)

MacBook Air を注文したことだし、Objective-C のプログラミングでもやってみようかと手を出した。コンパイル環境は Ubuntu Linux 12.10 (MacBook Air はまだ届いていない)。基本、C の拡張ということで甘く見てた。そして一手目からコケた。

  • 拡張子は何?
  • コンパイラーは何?
  • Makefile はどう書くの?
  • 必要なライブラリーは?

Hello, World を出力するまでを記事にする。

インストール

libc6-dev をインストールするために build-essential パッケージを、Objective-C 用のライブラリーをインストールするために gobjc パッケージをインストールする。

$ sudo apt-get install build-essential
$ sudo apt-get install gobjc

ソースコード

  • #include の代わりに #import を使う
  • Objective-C では objc/Object.h のインポートが必須 (Cocoa 開発の場合を除く)

#import は #include と違って二重読み込みをしない仕様とのこと。

Hello, World を出力するプログラムはこちら。

#import <objc/Object.h>
#import <stdio.h>

int main(void)
{
  printf("Hello, World!\n");

  return 0;
}

main 文の引数を空にすべきか、void にすべきか悩む... ANSI C の上位互換なら void にすべきか? これを拡張子 .m で保存する。

Makefile

GNU Makefile では、Objective-C をデフォールトでサポートしていないのね。implicit variables や implicit rules が使えなくて驚いた。

Objective-C のコンパイラーは gcc を使えば良いらしいけど、変数名を CCC とするか OBJC にするか二通りの流儀があるらしい。CCC は昔、C++ のコンパイラー変数として使われていたこともあるので、後者を選ぶ。

必須ライブラリー objc を呼ぶことを忘れずに書いた Makefile (最小) は以下の通り:

#
# Makefile for hello
#
TARGET = hello

OBJC = gcc
OBJCFLAGS = -W -Wall
LIB = -lobjc

all: $(TARGET)

$(TARGET): main.o
 $(OBJC) $(OBJCFLAGS) $^ $(LIB) -o $@

%.o: %.m
 $(OBJC) $(OBJCFLAGS) -c $< -o $@

#
# clean
#
RM = rm -f

clean:
 $(RM) *~
 $(RM) *.o
distclean: clean
 $(RM) $(TARGET)

最後に make コマンド実行でコンパイル終了。

$ make
gcc -W -Wall -c main.m -o main.o
gcc -W -Wall main.o -lobjc -o hello

あとがき

今回のコードは、Objective-C のコードを一行も書いていない。C のソースコードを、Objective-C のやり方に則ってコンパイルしただけ。まだまだ勉強することは多い。

調べてると、Objective-C++ とか Objective-C 2.0 とか言語が進化してるし、gcc は事実上 GNUstep 専用と化し、Mac では LLVM ベースにシフトしているとか。一歩一歩勉強しよ。

参考記事

2013-04-02

Ubuntu Linux 12.10 で nvidia-settings

Ubuntu Linux 12.10 で nvidia-settings を実行したところ、設定を保存するはずのファイル /etc/X11/xorg.conf が見当たらなくて困ったのでメモ。

  1. sudo nvidia-settings で設定を行なう
  2. nvidia-settings Configuration タブから「Save Current Configuration」を選ぶ
  3. /root 以下の .nvdia-settings-rc に保存するようデフォールトで選定されているので、そのまま「OK」する

以上。Linux を再起動すると、ちゃんと nvidia-settings の設定が保存されていた。/etc/X11/xorg.conf も自動的に作られていた。

何だか分からないけど、解決なのかな?

古いやり方をしている様ならご指摘賜わりたい。

2013-03-28

MacBook Air 11 インチを注文した

会社に入ったら MacBook Air を買うんだ〜、と twitter につぶやいて数か月。遂に可愛いい MacBook と別れる決意をした。

前回は Apple Store で購入したので、キーボード交換くらいしかスペック変更できなかったけど、今回はなるべくスペックを高くした。MacBook は後でメモリー増設したり、ストレージが足りなくなってアップアップになったりしたけれども、もうその愚は犯さない。

目的は二つ。ブロガー・ミーティングのために持ち歩く。多少の開発マシンとしても使用する。MacBook は重くて辛かったので、ディスプレイ・サイズが小さくとも軽量でコンパクトな 11 インチ・モデルを選択。その上で、開発もやりたいのでスペックは高めに。本当に開発するなら、Pro なんだろうけど、Pro は重いのよね。

購入スペックは以下の通り (青字は変更部分):

  • ディスプレイ: 11.6 インチ (1366 x 768)
  • ストレージ: 256 GB SSD
  • CPU: 2.0 GHz (Dual Core) Intel Core i7
  • メモリー: 8 GB 1,600 MHz DDR3L SDRAM
  • 高さ: 0.3〜1.7 cm
  • 幅: 30 cm
  • 奥行き: 19.2 cm
  • 重さ: 1.08 kg
  • グラフィックス: Intel HD Graphics 4000
  • カメラ: 720p FaceTime HD カメラ
  • USB 3.0 ポート x2
  • Thunderbolt ポート x1
  • MagSafe 2 電源ポート
  • 802.11n Wi-Fi ネットワーク, IEEE 802.11a/b/g 対応
  • Bluetooth 4.0
  • キーボード: バックライト・キーボード (US)

しめて 134,857 円也。

あとがき

前の MacBook は 159,800 円してたから、安くなったなぁ。しかも、MacBook Air だってのに。初代 MacBook Air の高嶺の花さときたら、もう。泣きたくなっちゃう。今回、唯一ダウングレードしたのはディスプレイ・サイズだけ。それでも画面サイズは 1280 x 800 から 1366 x 768 になってるので徴妙に広がってる。

昨夜、注文。お届け予定日は 2013-03-31 から 2013-04-04。来週がワクワク。

カスタムしないなら、Amazon で買っちゃうのも手かもね。ちょっと安い。

APPLE MacBook Air 1.7GHz Core i5/11.6/4GB/128GB MD224J/A
APPLE MacBook Air 1.7GHz Core i5/11.6/4GB/128GB MD224J/A

ちなみに、Apple 45W MagSafe 2 電源アダプタ for Macbook Air (6,475 円) も注文した。こちらは出荷に 3-4 週間かかるとのこと。最短で 2013-04-18。こっちは気長に待つ。

Redmine で別サーバーにある git リポジトリーを参照する

Redmine はローカル・マシンにあるリポジトリーしか参照できない。なので、Redmine 用のサーバーとリポジトリー用のサーバーを分けて運用している場合、チケットとコミット・ログを紐付けることができない。

これは不便なので、公開リポジトリーに commit したら Redmine サーバーにデータを転送するようにした。

なお、掲題の通り今回は git リポジトリーを扱う。

設定

Redmine を動かしているサーバーを server_redmine と呼ぶ。

Git の公開リポジトリーを置いているサーバーを server_git と呼ぶ。リポジトリーは /var/git/sample.git にあるとする。

ssh ログインの準備

server_git から server_redmine へ ssh ログインできる様に設定をしておく。

server_git で上 ssh 鍵を作り、server_redmine へ公開鍵をコピーする。

server_git ~$ ssk-keygen -t rsa
server_git ~$ ls .ssh/
id_rsa id_rsa.pub
server_git ~$ scp .ssh/id_rsa.pub server_redmine:~/
server_git ~$ ssh server_redmine
server_redmine ~$ mkdir .ssh
server_redmine ~$ chmod 700 .ssh
server_redmine ~$ touch .ssh/authorized_keys
server_redmine ~$ chmod 600 .ssh/authorized_keys
server_redmine ~$ cat id_rsa.pub >> .ssh/authorized_keys
server_redmine ~$ rm id_rsa.pub
server_redmine ~$ exit

以上で設定は終了。ssh ログインできれば成功。

server_git ~$ ssh server_redmine
server_redmine ~$ hostname
server_redmine

git repository のコピー

まずは、server_redmine に server_git の git リポジトリーを clone する。

server_redmine ~$ cd /var/git/
server_redmine /var/git$ git clone --mirror ssh:server_git:/var/git/example.git

--bare--mirror の違いがいま一つ分かっていないけれども、--mirror の方が今回の用途に合っていそう。

なお、この作業には server_redmine から server_git へ ssh ログインできることが前提になっている。もし出来ない場合は、上の server_git から server_redmine へ ssh ログインする設定をもう一度、逆方向にして欲しい。

ここまでで、server_git にある最新の git リポジトリーを server_redmine に持って来れた。けれど、今のままでは server_git のリポジトリーにコミットされた内容が server_redmine 側に反映されない。

hooks/update の利用

たいていのバージョン・コントロールには hook という機能がある。コミット直前に何かするとか、コミット直後に何かするとか、そういう機能。

git にも hook 機能があるので、それを使う。今回使うのは post-update フック。

post-update は、全てのコミットが公開リポジトリーに push された後に実行されるフック。server_git 内の /var/git/example.git/hooks/post-update を編集する。中身は次の通り:

#!/bin/sh
#
# An example hook script to prepare a packed repository for use over
# dumb transports.
#
# To enable this hook, rename this file to "post-update".

# exec git update-server-info
ssh -t -t server_redmine <<EOF
 cd /var/git/example.git
 git fetch --all
 exit
EOF

server_redmine に ssh ログインして、git fetch している。git の公開リポジトリーから redmine 側のリポジトリーに push できれば話は簡単なのだけど、「公開リポジトリー (--bare 付きで作ったリポジトリー)」からは git push できない制約がある。仕方がないので、server_redmine 側に移って git fetch している。

ファイルを作ったら、実行権限を付けるのを忘れずに。

server_git ~$ chmod +x /var/git/example.git/hooks/post-update

あとがき

他サーバーにある git repository を同期する手段には、cron を使って定期的に git fetch (or git pull) する方法もある。この方法の欠点は、git push 後、Redmine にデータが同期するまでにタイムラグが出来ること。また、git repository が更新されていなくても、git fetch が実行されてしまうこと。

hook を使えば、誰かが git push したら、自動的に Redmine 側の git repository に反映される。タイムラグもないし無駄な git fetch も発生しない。ぼくは、こちらの方法を好む。

2013-03-27

Android のバージョンとその分布 —— 自分用まとめ 2013/02

2013-03-06 の Engadget に Android のバージョン分布に関する記事が載っていた。Android はバージョンがごっちゃになって、既にぼくの頭の中で混乱の渦を描いている。この記事を参考に自分用のまとめを書いておく。

Android の歴史

基本、バージョン番号順に並べた。そのため、リリース日が前後している行がある (Froyo 2.3.3/2011-02-09 と Gingerbread 2.3/2010-12-06)。また、Android は 2 系がモバイル用、3 系がタブレット向けに分かれたので、その点も考慮に入れて作表した。モバイル/タブレットの統合はバージョン 4 の Ice Cream Sandwich 以降で行なわれている。

バージョンリリースモバイルリリースタブレット
1.02008-09-23——x
1.12009-02-09——
1.52009-04-30Cupcake
1.62009-09-15Donut
2.02009-10-26EclairHoneycomb
2.0.12009-12-03
2.12010-01-12
2.22010-05-21Froyo
2.2.12010-09-10
2.2.22011-01-22
2.32010-12-06Gingerbread
2.3.12011-01-26
2.3.22010-12-16
2.3.32011-02-09
3.02011-02-22
2.3.42011-04-28
3.12011-05-10
3.22011-07-15
2.3.52011-07-25
2.3.62011-09-02
2.3.72011-09-20
3.2.12011-09-20
3.2.22011-08-30
4.02011-10-18Ice Cream Sandwich
4.0.12011-11-14
4.0.22011-11-29
4.0.32011-12-16
4.0.42012-03-28
4.12012-06-27Jelly Beans
4.1.12012-07-10
4.1.22011-10-09
4.22012-11-13
4.2.12012-11-28
5.02013-XX-XXKey Lime Pie

API 番号とバージョン番号の対応は次の通り:

APIバージョンコードネーム
11.0——
21.1——
31.5Cupcake
41.6Donut
52.0Eclair
62.0.1
72.1
82.2Froyo
92.3 - 2.3.2Gingerbread
102.3.3 - 2.3.7
113.0Honeycomb
123.1
133.2
144.0 - 4.0.2Ice Cream Sandwich
154.0.3 - 4.0.4
164.1Jelly Beans
174.2

バージョン分布

上のデータが頭に入ってなくて、バージョン分布がよく分かっていなかったんだよね。Engadget のデータを転載する。上位 5 つを赤字で書いた。

バージョンコードネームAPI利用率
1.6Donut40.2%
2.1Eclair71.9%
2.2Froyo87.6%
2.3 - 2.3.2Gingerbread90.2%
2.3.3 - 2.3.71044%
3.1Honeycomb120.3%
3.2130.9%
4.0.3 - 4.0.4Ice Cream Sandwich1528.6%
4.1Jelly Bean1614.9%
4.2171.6%

このデータは Google の発表による。

Google が Android 開発者向けのプラットフォームバージョン分布データを更新しました。2013年3月4日までの14日間に Google Play にアクセスした端末を集計した最新データ

Androidのバージョン分布、4.x系が45%に達し Gingerbread (2.3)を追い越す - Engadget Japanese より引用

Google の発表なので、全世界でのデータかな? 日本でのデータではないよね? 一応、バージョン 4 系が 45.1%。Android 2.3.X の Gingerbread が 44.2%。僅差の勝利。第三勢力に Froyo 7.6% がしぶとく残ってる。タブレット専用の Honeycomb は 1.2%。ほとんど普及しなかったのね。

日本だけだと、まだ Gingerbread が多そうな気もする。Nexus 4 もまだ発売されてないしね (ないよね?)。誰か日本限定のデータを出してくれないかしらん。

2013-03-21

Rails の Exception Notification で例外を Gmail 通知させてみた

Ruby on Rails のアプリで例外が発生したらメールでお知らせを受け取りたい。exception_notification という gem を使うと可能になるというので、設定してみた。

exception_notification の設定

Gem install

Gemfile に次の一行を追記して、bundle install を実行する。

gem 'exception_notification', :require => 'exception_notifier'

作者の Sebastian Martinez 氏から、最新版の exception_notification なら「:require => 'exception_notifier'」の記述はいらないよ、とコメントをもらった [Thank you, Sebastian]。

gem 'exception_notification'

メールを送付するための Action Mailer の gem も自動でインストールされるので助かる。

設定

config/environments/development.rb にメール送付の設定を書く。上手く行ったら、config/environments/production.rb にコピー。

  # Exception Notification
  config.middleware.use ExceptionNotifier,
    :email_prefix => "[プロジェクト名] ",
    :sender_address => %{"notifier" <notifier@example.com>},
    :exception_recipients => %w{exceptions@example.com}

エラーが出たら、メールを送りたい。でも、とりあえずメール設定は後回しにしたいので、ターミナルに出力させてみる。次の一行を config/environments/development.rb に追記。

  config.action_mailer.delivery_method = :test
例外のコード

手元に例外を出すコードがなかったので、ちょっと強引に行く。Ruby on Rails Guides のブログ・アプリで新規作成ページに行ったら例外を出す、本当に強引なコード。

app/controllers/posts_controller.rbdef new に次の様に例外発生コードを挿入。

  def new
    raise "exception sample"
...
例外を出す

さて、ブラウザーを起動して「新規作成」ページへ。例外が発生するはず。xterm にはこんな文章が出てくれば OK。

Sent mail to exceptions@example.com (7ms)
Date: Thu, 21 Mar 2013 11:59:53 +0900
From: notifier <notifier@example.com>
To: exceptions@example.com
Message-ID: <514a77a971208_16764fb37dc647a@localhost.mail>
Subject: [Try-RoR] posts#new (RuntimeError) "exception sample"
Mime-Version: 1.0
Content-Type: text/plain;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

A RuntimeError occurred in posts#new:

  exception sample
  app/controllers/posts_controller.rb:31:in `new'

...

Gmail 設定

Action Mailer の設定を config/environments/development.rb もしくは config/environments/production.rb に書く。先に書いた terminal に例外情報を出力するコードはコメント・アウトする。

  # Action Mailer for Gmail
  #  config.action_mailer.delivery_method = :test
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    :address => 'smtp.gmail.com',
    :port => 587,
    :domain => 'gmail.com',
    :user_name => 'your_account@gmail.com',
    :password => 'your_password',
    :enable_starttls_auto => true
  }

これで例外を発生させて Gmail からメールが届けば成功。

わざと例外を発生させてる人は、そのコードを削除してお終い。

あとがき

Rails2 時代と比べて、SSL 関連の設定が楽になってて幸せだった。Action Mailer の SMTP を Gmail ではなく Yahoo! Mail (yahoo.com の方) を使いたかったけど、上手くいかなかった。同じ様な設定で行けるはずなんだけど...

そうそう、自分のサーバーからメールを送る時は postfix あたりを使うと良いらしい。暇が出来たら試してみたいね。

$ sudo apt-get install postfix
config.action_mailer.delivery_method = :sendmail

ref

rvm でデフォールトの ruby のバージョンを指定する

rvm で ruby の 1.9.3 と 2.0.0 を入れている。現在、デフォールトが 1.9.3 なのだけど、メインに使っているのは 2.0.0。毎朝、rvm で ruby のバージョン切替を行なうのが面倒になったので、デフォールトの ruby version を 2.0.0 に変更した。

現状

$ rvm list

rvm rubies

=> ruby-1.9.3-p392 [ i686 ]
   ruby-2.0.0-p0 [ i686 ]

# Default ruby not set. Try 'rvm alias create default <ruby>'.

# => - current
# =* - current && default
#  * - default


$ rvm use 2.0.0
Using /home/ataka/.rvm/gems/ruby-2.0.0-p0
$ rvm current
ruby-2.0.0-p0

rvm list で利用可能な ruby の一覧を表示。

rvm current で現在利用中の ruby を表示。

デフォールトの変更

デフォールトの変更は --default オプションを付ける。

$ rvm use 2.0.0-p0 --default

あとがき

これで明日以降、面倒や変なトラブルに悩まされなくなるはず。

会社とこのブログの立ち位置について

アクトインディ株式会社に入社した。一つ、このブログと会社との関係について書いておく。

ぼくのブログ (clmemo@aka 及び life@aka) は、安宅個人の主張・意見・表現の場であって、安宅が所属する会社の意見を代表するものではない。

ブログを書き始めてもう 8 年。ブログを書くということは、ぼくに生活に大きな位置をしめる。極端な書き方をすれば、ぼくのブログは、ぼくのブランドであり、ぼくにとってのもう一つの会社のようなもの。

ぼくは、このブログで偏った情報を流さない様にしてきたつもり。そのスタンスはぼくのブログの在り方であり、ぼくの誇りでもある。だから、会社に所属したからと言って、会社に偏った情報を書くつもりはない。会社の意見を代表するつもりもないし、そんな権利は最初から持っていない。

上に、このブログを「会社」の様なものと書いた。ぼくがブログを書く時は、「安宅のブログ」という会社の社員として文章をつづっている、とも言える。アクトインディはそういう意味では別の会社であり、他社の企業秘密を漏らしたり、一つの会社を持ち上げたり、また一つの会社を誹謗中傷することはない。「安宅のブログ」のポリシーとして、ステルス・マーケティングを行なうこともしない。

その上で一筆。自分が所属する会社は、やはりぼくの生活の一部なので、関連する記事はやはり増える。しかし、ぼくがブログを書くスタンスは上記の通り。そして、ぼくのブログの立ち位置もそのスタンスの上に立っている。