query: tag:tips

Pryで過去の実行結果にアクセスするには、_out_ 変数を配列のように使うことができます。

ruby>>
[1] pry(main)> "Hello, " + "world!"
=> "Hello, world!"
[2] pry(main)> out[1]
=> "Hello, world!"
[3] pry(main)> out[-1]
=> "Hello, world!"
<<--

同様に、_in_ 変数を配列のように使って入力文字列にアクセスできるようです。

ruby>>
[6] pry(main)> in[1]
=> ""Hello, " + "world!"\n"
<<--

posted by genki genki on Tue 6 Mar 2012 at 11:32 with 0 comments

Xcodeのバージョンアップをしてから、/Developer ディレクトリがなくなり
/Applicationsの下に引っ越したようなので、
xcodebuildコマンドが動かなくなりました。

pre>>
Error: No developer directory found at /Developer. Run /usr/bin/xcode-select to up
date the developer directory path.
<<--

xcode-selectコマンドで新しい場所を教えて上げる必要があるようです。

pre>>
xcode-select -switch /Applications/Xcode.app
<<--

これでok.

posted by genki genki on Mon 27 Feb 2012 at 16:42 with 0 comments

.rvmrc ファイルを置いておくと自動的に使用するRubyのバージョンを切り替えられるので便利ですが、デプロイ先で利用する場合に毎回 .rvmrc を信頼するか Yes/No? と聞かれるのが自動化と相性が良くないので、

pre>>
% cd /path/to/.rvmrc
% rvm rvmrc trust
<<--

しておくとその後何も聞かれなくなります。

posted by genki genki on Tue 13 Dec 2011 at 09:10 with 0 comments

バックグラウンドジョブの一覧は

pre>>
% jobs
<<--

で得ることができますが、そのままではPIDがわかりません。

pre>>
% jobs -p
<<--

とやると PID を含めた結果が得られます。

posted by genki genki on Wed 26 Oct 2011 at 02:40 with 0 comments

以下のようにメソッド引数のデフォルト値を設定すれば、
呼び出す時に省略することができます。

ruby>>
def foo(a = nil)
a
end

foo #=> nil
foo("test") => "test"
<<--

では、引数が省略されたかどうか判別するにはどうすればいいでしょうか。
以下のようにすれば判別が可能です。

ruby>>
def foo(a = (a_default = true) && nil)
[a,a_default]
end

foo #=> [nil, true]
foo("test") #=> ["test", nil]
<<--

Rubyの引数のデフォルト値は、式を記述でき、省略された場合だけ評価されるのでそれを利用できます。

posted by genki genki on Tue 9 Aug 2011 at 04:47 with 0 comments

昔は
mysql_retry_lost_connection
というものがあったのですが、最近 (Rails-2.3以降) は config/database.yml の中で

yaml>>
production:
reconnect: true
<<--

とやるだけで、接続が切れた場合に再接続してくれるようです。
まあ、ここまで用意するならデフォルトでそうなってても良いと思うんですけどね。

posted by genki genki on Sat 11 Jun 2011 at 07:03 with 0 comments

結構長いことredmineを使ってるのですが、wikiのサイドバーを作れることに最近気が付きました。

作り方は単純で Sidebar という名前のページを作ればok.
サイドバーに入れる場合、見出しは h3 が良さそうです。

posted by genki genki on Fri 3 Jun 2011 at 04:54 with 0 comments

iftopコマンドを使うと、特定のインターフェイス/ポート番号における通信量を調べることができます。

ローカルのポート1234への通信量を調べる例:

pre>>
iftop -i lo -B -f "dst port 1234"
<<--

転送されるデータ量を測定してチューニング、使ってるか使ってないかわからないサーバプロセスの発見などに使えます。

ubunut/debianなら、

pre>>

apt-get install iftop

<<--

でインストールできます。

posted by genki genki on Tue 31 May 2011 at 06:11 with 0 comments

bundlerを使うとRubyアプリケーションごとに閉じたgemの依存関係を構築できるので、gemのバージョンの違いや環境ごとの違いで悩まされることが減ります。
これは非常に便利なのですが、rakeやunicornのようにコマンドをインストールするgemの場合、

pre>>
% bundle exec unicorn
<<--

のように、bundle execを介して実行する必用があって面倒です。
しかし、rvmを使えばこれを賢く解決できます。

比較的新しめのrvmとbundlerが必用になるので、
あらかじめ最新版をインストールしておいてください。

まず、以下のように適当なアプリケーション名などでgemsetを作ります。

pre>>
% rvm gemset create foo-app
<<--

作成したgemsetは

