2013-01-17

Run rbenv in global

Updated (Feb 13, 2014): Fixed my poor English. And note that I hadn't encountered problem around my global rbenv installation for a year.

When we want to have ruby in a server, sometime we can't use the system's package manager.

Because package managers (in almost distros) serve older Ruby. Plus, they may have weird complex rubygems integration.

So the following are my ideas to get Ruby in your servers:

  • Build packages by ourselves: deb, rpm, ebuild

    • I think helpful when you have many servers, but when not, it might be overkill.
    • Building and maintaining packages are boring stuff.
  • Install ruby by hand: make && make install

    • Difficult to control later. What you do when you want to uninstall ruby?
    • How to upgrade cleanly?
  • Version Managers: Install rbenv, rvm

    • I think this is the bet solution; at least for me.
    • I prefer rbenv because it's made simple. rvm changes many shell behaviors.
    • rbenv is great for installing globally.

So, I'm using rbenv for my servers.

But Ruby is used from many users (including system users, daemons). Normally we install rbenv in ~/.rbenv, but it's depends on user's shell ($PATH) configuration and user's home directory.

Here's how I installed rbenv in global.

Install rbenv and ruby-build

I used /usr/local/rbenv for place rbenv.

sudo -i

cd /usr/local
git clone https://github.com/sstephenson/rbenv rbenv
mkdir -p rbenv/plugins
git clone https://github.com/sstephenson/ruby-build rbenv/plugins/ruby-build

RBENV_ROOT

rbenv looks RBENV_ROOT for many paths. In default (= when not specified), ~/.rbenv is set.

When installed rbenv in /usr/local/rbenv, we should set it to RBENV_ROOT=/usr/local/rbenv.

Install ruby in rbenv by ruby-build

Simply do:

sudo env RBENV_ROOT=/usr/local/rbenv install 1.9.3-p374
sudo env RBENV_ROOT=/usr/local/rbenv rehash

Then, set installed ruby to default ruby:

sudo env RBENV_ROOT=/usr/local/rbenv global 1.9.3-p374

Okay, we've done setup ruby on /usr/local/rbenv/shims/ruby. but, still requires to set $PATH. Let's solve it.

global-rehash

I wrote simple plugin for rbenv: https://github.com/sorah/rbenv-global-rehash

This generates symbolic links and scripts from ${RBENV_ROOT}/shims and ${RBENV_ROOT}/bin into specified directory.

For ${RBENV_ROOT}/bin, this plugin generates script to invoke with suitable $RBENV_ROOT.

But scripts in ${RBENV_ROOT}/shims (generated by rbenv rehash) already contains export RBENV_ROOT, so this script generates symlink for shims.

Install this:

sudo git clone https://github.com/sorah/rbenv-global-rehash /usr/local/rbenv/plugins/rbenv-global-rehash

Then,

sudo env RBENV_ROOT=/usr/local/rbenv rbenv global-rehash /usr/local/bin

Finally you can:

/usr/local/bin/rbenv versions
/usr/local/bin/ruby -v

# RBENV_ROOT will not be required after the first run
sudo rbenv global-rehash /usr/local/bin

Enjoy!

Published at 2013-01-17 22:56:13 +0900 | Permalink
2013-01-04

Renewed this blog

Just released days.gem, the simple blog system built up with Sinatra, and migrated this blog from Lokka.

And, I'll never write Japanese-only article for this blog, please see also http://diary.sorah.jp/ for Japanese entries.

Days

Days is simple blog system built up with Ruby + Sinatra.

This system's big feature is: core separated from deployment.

To set up days and start it, we have to do:

$ gem install days
$ mkdir my_blog
$ cd my_blog
$ days init
$ days migrate
$ days server

by days init, days.gem generates simple Gemfile, config.yml, and config.ru.

But you can customize appearances by placing haml views to views directory.

Core application part is included in days.gem, and it's required by config.ru and gem bundler.

I'm writing tutorial and documentation of days.gem. Stay tuned, please!

Published at 2013-01-04 05:27:50 +0900 | Permalink
2012-12-17

Show warning for RSpec examples that has no expectation

dev

You may sometimes forget to write should for matchers.

it { a == b } # ng
it { a.should == b } # ok

Using the above RSpec configuration, that warns for such cases.

$ rspec -fd spec/a_spec.rb
foo
[WARN] No expectation in example at ./spec/a_spec.rb:4: You may forget to write `should` in the example
  example at ./spec/a_spec.rb:4
