0

args_parserを使うとRubyでコマンドラインアプリ作るのにとても便利

args_parserというgemを作りました。
2年前に作ったArgsParserをバージョンアップしていたら互換性が無くなってきたので名前を変えた。
optparseよりもすっきり書けると思う。


■インストール

gem install args_parser


■使い方
試しに、「webページのURLを指定してダウンロードする」アプリを作ってみる。
こういう風に使えるのを作る。
ruby download_webpage.rb -url http://example.com -o out.html


download_webpage.rb
#!/usr/bin/env ruby
require 'rubygems'
require 'args_parser'

parser = ArgsParser.parse ARGV do
arg :url, 'URL', :alias => :u
arg :output, 'output file', :alias => :o, :default => 'out.html'
arg :verbose, 'verbose mode'
arg :help, 'show help', :alias => :h
end

if parser.has_option? :help or !parser.has_param?(:url, :output)
STDERR.puts parser.help
STDERR.puts "e.g. ruby #{$0} -url http://example.com -o out.html"
exit 1
end

require 'open-uri'
puts 'download..' if parser[:verbose]
data = open(parser[:url]).read
puts data if parser[:verbose]

open(parser[:output], 'w+') do |f|
f.write data
end
puts "saved! => #{parser[:output]}"


こんな感じで実行できる。

2

\r\nのファイルが混じっているので\nに直すワンライナー

newgemで生成したgemのテンプレートに改行コードが\r\nのものと\nのものが混じっているのが気持ち悪いので、全部\nに統一した。

find * | xargs -n1 ruby -e 'lines = open(ARGV[0]).read.gsub(/\r\n/, "\n"); open(ARGV[0],"w+").write lines'

実行したディレクトリの中のファイルの改行コードが\nになる。

0

Bundler.requireがエラー出すので、プロジェクトローカルにgemを入れた

とある環境でbundle installしてsystemにインストールされたrubygemを使う様にしたら、Bundler.requireがエラー出すようになった。

bundler-1.1.3/lib/bundler/runtime.rb:77:in `require': private method `gsub' called for nil:NilClass (NoMethodError)


プロジェクトローカルにインストールしたらエラーが出なくなった。
bundle install --path gems


■Bundler
最近はbundlerというgemの管理機構が使われている。

Gemfileというテキストファイルを作って、プロジェクトで使用するRubygemsを書いておく。

Gemfile
source :rubygems

gem 'sinatra', '>=1.3'
gem 'twitter'
gem 'oauth', '0.4.5'
gem 'json'
バージョン指定ができる。

bundle install
rubygemsに公開されていないgitリポジトリを指定したりもできるし、一発で全てのgemがインストールできるので開発環境から本番環境にデプロイするのに便利。
メジャーバージョンアップで仕様が大きく変わったgemがあっても問題ない。


require 'rubygems'
require 'bundler/setup'
Bundler.require
require 'yaml'
これでGemfileに書かれたgemがrequireされる。
yamlみたいな標準で入ってるgemは自分でrequireしないとならないっぽい。

0

簡単なon memory cacheを作った

tmp_cacheというgemを作った。


■インストール

gem install tmp_cache


■使い方
cacheなので、memcacheのように有効期限を指定できる。
60秒間生きるキャッシュの場合、61秒後はnilになる
#!/usr/bin/env ruby
require 'rubygems'
require 'tmp_cache'

TmpCache.set('name', 'shokai', 60) # expire 60 sec

puts TmpCache.get('name') # => 'shokai'
sleep 61
puts TmpCache.get('name') # => nil
TmpCacheはグローバルにどこからでも読めるので便利


■利用例
skype-chat-gatewayや、Herokuで秋月電子のRSSを作るで使ってる。

skype-chat-gatewayにHTTPアクセスがあるたびに、何百回もAppleScriptを呼び出してSkype.appと通信させるとひどいことになるのでcacheさせている。
秋月のほうも、新着商品の個別ページ100個以上を見に行っているのでcacheを使わなければ大迷惑になってしまう。
Herokuは無料でmemcachedが使えるけどそれだけの為に(無料なのに)クレジットカードを登録するの嫌だし。



例えば、webページを読みに行くのを1200秒cacheする場合はこんなふうにする。
#/usr/bin/env ruby                                                                                                                                                           
require 'rubygems'
require 'open-uri'
require 'tmp_cache'

def get_page(url, expire=1200)
TmpCache.get(url) || TmpCache.set(url, open(url).read, expire)
end

url = 'http://shokai.org'

puts get_page(url)

puts get_page(url) # 2回目はcacheから読まれる

0

UTF-8-MACをUTF-8に変換する

Twitterをterminalで見ていると、ごく稀に変な文字が入っているtweetがあって、それがUTF-8-MACだとgeta6に教わった。
Macだと「ぱぴぷぺぽ」など一部の日本語をファイル名にすると変な事が起こるのだが、それの原因がUTF-8-MACらしい。

そういう文字をDBに保存するとのちのち良くないので、Rubyで変換した。
Iconv使ったら簡単だった。


■例

touch ぱぴぷぺぽ
echo は<309a>ひ<309a>ふ<309a>へ<309a>ほ<309a>
となる。


ただし、TerminalやiTerm2で「ぱぴぷぺぽ」をechoやlsしてもふつうに「ぱぴぷぺぽ」になってしまって、Rubyに渡して変換を試せない。
GNU Screen上でechoやlsするとUTF-8-MACの文字を出力できる。

■Rubyで変換
インストール
brew install iconv
gem install iconv


標準入力を全て普通のUTF-8に変換する
convert-macutf.rb
require 'rubygems'
require 'iconv'

ARGF.each do |line|
puts line
puts Iconv.iconv("UTF-8", "UTF-8-MAC", line)
end


screen起動してから
touch ぱぴぷぺぽ
ls | ruby -Ku convert-macutf.rb
結果
convert-macutf.rb
convert-macutf.rb
ぱÿぴÿぷÿぺÿぽÿ
ぱぴぷぺぽ



iconv単体で使う時はこう
ls | iconv -f UTF-8-MAC -t UTF-8