pre>>
% rvm gemset use foo-app
<<--

のようにしてアクティベートできます。新規に作成したgemsetの中身は
こんな感じになっています。

pre>>
% gem list

*** LOCAL GEMS ***

bundler (1.0.2)
rake (0.8.7)
<<--

bundler-1.0.2はちょっと古いので、gem udpateして最新のbundlerにします。

この状態であらかじめ用意しておいたGemfileに従ってgemをインストールします。

pre>>
% bundler install --system
<<--

これで foo-app gemset にはGemfileで指定したgem群が入った状態になり、rake, unicornなどのコマンド群もrvmがいい感じに取り計らってくれます。
あとは、rvm gemset use xxx を使えば適宜必用なgem環境を切り替えることができます。

ただ、アプリケーションが複数ある場合に、頻繁にgem環境を切り替えるのは面倒です。
アプリケーションのrootディレクトリに .rvmrc というファイルを作って

pre>>
rvm use ruby-1.8.7-p302@foo-app
<<--

のように記述しておいておくと、cd した時にrvmが勝手にgemsetを切り替えてくれます。これで完璧ですね!

Bye bye gem hell!

posted by genki genki on Sat 28 May 2011 at 21:36 with 0 comments

Rubyはメソッド定義内で begin/end が無くても直接rescueやensureを記述できますが、これは無駄な記述を減らす上でとても魅力的な文法だと思います。

ruby>>
def foo
puts "hello world :-)"
rescue
puts "something wrong :'-("
end
<<--

この書き方のまま、所定回数だけretryしたい場合、retry回数を覚えておくカウンタ変数を用意する場所に困ったりするのですが
(ローカル変数として定義すると、retry後に再初期化されてしまいますからね)
以下のように引数として用意しておくと、methodが定義するブロックよりも外側のライフタイムを持つので、retryカウンタとして使えます。

ruby>>
def foo(bar = 0)
puts bar
raise
rescue
bar += 1
retry if bar < 10
end

foo
<<--

実行した結果は以下の通り

pre>>
0
1
2
3
4
5
6
7
8
9
<<--

posted by genki genki on Sat 28 May 2011 at 01:21 with 1 comment

Rubygems-1.8.2 にアップデートして色々と痛い目にあっています。
ちょっと時期尚早な気がしたので、一旦過去のバージョンに戻すことに。
以下のようにすればokです。

pre>>

gem update --system 1.7.1

<<--

posted by genki genki on Sun 15 May 2011 at 04:03 with 0 comments

Rubyスクリプト中から

ruby>>
require "hoge"
<<--

されている hoge のソースを見てみたい時には、

sh>>
vim gem which hoge.rb
<<--

すると見つけてきてくれます。

posted by genki genki on Sun 8 May 2011 at 17:08 with 0 comments

昔はShift JISからEUC-JPに一括変換するのにqkcを使っていましたが、
最近は UTF8に変換する方が多いので、qkc は使えません。
そんな時は nkf で

pre>>
% nkf -w --in-place *
<<--

--in-placeを指定すれば一括変換できます。

posted by genki genki on Sat 11 Sep 2010 at 22:28 with 0 comments

普段のコミットログから作業日報的なものを生成したい場合、
以下のようなコマンドでそれらしいものが出力できます。

pre>>
% git log --author=takiuchi --format="%ad %s" --date=short
<<--

posted by genki genki on Wed 21 Apr 2010 at 08:46 with 0 comments

厳守してるわけじゃないですが、なんとなくこんなリズムでコードを書くようにしています。

  • 朝はデバッグ
  • 午後はテスト、ドキュメントを書く
  • 夜は新しいコードを書く

朝は脳が冴えていて、前日仕込んだバグが嘘のようによく取れます。

午後は眠くなるので、あまり脳を使わないテストやドキュメントを書きます。
単調な作業への反動でいいアイディアをひらめいたりします。Yakです。

夜は創造の時間です。新しいことに取り組みます。行き止まりだと思っていたところに道が開けます。

posted by genki genki on Mon 12 Apr 2010 at 18:33 with 0 comments

Valgrindを使うとメモリリークの検出などを行うことができて便利ですが、
OSやライブラリに起因するメモリリークのレポートが大量に出てくると邪魔なため、backtraceのパターンを指定して抑制(suppress)することができます。

例)valgrind.supp

pre>>
{

Memcheck:Leak
fun:malloc
fun:_nc_table_insert_n
fun:token_table_add
fun:notify_register_check
fun:notify_register_tz
fun:tzsetwall_basic
fun:localtime
fun:ctime
}
<<--

