Tag Archives: ruby

4/20のTokyo Rubyist Meetupに行ってきた

4/20のTokyo Rubyist Meetup – After the Earthquakeに行ってきた。Twitterのハッシュタグは#trbmeetup

(あとで書く)


__FILE__と$0

FILE はそのコードが書かれているファイルを指し、$0は起動されたスクリプトを指す。

FILE は実行中のプログラムのファイル名」が詳しい。

先程の記事に載せたgistではこれを利用してサンプルプログラムを末尾に記述している。


コマンドラインアプリ作成にちょっと便利なStringの拡張

githubをうろうろしていたら「なるほど」と思ったコードを見つけたのでメモっておく。

get-twitter-oauth-token / bin / get-twitter-oauth-token (gistじゃないので残念ながら埋め込むことができない。コピペするのも微妙なのでリンクだけ提示しておく)

これは@jugyoさん作のコマンドラインからTwitterのOAuthのアクセストークンと秘密鍵を取得するスクリプトで、openコマンドを使ってるあたり多分Mac専用なんだと思う(Linuxとかでもあるのかな?)。

なるほどなーと思ったのはStringを拡張しているcolorとaskという二つのメソッド。

colorはその名のとおり文字列に色をつけるもので、引数numにはANSIエスケープシーケンス(?)で指定できる色の番号を渡す(「bashのプロンプトに色をつける」などを参照。zshでもいける)。

もうひとつのaskはユーザからの入力を受け付けを表示するもので、レシーバの文字列を印字してから入力された内容を返す。凄く短いメソッドだけど、これひとつだけで可読性が向上するから感動してしまった。

ただこれだとパスワードの入力もみえてしまうので、sttyを使って入力中の文字列を表示しないメソッドもあったほうが便利だと思い、ちょっと書いてみた。

ask_passwordなんて長ったらしいけど、パスワードはそうそう聞くものでもないしまぁいいかな、と。askとcolorはそのまま拝借した。これがあるだけでコマンドラインアプリがちょっと書きやすくなるんじゃないかと思う。


MechanizeをMac OSXにインストール

MechanizeはNokogiriに依存しており、Nokogiriはlibxml2とlibxsltに依存している。 libxml2はhomebrewで提供されているのでそれを利用し、libxsltはソースから入れる。

$ brew install libxml2 # libxml2 v2.7.7
$ wget ftp://xmlsoft.org/libxml2/libxslt-1.1.26.tar.gz
$ tar zxf libxslt-1.1.26.tar.gz
$ cd libxslt-1.1.26
$ ./configure --prefix=/usr/local/Cellar/libxslt/1.1.26 --with-libxml-prefix=/usr/local/Cellar/libxml2/2.7.7
$ make
$ make install
$ gem install nokogiri -- --with-xslt-dir=/usr/local/Cellar/libxslt/1.1.26
$ gem install mechanize

nokogiriのインストール方法についてはNokogiriのチュートリアルが詳しい。


RMagickで枠線を付ける

RMagickを使って画像に枠線を付ける方法。


require 'rubygems'
require 'RMagick'

input  = "/path/to/input" # 元画像
output = "/path/to/output" # 書き出し先
thick = 10 # 枠線の太さ
color = "black"

image = Magick::ImageList.new(input)

# 上下左右にそれぞれborder_widthだけ追加して枠線を描画
image.
  border(thick, thick, border_color).
  write(output)

# 枠線の分だけ元画像を縮小して描画
width = image.first.columns
height = image.first.rows
image.
  resize(width - thick, height - thick).
  border(thick, thick, border_color).
  write(output)

Magick::ImageとMagick::ImageListの違いはまだよくわかってない。


RSpec 1.3でカスタムマッチャ

ある処理で行われるファイルの移動が適切かどうかテストしたかったので、カスタムマッチャを作ってみた。使用したのはRSpec 1.3.1。

目標のspec

lambda { foo }.should move_file(src, dest)