Published at 2012-12-17 10:33:05 +0900 | Permalink
2012-11-30

Updating Galaxy Nexus (JP) from stock 4.0 to CM10 with SIM unlocking

Finally got latest Android world.

Before

  • Device: Galaxy Nexus (JP, locked to docomo)
  • Android 4.0.0
  • SIM: SoftBank

    • Unlocked Using F*ckDocomo

Update this to CyanogenMod 10 (Android 4.2.)

Lock again

"Unlock → Lock again." on F*ckDocomo.apk.

Backup /factory/nv_data.bin.

Backup

$ adb backup -f backup.ab -apk -all

Then enter your password on the device.

$ fastboot boot recovery-clockwork-…

Get latest clockworkmod and boot it, then run nandroid backup.

Update

Apply CM10 and gapps zip.

then, reboot and edit backup'd nv_data.bin by seeing this entry.

$ adb push nv_data.bin /sdcard/nv_data.bin # push edited nv_data.bin
$ adb shell
$ su
# mount -o remount,rw -t ext4 /dev/block/mtdblock0 /factory
# cd /factory
# cp /sdcard/nv_data.bin .
# chown radio.radio nv_data.bin
# chmod 700 nv_data.bin
# cp nv_data.bin /data/radio/
# reboot

after reboot, your device is still locked, so:

$ adb shell
$ su
# cat /data/radio/log/nv.log
...
Fri Nov 30 00:44:45 2012: MD5 fail. orignal md5 'aaa' computed md5 'bbb' (rild)
Fri Nov 30 00:44:45 2012: Backup NV restored.(GED)
# mount -o remount,rw -t ext4 /dev/block/mtdblock0 /factory
# cd /factory
# echo -n 'bbb' > nv_data.bin.md5
# chown radio.radio nv_data.bin.md5
# chmod 700 nv_data.bin.md5
# cp nv_data.bin.md5 /data/radio/
# reboot

finally your device is unlocked.

Restore

$ adb restore backup.ab
Published at 2012-11-30 01:11:28 +0900 | Permalink
2012-10-13

rspec-mock broken by `scope :public` in ActiveRecord::Base

dev
class Foo < ActiveRecord::Base
  scope :public, -> { … } # this overrides Module#public
end

class FoosController < ApplicationController
  def create
    @foo = Foo.new(params[:foo])

    respond_to do |format|
      if @foo.save
        format.html { redirect_to @foo, notice: 'foo was successfully created.' }
        format.json { render json: @foo, status: :created, location: @foo }
      else
        format.html { render action: "new" }
        format.json { render json: @foo.errors, status: :unprocessable_entity }
      end
    end
  end
end

describe FoosController do
  describe "POST create" do
    describe "with invalid params" do
      it "re-renders the 'new' template" do
        # rspec-mock expects Foo.public to `Module#public`
        Foo.any_instance.stub(:save).and_return(false)

        post :create, {:foo => {}}, valid_session
        response.should render_template("new")
      end
    end
end

scope :public overrides Module#public method in the model, but rspec-mock expects Foo.public to be Module#public. rspec-mock calls Foo.public with arguments, so it raises ArgumentError on line scope :public. :/

 ArgumentError:
   wrong number of arguments (1 for 0)

こんな感じで scope :public, -> {…} していると、rspec-mock が Module#public(*name) を期待して引数付きで public を呼んで崩壊する模様。

Foo を stub ってるせいでテストがコケるみたいです。

Published at 2012-10-13 01:06:17 +0900 | Permalink
2012-10-08

Pending は邪悪な物であり、邪悪な物を生み出した人間には斧を

そらはーです!

RSpec で pending 使ってテストを一時的に無効化した事ある方は大勢いらっしゃるんじゃないでしょうか!

なんらかの事情で一時的に pending せざるを得ない状況ならともかく、pending したなら責任をもって該当のテストを治すか、そもそも不要なら消すなどといった対処をしてもらいたいものですね!

でも、実際来週までには!とか言っても放置する人間や、そもそも直さず1年,2年以上放置される事もしばしばあるのが現実です………