funはbacktrace上の関数名を示しますが、全体をマッチさせる場合、
呼び出し経路ごとに異なったパターンになるため、
沢山登録する必要が出てきてしまいます。

最新のValgrind(valgrind-3.6.0.SVNで確認)では、
"..." 記法によって中間のパターン指定を省略することが
できるようになりました。
これを使用すると、先程の例は以下のように書き直せます。

pre>>
{

Memcheck:Leak
fun:malloc
...
fun:localtime
}
<<--

localtime関数を呼び出したあとに、内部のmalloc呼び出しで
発生したメモリリークを全部一括で抑制できます。便利ですね。

posted by genki genki on Mon 5 Apr 2010 at 14:32 with 0 comments

To reduce consumption of papers, I investigated way to print both sides of paper on MacOSX.

  1. First, print even number pages by reverse order.
  2. Second, bring the output papers to the medium tray.
  3. Last, print odd number pages.

Be careful of the flow of from even number pages to odd number pages.
If you do oppositely, sometimes you would get the out of order result.

This can be used with layouts that have 2 or more pages a paper.

posted by takiuchi takiuchi on Sat 20 Jun 2009 at 18:56 with 0 comments

行末に|を記述するHamlの複数行記法が書きにくかったので、
Vimで整形出来るようにするための外部プログラムを作ってみました。

http://gist.github.com/112140

pre>>
set fp=/path/to/haml_formatter.rb
<<--

して、visualモードで選択してgqで整形です。

posted by genki genki on Sun 17 May 2009 at 07:32 with 0 comments

rubyで普通にinjectを使って合計を求めようとした場合、こんな感じになります。

ruby>>
(1..10).inject(0){|sum, i| sum + i} #=> 55
<<--

しかし、以下のように書く事も出来ます。

ruby>>
(1..10).inject(&:+) #=> 55
<<--

posted by genki genki on Sun 10 May 2009 at 04:49 with 0 comments

Enumerable#grepを使う事で、文字列の配列から、
所望のパターンにマッチするものだけを抜き出す事が出来ますが、
以下のようにブロックを指定する事で、
マッチした部分だけを取り出す事が出来ます。

ruby>>
Dir["config/environments/*.rb"].grep(%r{(\w+).rb$}){$1}
#=> ["development", "production", "rake", "staging", "test"]
<<--

痒いところに手が届く感じですね。

posted by genki genki on Thu 30 Apr 2009 at 14:27 with 0 comments

一人で長距離を走るのが暇なので、
走っている間に会話ができる仲間を求めてはじめた
MerbJog
ですが、
勉強会系イベントの手法として優れた特性を持っている事が分かったので
開催する上でのポイントなどをまとめておきます。

特長

  • 会場スペースの制約が無く、参加人数に制限がいらない
  • 1〜2時間程度と、短時間で終わる
  • 仕切り、準備、後片付けなどがほとんど不要
  • 話した内容とは無関係に、走り終わったあとに満足感がある
  • フォーメーション的に中心人物ができにくいので、全員が比較的フラットに話題に参加できる
  • 体力の許す限り話したい人のそばに移動できる
  • 二次会をしないので安上がり
  • 健康的

短所

  • ググれないので脳に入ってる情報だけがたより
  • ホワイトボード、PCなどが無いので言葉だけで説明する必要がある
  • 悪天候時には中止・延期せざるをえない
  • 体力が無い人は参加できない
  • 参加者と遭遇できない場合がある

開催上のポイント

  • 皇居などの信号が少なく、5〜10kmぐらいのコースが良い
  • 遭遇できなくても泣かない。たまには一人で走るのもよし
  • 遭遇率を高めるために、主催者は携帯を持っていく
    • 携帯はランニングポーチに入れておくと気にならなくて良い
  • 筋肉の疲労が抜けるまで、なか2日程度あけた方が良い

See Also

posted by genki genki on Mon 13 Apr 2009 at 13:44 with 1 comment

gemを指定したディレクトリにインストールする方法を紹介します。
以下のように -i オプションでディレクトリを指定します。

pre>>
gem install -i ./gems data_objects --no-ri --no-rdoc
<<--

Gemをunpackしている場合に、もう一つ、二つGemを追加したい時などに重宝します。

posted by genki genki on Sun 12 Apr 2009 at 17:34 with 2 comments

Passengerは非常に便利なのですが、
通常の設定では、アプリケーションへのアクセスが無い状態が5分程度続くと、プロセスがkillされてしまい、次回にアクセスする時に時間がかかるようになります。

これを回避するためには、httpd.confなどで、以下のように指定します。