チェックする項目

  1. fooメソッドを実行する前にsrcにファイルが存在することをチェック(事前チェック)
  2. Foo#barを実行した後にsrcにファイルが存在しないことをチェック(事後チェック)
  3. Foo#barを実行した後にdestにファイルが存在することをチェック(事後チェック)
  4. srcとdestのMD5値が一致することをチェック(事後チェック)

(1は要らないかも?)

実際のコード

CustomFileMatchers::MoveFileのmatches?で具体的なテストを実行する。

使い方

describe文のなかでincludeして使う。 ためしにちゃんと判定できているかもspecで書いてみた。 (it文の内容が微妙かもしれない)

まとめ

意外と簡単にできたし、specのコードがコンパクトかつそれだけで意味が通じるようになるのでカスタムマッチャはとても便利。

複数のチェック項目が通って一つの意味を成す場合にとても強力。

change.from.toのように条件の追加をメソッドチェインしたければCustomFileMatchers::MoveFileに引数をインスタンス変数に保存するようなメソッド(changeでいうところのfromやto)を追加して、matches?でそれらをチェックすればいいのだと思われる。

参考資料


watchrでautospecみたいなこと

watchrで更新のあったファイルに対してrspecを実行する方法。

secondlifeさんの記事を読んで、取り急ぎやってみた。

$ gem install watchr
$ gem install ruby-fsevent # Mac OSXの場合
$ gem install rev # Linux/*BSDの場合
$ cd (RAILSアプリのルートディレクトリ)
$ vi spec.watchr
watch('app/(.*)\.rb') { |md| system("ruby script/spec spec/#{md[1]}_spec.rb") }
watch('spec/(.*)_spec\.rb') { |md| system("ruby script/spec #{md[0]}") }
$ watchr spec.watchr

autospecより汎用性があって便利かも。

追記

Rails3だとbundle exec rspecを使うのでこんな感じ?


watch('app/(.*)\.rb') { |md| system("bundle exec rspec spec/#{md[1]}_spec.rb") }
watch('(lib/.*)\.rb') { |md| system("bundle exec rspec spec/#{md[1]}_spec.rb") }
watch('(spec/.*)_spec\.rb') { |md| system("bundle exec rspec #{md[0]}") }

Rubyでクロージャ

こうやればいいのか。

def gen
  x = 0;
  return lambda {
    puts x
    x += 1
  }
end

y1 = gen 
y1.call #=> 0
y1.call #=> 1

y2 = gen
y2.call #=> 0

y1.call #=> 2

jQuery.extend

WEB+DB Press No.60のjQueryに関する記事がとても面白かった。で、jQueryで提供されているextendの使い方を今になって理解してきたのでメモっておく。

jQuery.extendはRubyでいうところのHash#merge!だった。

var foo = { a: 1 }
jQuery.extend(foo, { b: 2 })
//=> { a: 1, b: 2 }
foo
//=>{ a: 1, b: 2 }

なので、次のようにするとハッシュ引数のデフォルト値の設定とかができて便利(Hash#reverse_merge的なこと)。

function foo(args) {
  args = jQuery.extend({ a: 1, b:2 }, args);
    :
}

ついでに、jQuery.extendはオブジェクトのコピーにも使える。ちゃんと見てないけどたぶん浅い。

var foo = { a: 1 }
var bar = jQuery.extend({}, foo)
//=> { a: 1 }

ただしfooはFooのインスタンスだけど、barはObject直下のインスタンス(?)なのでFooをプロトタイプに持たないので要注意(用語がわからないけどこれで合ってるのかな)。


homebrewとrvmをセットアップするスクリプト

Macbook ProとMacbook Airでちまちまと同じ環境を用意するのが面倒になったので、最初の処理をまとめたスクリプトを書いてDropboxで共有するようにした。

個々のgemに関してはbundlerを使ってGemfile(.lock)やプロジェクトごとのvendor/bundleに入れておくことで手軽に共有できるので、とっかかりとしてはこれで十分かなと。

これ以外にも.zshrcや.irbrc、.vimrcもDropboxで共有している。Dropboxは凄く便利なので本当にオススメです。1個でも違う環境が入ったときが面倒かもなぁ

参考資料