pending を放置する事によって、実はそれは(他の人にとって)かなり重要なテストで、そんなテストがpendingされてる訳ないと思った、他のメンバーによる変更で実はそのテストがコケて事故っていたという可能性も存在するわけです。

  1. 重要なテストをAさんが pending する (「テストは追って修正する」みたいな感じで)
  2. 比較的大きめの変更を B さんが加える。一応全部テストを回してグリーンな事を確認
  3. (実は重要なテストがAさんによって pending されている事に気づいていない)
  4. 事故っている

本当は pending を使わないのが一番なんですが、やむなく使った場合はちゃんと責任を持って直しましょ… 直せ!!! というわけで、催促するツールを作りました!

Pendaxes

cookpad/pendaxes

pend(ing) axes です! 今のところ rspec をサポートしてます!

メール等でコミットした人に個別で催促メールを送ったりできます!!!!

$ gem install pendaxes
$ cd /path/to/your/git/working/copy
$ pendaxes --init
$ pendaxes
$ open report.html

とりあえず試すには、working copy の中で pendaxes --init を叩くとそのディレクトリで .pendaxes.yml を吐き出すので、そこで pendaxes を実行すると report.html を吐き出します。

後述するメール設定をすると、この report.html のようなメールがコミッター毎にその人のコミットしたpendingがメールで送られると思えば良いです。

(git grep とかを使ってるので git リポジトリと git が必要です)

(Ruby 1.9.2 以降で動きます。それ以前は保証しません)

設定ファイル

https://github.com/cookpad/pendaxes/wiki/Configuration

を参照してください… ちょっと複雑です。以下に一例を載せるので参考にしてください><

メールを送る

notifications に以下のような行を足せば動きます。mail.gemsendmail delivery_method を使って、各コミッターにメールを送信します。

- use: mail
  reporter:
    use: haml
  from: no-reply@example.com
  delivery_method: sendmail

こんなメールが飛びます:

cron で回してみる

cron で回す際は、config.yml に git clone 先と clone 元を指定してあげると pendaxes が pull まで面倒を見てくれて便利です。pendaxes --init で指定付きで生成できます。

$ pendaxes --init config.yml https://github.com/cookpad/pendaxes.git /tmp/pendaxes

で、/tmp/pendaxeshttps://github.com/cookpad/pendaxes.git を clone して自動で git fetchgit reset --hard で最新のコードに更新してくれる config.yml を生成してくれます

$ pendaxes config.yml

で生成した config.yml を実行してくれます。後は同じように config.yml を編集してメール等を送る設定を追加した上で cron で回せばいいと思います。

効果

毎朝6時に cron で回して送るようにしたところ、だいたい放置されていた大量の pending がどんどん数日で消えて行きました! わーい!

…あれ?

Published at 2012-10-08 18:10:37 +0900 | Permalink
2012-10-08

Mac でも MigMix にしてみた

M+ と IPA フォントを合成したフォント、MigMix という物があります。

Nexus 7 ではこのフォントで生活しているんだけど、実際にヒラギノよりこっちの方が好みと気づいたので切り替えてみた。とりあえずChromeとVim等、設定可能なアプリケーションではMigMix を利用するようにした。Vim は MacVim なので :set guifontwide で。

太字がいいですね!

Terminal.app でも日本語とかだけ別フォント設定出来ればいいんだけど。iTerm2 はできたはず。

Published at 2012-10-08 01:45:57 +0900 | Permalink
2012-10-06

rspec-rails は Gemfile で development グループにも入れてあげよう

dev

なんか rspec-rails でテストが生成されないなーと思ってたらこういう事だった。ちゃんとREADME読めっていう話ですね!

https://github.com/rspec/rspec-rails#configure

It needs to be in the :development group to expose generators and rake tasks without having to type RAILS_ENV=test.

group :test, :development do
  gem "rspec-rails"
end
Published at 2012-10-06 18:58:06 +0900 | Permalink
2012-09-22

iPhone 5 (KDDI) を予約したので現在の回線をまとめておく

iPhone 4S (KDDI) の割賦が残っているというのに、iPhone 5 を偶然にも触ってしまって「これは買うしかない」と思って仕事帰りに予約してしまった。

現在の回線とiPhone 5にしたときのプラン予定をメモっておく。

回線一覧

  • au

    • iPhone 4S (7年目)
    • IS01 (約2年目 - 解約するかMNPするか機種変するか悩ましい回線)
  • SoftBank

    • Galaxy Nexus (契約時: Desire HD) + 学割適用による3円運用, 1.5年くらい?
  • docomo

    • BF-01D (データ回線, 6ヶ月目)