pre>>
PassengerPoolIdleTime 0
<<--

これで、プロセス数の限界に達して追い出されるまで、Idle時間によってkillされる事は無くなります。

See Also

posted by genki genki on Sat 28 Mar 2009 at 20:32 with 0 comments
UL/LIタグを使ってリストを表示するときに、 コレクションが空の場合はULタグを表示したくない場合というのが頻繁にあります。 html>> <% if @posts.present? %>
    <% @posts.each do |post| %>
  • <%= h(@post.body) %>
  • <% end %>
<% end %> <<-- そういう時は、だいたいこんな感じにコードを書きます。 しかし、条件が複雑になってきたり、複数のコレクションを考えなければ行けない場合に、きれいに記述出来なくなってきます。 そんな時は、以下のようなヘルパを使って、分岐条件を遅延評価するようにすると、処理が簡潔になります。 ruby>> module ApplicationHelper def delayed_if(&block) flag = Object.new def flag.set; @value = true end def flag.reset; @value = false end result = capture(&proc{block.call(flag)}) concat(result) if flag.instance_variable_get(:@value) end <<-- 利用法 html>> <% delayed_if do |flag| %>
    <% @posts.each do |post| %>
  • <%= h(@post.body) %>
  • <% flag.set %> <% end %>
<% end %> <<-- flag.setがよばれた時だけ、delayed_ifのブロックが表示されます。 この例だと単純すぎてあまり恩恵が分かりにくいですが、 複数のコレクションを一つのULで表示する場合などでも簡潔に記述出来るようになります。
posted by genki genki on Sat 21 Mar 2009 at 17:33 with 0 comments

リソースを新規に作成する場合に、既存のものを再利用して作成したい場合は良くあると思います。
そんな時は、newアクションで:idを受け取れるようにして、
以下のようにすると、簡単に実現出来ます。

ruby>>
def new
@post = Post.new
@post.attributes = Post.find(params[:id]).attributes if params[:id]
@posts = Post.for_user(current_user).all
end
<<--

そしてposts/new.html.erbの中で

html>>
<% if @posts.present? %>

method="GET"> <%= select_tag :id, options_for_select(@posts.map{|i| [i.title, i.id]}) %> <%= submit_tag '読み込む' %>
<% end %> <<--

こんな感じに、テンプレートの読み込みフォームを作ります。
これで完了です。
Ajaxで posts/new/1 のようなURLにGETで遷移するようにした方が格好がいいかもしれません。

newアクションが:idで指定したリソースをテンプレートとして利用して新規にリソースを作成するというのは、標準的な挙動になっても良い気がします。

posted by genki genki on Sat 21 Mar 2009 at 13:18 with 0 comments

Skitchはスクリーンショットをとったり、図を描いたり、
画像形式を変換したりと、非常に便利な画像処理ツールで、
愛用しています。

コマンドラインからSkitchを起動出来たら便利だな、
と思って試したら、すんなり出来たので紹介します。

pre>>
% /Applications/Skitch.app/Contents/MacOS/Skitch foo.png
<<--

こんな感じでOK。convertコマンドの代わりになるかも。

posted by genki genki on Sun 15 Mar 2009 at 09:51 with 0 comments

ちょっと必要だったので作りました。

ss

CoreGraphicsを使って、指定したCGRectの中に、指定した太さの×印(Cross Sign)を描画するためのPathを生成します。

objective-c>>
void PDPathAddCrossSign(CGMutablePathRef path, CGRect rect, CGFloat thickness)
{
CGFloat diff = rect.size.width - rect.size.height;
rect = CGRectDeflateRect(rect, MAX(0, diff/2), MAX(0, -diff/2));
CGFloat radius = rect.size.width/2;
CGFloat d = sqrt(2)*thickness/2;
CGFloat cx = CGRectGetMidX(rect), cy = CGRectGetMidY(rect);
CGAffineTransform transform = CGAffineTransformMakeTranslation(cx, cy);
CGPathMoveToPoint(path, &transform, d, 0);
for(int i = 0; i < 4; ++i){
CGPathAddLineToPoint(path, &transform, radius, radius - d);
CGPathAddLineToPoint(path, &transform, radius - d, radius);
CGPathAddLineToPoint(path, &transform, 0, d);
transform = CGAffineTransformRotate(transform, M_PI/2.0f);
}
CGPathCloseSubpath(path);
}
<<--

中で呼び出してるCGRectDeflateRectは以下のようなものです。

objective-c>>
CGRect CGRectInflateRect(CGRect rect, CGFloat width, CGFloat height)
{
rect.origin.x -= width;
rect.origin.y -= height;
rect.size.width += width2;
rect.size.height += height
2;
return rect;
}

