rubyのIDEではRubyMineが有名だけど有料なのでEclipse+RDT(Ruby Development Toolkit)を試してみました。(Aptana Studio 3 Pluginは使わない)

Eclipseのインストール

eclipseのサイトからMac OS X 64 Bit版をダウンロード。この時のバージョンは4.3.2でした。

RDTのインストール

-All Available Sites--にしてrubyで絞り込むとRDTが出てくるのでインストール。

PreferencesでRubyのInterpretersを追加。上記のようにrbenvを使ってる場合はshims/rubyを指定すればOKでした。

Enginesで何でdebugするのかというのを選びます。他のはgemが必要だったりバージョン毎に動いたり動かなかったりするのでRuby Build-In Debuggerを選択。

普通のrubyスクリプトをdebug

これは普通にできる。トップレベルのlocal変数が見れない気がするけど。

sinatraアプリをdebug

これも普通に実行するとhttp://localhost:4567/とかで立ち上がるのでブラウザからアクセスするとちゃんとブレイクポイントで止まってくれる。

railsアプリをdebug

怖話で試してみる。

これも要はscript/rails serverを実行してhttp://localhost:3000/にアクセスすればいいだけだからDebug Configurationsで下記のようなものを用意する。

実行するスクリプトはscript/rails

引数はserver

ただでさえ遅い怖話のデバッグ起動はクッソ重いので覚悟すること。

ちゃんとブレイクポイントの上の行の@nowがとれてます。

感想

ややこしいプロジェクトの厄介なバグを本腰入れて追い回す時には良いかも。ただほんとに重いので軽快にdebugしたいならpry-byebugの方が良いかな。

気になった点

ruby1.9からのnew hash syntaxがエラーと認識されている。RDTのどこかで設定できるのかな?

$ brew update
$ brew upgrade rbenv ruby-build
$ CONFIGURE_OPTS="--with-openssl-dir=`brew --prefix openssl` --with-readline-dir=`brew --prefix readline`" rbenv install 2.1.2
$ rbenv global 2.1.2
$ gem install bundler rbenv-rehash

sinatraset :foo, 'bar'みたいなDSLを使って値を設定できる。でもこの値ってどこにどうやって保存されているんだろう?

普通、最終的にはインスタンス変数かクラス変数に格納されてるって思うよね。

(class << self; self; end).class_eval do
  undef_method(name) if method_defined? name
  String === content ? class_eval("def #{name}() #{content}; end") : define_method(name, &content)
end

sinatra/lib/sinatra/base.rb at v1.4.5 · sinatra/sinatra

ところがset :foo, 'bar'するとbarを返すfooというメソッドが定義されるという形で保存されている。

setするたびにundef_methodして定義し直すので変数みたいに使えるようだ。静的な頭で考えてたのでクラクラするような格納方法だ。

$LOADED_FEATURESっていうのがある。

% pry
[1] pry(main)> $LOADED_FEATURES
=> ["enumerator.so",
 "/usr/local/opt/rbenv/versions/2.1.0/lib/ruby/2.1.0/x86_64-darwin13.0/enc/encdb.bundle",
 "/usr/local/opt/rbenv/versions/2.1.0/lib/ruby/2.1.0/x86_64-darwin13.0/enc/trans/transdb.bundle",
 "/usr/local/opt/rbenv/versions/2.1.0/lib/ruby/2.1.0/x86_64-darwin13.0/rbconfig.rb",
 "/usr/local/opt/rbenv/versions/2.1.0/lib/ruby/2.1.0/rubygems/compatibility.rb",
 "/usr/local/opt/rbenv/versions/2.1.0/lib/ruby/2.1.0/rubygems/defaults.rb",
 "/usr/local/opt/rbenv/versions/2.1.0/lib/ruby/2.1.0/rubygems/deprecate.rb",
 "/usr/local/opt/rbenv/versions/2.1.0/lib/ruby/2.1.0/rubygems/errors.rb",
 "/usr/local/opt/rbenv/versions/2.1.0/lib/ruby/2.1.0/rubygems/version.rb",
(snip)

ほうほう。

rubygems - How do I get a list of files that have been `required` in Ruby? - Stack Overflow

ActionMailerでマルチバイトのメールを送る時下記のように三行書く。

mail = NoticeMailer.charging(user, charge)
mail.transport_encoding = '8bit'
mail.deliver

プロジェクトの中にはNoticeMailer.posted_questionとかいくつかあるし、他のmethodでも他のMailerクラスでも一行で書きたいんだけどどのファイルにどう書くのがキレイかなあ?

追記:

tkawaさんのコメントを受けて実装された。

NoticeMailer.charging(user, charge).deliver

アプリの一部では使うからjbuildrのgem入れてるけど基本的にscaffoldでjson使いたくない場合。

# config/application.rb:
module Rails
  class Application < Rails::Application
    config.generators do |g|
      g.jbuilder false
    end
  end
end
% brew update
% brew upgrade ruby-build
% CONFIGURE_OPTS="--with-openssl-dir=`brew --prefix openssl` --with-readline-dir=`brew --prefix readline`" rbenv install 2.1.0
% rbenv global 2.1.0
% gem install bundler rbenv-rehash
% rbenv rehash

バージョンのパッチレベル表記がシンプルになったのは気持ちいいですね。

元から入ってるrubyが最新版ですがsudoとかで壊すとやっかいなので。

% brew install readline openssl
% CONFIGURE_OPTS="--with-readline-dir=`brew --prefix readline` --with-openssl-dir=`brew --prefix openssl` --with-gcc=clang" rbenv install 2.0.0-p247
% rbenv global 2.0.0-p247
% rbenv rehash
% gem install bundler rbenv-rehash

acts_as_listはitemに対するcategoryだとか、並び替えをグループ化する対象(scope)を指定できる。scopeをcategoryにすると同一category_idの中で並べ替えるといった具合。

シンプルにはそういうの要らなくて普通にitemを並べ替えたいだけだとおもうんだけどREADMEにのってる例がいきなりそういう応用編なので分かりづらいと思う。

configuration = { column: "position", scope: "1 = 1", top_of_list: 1, add_new_at: :bottom}

acts_as_list/lib/acts_as_list/active_record/acts/list.rb at a736eca3b0918c39759f94d71193c12508344e9c · swanandp/acts_as_list

scopeに何も渡さなかった場合は"1 = 1"という文字列がSQLに渡されるので常にtrueだからそのシンプルな例が適応される。

active_decoratorは他の類似gemより気持ち良く書けて好きなんですが、時々

「decoratorのmethodが呼べないなあ?」

みたいな時があるのにもかかわらずなんとなく使ってて反省したのでコードを読んでみた。

要はview_assignsというその名の通りのrailsのmethodを使ってview_contextのinstance変数を列挙してActiveRecord系のものだったらdecorateすると。

なるほどなぁ〜。この辺が他の明示的にdecorateする系とは違うピリッと効いてるところなのかな。

それでやっとわかった。

= current_user.foo

とか

= @post.user.foo

とかいうようなassignしてない部分で「あれ、効かないな」となってたわけだ。

俺が使い方をわかってなかっただけなんですが、特に後者は結構でてくると思うけどみんなどうやってるんだろう?

追記:

と思ったらこのPRが正にそれっぽい。

Decorate associations of a decorated object by ronen · Pull Request #8 · amatsuda/active_decorator

association全部decorateするのはやり過ぎ感とかあるのかな?