au

iPhone 4S

内容 (円)
プランEシンプル1486
誰でも割+家族割-743
学割 (2013/4まで)-372
WEB de 請求書割引-20
iPhone 4S 32GB 分割支払金2570
ユニバーサルサービス料3
合計2924

学割、LTEプランにすると吹っ飛ぶのかなあ。吹っ飛んでもいいけど。

IS01

内容 (円)
プランEシンプル1486
誰でも割+家族割-743
EZ WIN300
毎月割-1023
WEB de 請求書割引-20
ユニバーサルサービス料3
合計3

そろそろ2年目なので、解約するかMNPするか機種変するかで迷います。

SoftBank

内容 (円)
ホワイトプランN934
ホワイト学割 with 家族 2011-934
S!ベーシックパック300
安心保証パック475
月々割-835
ユニバーサルサービス料3
合計3

Desire HDで契約したけど、Galaxy Nexus (docomo) にさして使っています。

docomo

内容 (円)
Xi データプラン フラット にねん4700
moperaU スタンダードプラン500
ケータイ保証お届けサービス280
月々サポート-800
eビリング割引-100
BF-01D 端末等代金分割支払金1365
ユニバーサルサービス料3
合計6177

こちらはデータプランなので音声回線無し。キャンペーン適用中により10月からちょっとたかくなりそう。

合計

9107円

iPhone 5 (KDDI) 予定

内容 (円)
LTE プラン980
LTE NET315
LTE フラット5460
テザリングオプション525
キャンペーン(テザリング 2 年間無料)-525
毎月割-2180
au スマートバリュー-1480
iPhone 5 64GB 分割支払金3430
ユニバーサルサービス料3
合計6528

Xi のモバイルルータとどう両立させるか悩みものですが、近場に行くときもいちいちモバイルルータ持って行かなくて良くなりそうなのでパケット定額入れてみることにしました。

別に使わないときは外せばいいだけだし…

学割吹っ飛ばなければもうちょっと安くいけるんだけどなあ。無理だろうなー

(通信費が合計iPhone 5導入後は12711円になる予定)

Published at 2012-09-22 18:36:31 +0900 | Permalink
2012-09-17

SapporoRubyKaigi 2012

P9146202

札幌Ruby会議2012に参加してきました。スピーカー && 偽スタッフとして。

当然のように凄い楽しかったし、(わたしはお金払ってないけど) やっぱりスタッフの方々 がんばりすぎな気がした。お疲れ様でした、楽しませて頂きました。

初めての札幌で、しかもまさかカンファレンスで来る事になるとは思ってませんでした。 札幌、またきたいですね。居心地良い!

ちなみに、写真はここにあります: http://www.flickr.com/photos/sora_h/sets/72157631550173713/

今回はなんと400枚くらい。

金曜日の午前に10kmほど札幌を練り歩いた観光写真はこちら: http://www.flickr.com/photos/sora_h/sets/72157631551488300/

しかし、まさか tenderlove, miyagawa, matz とかと北海道で沖縄そば食べる事になるとは思わなかったな…

発表の話

Guide to Social Coding という話をしてきた。その前の@tricknotesの発表とややかぶっているのではないかと一瞬ビクッとした。

資料はこちら: https://speakerdeck.com/u/sorah/p/guide-to-social-coding

翻訳の話

ご存じの方は多いと思いますが、主に翻訳に徹していました。

雑談もできるように設置されたIRCサーバーはほぼ翻訳チャンネルしか生きてなかったけど、 IRCでスピーカーの喋ったことをなるべく翻訳するチャンネルがありました。

一応各セッションにスタッフから最低1人はトランスレーターとしてついていましたが、 手助け歓迎という事だったので手助けしていた。当然非公式。 でもスタッフの席に座って電源を借りさせてもらえました。ありがとうございます。偽スタッフです。

まさかあそこまでスムーズに訳せるとは思ってなかったし、スタッフ各位にお礼されました。 お役に立てて光栄です。

とりあえずクオリティに関してはともかく、日本語→英語をひたすらやってました。

英語→日本語は無理ですね。日本語の生成速度より英語の生成速度の方が早い。

あと、日本語を書くときにどうしても「やあおまえら」とかになりがちなので どうなんかなあと思うことも。