CGRect CGRectDeflateRect(CGRect rect, CGFloat width, CGFloat height)
{
return CGRectInflateRect(rect, -width, -height);
}
<<--

これを使う事で、任意の大きさ、太さ、色で×印を描画できます。

posted by genki genki on Wed 4 Mar 2009 at 00:06 with 0 comments

自分用メモ。
Mac標準のTextEditとプレビューを使ってリンクを含むPDFを作成します。

  1. TextEditでテンプレを参考にしつつ文を作成
  2. URLとメールアドレスの部分だけ、青色、下線の状態に
  3. ファイル - プリントを選び、プレビューボタンをクリック
  4. 先程、青色にしたテキストを選択状態にし、ツール - 注釈 - リンクを追加を選択
  5. アクションをURLにして、URL欄にURLまたはmailto:メールアドレスを入力
  6. すべてのリンクが追加できたら、ファイル - 保存を選択
  7. 終わり
posted by satoko satoko on Wed 25 Feb 2009 at 17:02 with 0 comments

RailsのCacheSweeperは非常に便利なのですが、
callbackからコントローラのインスタンス変数にアクセスできると
もっと便利になる気がします。

ソースコードを読んでみたら、やっぱりみんなそう思うようで、
assignsメソッドが用意されていました。

rails>>
class PostsSweeper < ActionController::Caching::Sweeper
observe Post

def after_posts_rating
expire_fragment "posts/show/#{assigns(:post).id}"
end
end
<<--

こんな風に書けます。これは便利。

posted by genki genki on Thu 29 Jan 2009 at 06:03 with 0 comments

rubyのクラス同士の継承関係を比較する演算子についてのメモ。

ruby>>

class Foo;end
class Bar<Foo;end
class Baz<Foo;end
[Foo < Bar, Bar < Foo, Foo > Bar, Bar > Foo]
=> [false, true, true, false]

Foo <=> Bar
=> 1

Foo <=> String
=> nil

Bar <=> Foo
=> -1

Bar <=> Baz
=> nil
<<--

また、以下のようにモジュールのinclude関係も取得出来ます。

ruby>>

module Goo;end
class Foo;include Goo end
Foo < Goo
=> true

Foo > Goo
=> false

Goo < Foo
=> false

Goo > Foo
=> true
<<--

posted by genki genki on Sun 25 Jan 2009 at 20:40 with 0 comments

$EDITORで~/.zshrcを開いて

sh>>
alias mi='PATH=./bin:$PATH merb -i'
alias mg='PATH=./bin:$PATH merb-gen'
<<--

の2行を追加すると、
thor merb:gems:install環境でもそうじゃない環境でも、所望のコマンドが実行されて便利です。

posted by genki genki on Tue 13 Jan 2009 at 17:02 with 0 comments

Merbをコンソールから操作する時には、merb -iコマンドを実行するのですが、
アプリケーションコードの変更を検出すると、自動的にirbがリロードされてしまい、ヒストリーが消えてしまうので、若干不便さを感じていました。

そんな時は、
irb-history
があなたのMerbライフを強力にサポートしてくれます(Thanks maiha!)

まずはおもむろに

pre>>
% sudo gem install irb-history
<<--

つづいて、~/.irbrc に以下の行を追加します。

ruby>>
require 'rubygems'
require 'irb/history'
IRB::History.start_client
<<--

これでOK。あとは普通にmerb -iを使っていれば、リロードされても
ヒストリーが消えません。

posted by genki genki on Tue 13 Jan 2009 at 16:53 with 0 comments

GitHub上で公開されているgemは、GEM_NAMEにユーザIDがプレフィックスとしてついてしまうので、以下のようにdependency.rbを記述する必要があります。

ruby>>
dependency "genki-merb_babel", :require_as => 'merb_babel'
<<--

Railsのconfig.gemの場合の:libオプションに似ていますね。

posted by genki genki on Fri 2 Jan 2009 at 20:56 with 0 comments

merbのGemの名前は、"-"区切りのものと、"_"区切りのものがあるが、

  • "-" はオフィシャルなもの
  • "_" は野良Gem

という使い分けらしい。

posted by genki genki on Sat 27 Dec 2008 at 18:00 with 0 comments

merb-genコマンド用にZshの補完関数を作りました。

pre>>
_merb-gen () {
compadd merb-gen | grep '^ *' | awk '{print \$1}' | xargs
}

compdef _merb-gen merb-gen
<<--

.zshrcなどに記述すれば、
以下のような感じで補完出来ます。

pre>>
% merb-gen [TAB]
--debug controller part
--no-color core plugin
-d, flat resource
-f, helper resource_controller
-h, layout session_migration
-p, mailer slice
-s, migration very_flat
app model
<<--

posted by genki genki on Tue 18 Nov 2008 at 03:03 with 0 comments

Objective-CでMethodのIMPを取得して呼び出す場合に、
正しい関数プロトタイプの関数ポインタにキャストする必要がありますが、
typedefなどを使わずにその場で目的の関数ポインタ型にキャスト
する方法を紹介します。

objective-c>>
SEL selector = @selector(drawRect:);
Method method = class_getInstanceMethod([UISearchBar class], selector);
IMP drawRect = method_getImplementation(method);
((void(*)(id, SEL, CGRect))drawRect)(self, selector, rect);
<<--

こんな感じにすればOkです。

posted by genki genki on Thu 13 Nov 2008 at 01:12 with 0 comments

Objective-CでCSSでよく使うようなABCDEFFFのようなHex encodeされた形式の文字列からUIColorを生成する方法の紹介です。

objective-c>>
@interface UIColor (HexEncoding)

  • (UIColor*)colorFromString:(NSString*)string;
  • (NSString*)encodeToString;
    @end

@implementation UIColor (HexEncoding)

  • (UIColor*)
    colorFromString:(NSString*)string
    {
    NSScanner *scanner = [NSScanner scannerWithString:string];
    NSUInteger value;
    [scanner scanHexInt:&value];
    CGFloat red = ((value & 0xFF000000) >> 24) / 255.0f;
    CGFloat green = ((value & 0x00FF0000) >> 16) / 255.0f;
    CGFloat blue = ((value & 0x0000FF00) >> 8) / 255.0f;
    CGFloat alpha = ((value & 0x000000FF) >> 0) / 255.0f;
    return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
    }
  • (NSString*)encodeToString
    {
    const CGFloat *components = CGColorGetComponents(self.CGColor);
    return [NSString stringWithFormat:@"%02x%02x%02x%02x",
    (int)(components[0]*255 + 0.5f),
    (int)(components[1]*255 + 0.5f),
    (int)(components[2]*255 + 0.5f),
    (int)(components[3]*255 + 0.5f)];

}

@end
<<--

わかりやすいように、UIColorにメソッドカテゴリを追加しています。
encodeToStringのほうでは、0.5を足してroundをかけていますが、
状況に応じてfloorにしたりceilにしたりしてください。

また、この例ではComponentsのサイズが4である事を期待しています。
そうではない色を扱うときには問題が発生しますので、ご注意ください。

posted by genki genki on Fri 7 Nov 2008 at 12:10 with 0 comments

Redmineで2203年の予定を立てようとしたところ、エラーが出たので原因を調べていました。
どうやら、Railsのdistance_of_time_in_wordsでエラーが出ているようです。

ruby>>
def distance_of_time_in_words(
from_time, to_time = 0, include_seconds = false)
from_time = from_time.to_time if
from_time.respond_to?(:to_time)
to_time = to_time.to_time if
to_time.respond_to?(:to_time)
distance_in_minutes =
(((to_time - from_time).abs)/60).round
distance_in_seconds =
((to_time - from_time).abs).round
<<--

8行目あたりの減算でエラーが出ているようです。
実際、以下のような減算をしようとするとエラーが出ます。

ruby>>
Time.now - Date.parse("Mon, 01 Aug 2203").to_time
#=> RangeError: time - 7371010800.000000 out of Time range
<<--

ということで、あまりにも長い時間である場合には、
以下のような例外処理で対処するようにしました。

ruby>>
module ActionView
module Helpers
module DateHelper
def distance_of_time_in_words_with_limit(
from_time, to_time = 0, include_seconds = false
)
distance_of_time_in_words_without_limit(
from_time, to_time, include_seconds)
rescue
'a long time'
end
alias_method_chain :distance_of_time_in_words, :limit
end
end
end
<<--

これで23世紀の予定も思いのままです。

posted by genki genki on Fri 8 Aug 2008 at 06:44 with 0 comments

Controllerのアクションのテストを書くときに、
通常は以下のようにgetメソッドなどを使い、
アクションのメソッドを指定します。

rails>>
get :index
<<--

しかし、config/routes.rbの中でmap.root :formulae
のようにルートのPathをindexアクションにマッピングしている場合でも、
get :indexを呼び出した結果、Controllerに渡されるrequest.request_uri
の値は正しいルートのPathになっていません。

そのような場合には、以下のようにすると正しい結果が得られます。