全く参考にならないかもしれませんが、これはほぼセッションをちゃんと聞きながら 貢献する事ができる数少ない事だと思っていて、 ついでに英語の意識が高まるので大変良いです。

なんというか、日本語を聞いてそれに対応する英語を高速で構成する練習になります。 おかげで会期中、割とスムーズに英語を喋る事ができましたね。tenderloveとかdrbrainとかと。 try(:english) で喋ったけど予想以上にスムーズに喋れた。ぺらぺらって訳じゃないけど。

まあでも、自分のためにやってるんじゃなくて、非日本語圏の人向けにやっているのは誤解しないで いただきたく思います。

という訳で、もし機会があれば来年はちゃんと翻訳班として参加したいですね。

というわけで、@RubyKaigi2013のオーガナイザーの方々へ: もし気が向いたら翻訳班にお誘いください。お引き受けします!

Published at 2012-09-17 07:48:30 +0900 | Permalink
2012-09-10

Nexus 7

IMG_3095

Nexus 7がきました。かわいい。

サイズ的にも重量的にもちょうど良くて良い感じ。iPad に比べて物足りない感じはあるけど、使いやすい。

iPad もこのサイズでバリエーション持っていいと思うんだけど、開発者としてはリソースが増えると対応が面倒なのでやめて欲しい。

あと、Wi-Fi only の device のくせに地味に GPS が搭載されていてよかった。一番良いと思ったポイント。 /system/etc/gps.conf を調整したほうがいいかなー、どうだろ。

ホーム

Nexus 7 Home

こんな感じになりました。わりとふつう。背景はこれ

やった事

  1. 日本語のフォントが汚い!
  2. adb backup -apk -shared -all (うろ覚え) で途中まで設定した物とアプリをバックアップ
  3. fastboot oem unlock 後 Clockworkmod を fastboot boot でブートしてあげて、SuperSU.zip を flash (保証が飛びます)
  4. adb restore でバックアップから復元
  5. MigMix フォントをとってくる。
  6. adb remount したあと adb push migmix.ttf /system/fonts/ しようとしたけど、adb remount がコケるので /sdcard/ にとりあえず adb push
  7. adb shellsu で root になって

    # mount (/system がどのデバイスファイルからマウントされてるか調べる) # mount -o rw,remount /dev/… /system # cp /sdcard/migmix-regular.ttf /sdcard/migmix-bold.ttf /system/fonts/ # vi /system/etc/fallback_fonts.xml ( の一番下に以下を追記) migmix-regular.ttf migmix-bold.ttf # vi /system/etc/fallback_fonts-ja.xml (同じ事をやる)

  8. adb reboot でリブートする。フォントが綺麗になってることを確認する。終わり。

購入までの流れ

US の IP でがんばる

  1. Nexus 7 は今のところ日本のIPからだと買えない
  2. 変な VPN 使いたくないなぁ。
  3. EC2 micro が無料なので AWS のアカウントを取得して Ubuntu のイメージを us-west とかで立ち上げる
  4. ssh のダイナミックポートフォワーディングで何もしなくても問題なく購入ページが開けました。

転送

ちなみに今回は同僚がまとめて6台購入して、送料を割ってみんなで安くNexus 7を手に入れる試みをしました。

米国日通の転送サービス を使った。6台送りつけたら商用?とかいう扱いにされて若干高くなった。Google Play の送料 + 日通の送料 + 関税 でだいたい一人2000円。

Published at 2012-09-10 23:13:23 +0900 | Permalink
2012-09-09

socket.io で任意のeventを一つのlistenerで受け取る

dev

https://gist.github.com/3683181

無理っぽいのでこういうhackをするしかない。 Eventのinvoke周りは node.js 由来の EventEmitter を使っていて、その emit メソッドをラップして、本物のemitを実際に渡された引数で渡した後、別のeventとしてemitに飛んできた引数をargsとして渡しているだけ。

EventEmitter の emit は $emit に姿を変えていた

しかし socket.io がドキュメント無いのは驚いた。こういう知名度があって便利なライブラリ、わりとドキュメント無いのが多い。ドキュメントが、無い。人のこと言えないけど。

小さいコードなら今回のように自分で読んで解決できるけど、Rails のように巨大なライブラリがドキュメントなかったら絶望(デデドン) だと思う。

利用例

こんなふうに使います。

public domain なのでお好きにどうぞ。

Published at 2012-09-09 16:46:37 +0900 | Permalink