rails>>
request.set_REQUEST_URI '/'
get :index
<<--

posted by genki genki on Sat 26 Jul 2008 at 00:35 with 0 comments

RailsのXMLのレンダリングが遅い。
これは、String#to_xsが遅いのが原因らしい。

そこで、これを高速化するためのライブラリfast_xsを使うと、
XMLのレンダリングが速くなります
(手元の環境で試したところでは、若干速くなったような気がしました。)

Rails-2.0以降では、fast_xsがインストールされている場合に、
自動的にそれを利用するようになっています。

[Changeset 7774] Reference current fast_xs URL

インストールは、いつものようにsudo gem install fast_xsでOK。

See Also

 

posted by genki genki on Mon 21 Jul 2008 at 08:37 with 0 comments

Rubyで一時ファイルを作成する場合は、
Tempfileを使うのが一般的だと思いますが、
今回は一時ディレクトリを作成する方法を紹介します。

TempDir

Jim Freezeさん作のTempDirです。
sudo gem install tempdirでインストールできて、
以下のようにして使います。

ruby>>
require 'rubygems'
require 'temp_dir'
TempDir.create do |dir|
puts dir # => "/tmp/temp_dir_24463_24509_oxvgf"
end
<<--

dirは生成された一時ディレクトリのpathを示す文字列です。
createブロックを抜けると一時ディレクトリは削除されます。

posted by genki genki on Sun 20 Jul 2008 at 07:58 with 4 comments

Kagemushaを使って、スコープを汚さないDSLスタイルのinitialize
メソッドを提供する方法を紹介します。

ruby>>
require 'rubygems'
require 'kagemusha'

class Foo
def initialize(&block)
bar = nil # default value
meta = eval('class << self; self end', block.binding)
Kagemusha.new(meta) do |kage|
kage.def(:bar){|bar|} # substitution
end.swap(&block)
@bar = bar
end
end

def bar(x); puts x end

foo = Foo.new do
bar 'bar'
end

puts foo.inspect # => #<Foo:0xb7c03de0 @bar="bar">
bar "hello!" # => hello!
<<--

bindingのコンテクストからメタクラスを取得し、
Kagemushaを使って限定的にbarメソッドを置き換えています。
Foo.newのブロック内から抜けると、
barの呼び出しはグローバルスコープのbarを呼んで、
"hello!"が出力されます。

この方法は、initialize以外にも、
ブロックを受けるインスタンスメソッド全般に利用できます。
例えば、以下のようなコードで、一時変数t
の存在が気になる場合などですね。

rails>>
create_table do |t|
t.string :foo
end
<<--

posted by genki genki on Thu 17 Jul 2008 at 18:41 with 1 comment

メモもかねて。

MacBookにRailsの自動テスト環境を構築した

RAILS_ROOTでautotestを実行。起動時に全部のテストを実行するのでちょっとだけ重くなるかもしれません。それ以降はテストファイルやモデル、コントローラファイルなどを修正する度に該当のテストが走ります。

autotestを-fオプションを付けて立ち上げると、Fast startモードになり、最初に全部のテストを実行しなくなります。

posted by genki genki on Sun 6 Jul 2008 at 10:47 with 0 comments

KagemushaでActiveRecordのfindなどのクラスメソッドをswap
しようとすると、

pre>>
singleton method bound for a different object (TypeError)
<<--

というエラーが発生するという問題がありました。

このままでは困るので、とりあえず動くようにしてみました。
Unboundにしなければ問題は起こらないと思ったので、
instance_methodの代わりにalias_methodを使っています。

kagemusha_core_ext.rb

ruby>>
require 'uuidtools'

class Kagemusha #:nodoc:
def swap #:nodoc:
original_class_methods = {}
original_instance_methods = {}

@class_methods.each { |name, proc|
  if proc
    begin
      # replace method
      #method = @meta.instance_method(name)
      method = random_name
      @meta.instance_eval { alias_method method, name }
      @meta.instance_eval { define_method(name, proc) }
      original_class_methods[name] = method
    rescue NameError
      # insert method
      @meta.instance_eval { define_method(name, proc) }
      original_class_methods[name] = false
    end
  else
    begin
      # remove method
      #method = @meta.instance_method(name)
      method = random_name
      @meta.instance_eval { alias_method method, name }
      @meta.instance_eval { undef_method(name) }
      original_class_methods[name] = method
    rescue NameError
      # nop
    end
  end
}

@instance_methods.each { |name, proc|
  if proc
    begin
      # replace method
      method = @klass.instance_method(name)
      @klass.instance_eval { define_method(name, proc) }
      original_instance_methods[name] = method
    rescue NameError
      # insert method
      @klass.instance_eval { define_method(name, proc) }
      original_instance_methods[name] = false
    end
  else
    begin
      # remove method
      method = @klass.instance_method(name)
      @klass.instance_eval { undef_method(name) }
      original_instance_methods[name] = method
    rescue NameError
      # nop
    end
  end
}

return yield

ensure
original_class_methods.each { |name, method|
if method
# replace method
#@meta.instance_eval { define_method(name, method) }
@meta.instance_eval { alias_method name, method }
@meta.instance_eval { undef_method method }
else
# remove method
@meta.instance_eval { undef_method(name) }
end
}
original_instance_methods.each { |name, method|
if method
# replace method
@klass.instance_eval { define_method(name, method) }
else
# remove method
@klass.instance_eval { undef_method(name) }
end
}
end

private
def random_name
[UUID.random_128].pack("m").tr("=\n", '')
end
end
<<--

posted by genki genki on Sun 6 Jul 2008 at 02:28 with 2 comments

RubyKaigi会場にて、もろはしさんから、はてなスターを連打できないのはけしからんという訓示をいただきましたので、cuzicさん主催のHackathon会場からささっと対応してみました。

とはいっても、CSSで以下のようにRtoLのDirectionを指定しているだけです。

css>>
.star{unicode-bidi: bidi-override}
.star{direction: rtl}
<<--

追記

沢山ついたStarが数字で省略された場合に、
数字部分が左右反転されてしまうと都合が悪いので、
さらに以下のようなCSSを記述しました。

css>>
.hatena-star-inner-count {unicode-bidi: bidi-override}
.hatena-star-inner-count {direction: ltr}
<<--

posted by genki genki on Sun 22 Jun 2008 at 00:04 with 0 comments

公開鍵を登録してもpush出来ない問題でしばらく放置していたのですが、
Tom Copeland氏のサポート
のお陰で原因と解決方法がわかったので
まとめておきます。

  1. Dr. Nicのチュートリアルの通りにやる
  2. ただし、公開鍵の登録時には、公開鍵の末尾のコメント部分("=="の後ですね)に、メールアドレスなどのユニークな識別子を書いておく必要がある。

あとは、

pre>>
% git remote add rubyforge gitosis@rubyforge.org:
<<--

GitHubと両方登録しておいたら良いと思います。
Let's add remote rubyforge!

See Also

posted by genki genki on Thu 22 May 2008 at 19:13 with 0 comments

テストの実行時に利用されるDBは、通常development環境のstructureがコピーされますが、何らかの事情でproduction環境のものを使って欲しい場合もあります。
そんなときは、以下のRakeタスクを実行すればOK.

pre>>
% rake db:test:clone RAILS_ENV=production
<<--

これによって、production環境のstructureがコピーされます。

posted by genki genki on Thu 15 May 2008 at 11:13 with 0 comments

Gitでファイル一式をまとめてtar ballにする場合、.gitがあるディレクトリに
移動して、以下のようにします。

pre>>
% git-archive --format=tar HEAD | gzip > foo.tar.gz
<<--

これによって、Gitの管理下にあるファイル一式をまとめたtar.gzファイルが出来上がります。余談ですが、tar.gzをtar ballと呼ぶのはなんでだろう。

良く使いそうなので、専用のGitコマンドがあっても良いんじゃないかな?

posted by genki genki on Mon 12 May 2008 at 18:37 with 0 comments

svn upしたあとにどのファイルが更新されるかを事前にしらべるには、
以下のようなコマンドを使えば良いようです。

pre>>
% svn -u stat
<<--

svn up -dry-runが出来ると良いんですけどね。

See Also

posted by genki genki on Mon 12 May 2008 at 12:45 with 0 comments

Rubyでは、Dateのインスタンスをinspectすると、以下のような馴染みのない数値が出力されます。

ruby>>
Date.today.inspect
=> "#<Date: 4909185/2,0,2299161>"
<<--

これはDateクラスが日付の内部表現としてRationalを利用しているためですが、inspectしたときにこの表現が出てきても、日付がわからないので困りますね。
そこで、以下のようにDate#inspectを定義してあげると、
人間に優しい表現になります。

ruby>>
class Date
def inspect
strftime '#<Date: %x>'
end
end

Date.today
=> #<Date: 05/06/08>
<<--

これならDateが何日なのかわかりやすいですね。

strftime%xはロケールによって出力が変わるので、
お使いのPCの環境によっては、上記のような出力にならない事もあります。

See Also

posted by genki genki on Tue 6 May 2008 at 11:38 with 0 comments