Vimの正規表現では常に\vを使うことにする
:echo match('aaa', 'a*') => 0 (マッチする) :echo match('aaa', 'a+') => -1 (マッチしない)
このような結果になるのは、*はエスケープが不要だが、+はエスケープが必要なため。
:echo match('aaa', 'a\+') => 0
とすればマッチする。
エスケープが必要なのか不要なのか、メタキャラクタによってまちまちで分かりにくい。
また、magicというオプションによっても、挙動が変わる。
このややこしさは、\vというメタキャラクタを使うと解決できる。
:echo match('aaa', '\va+') => 0
このように正規表現の最初に\vを付加すると、あらゆるメタキャラクタがエスケープ無しで効果を発揮するようになる。
詳細は以下のヘルプで参照
:help magic
Rubyのカレントクラスという概念
書籍「メタプログラミングRuby」を読んでカレントクラスという概念を初めて知った。
Rubyはselfで参照できるカレントオブジェクトとは別に、常にカレントクラスを持っているとのこと。
defキーワードでメソッドを定義する時、このカレントクラスに対してインスタンスメソッドを定義する。
classキーワードでクラスをオープンすると、カレントクラスがそのクラスになるため、クラス定義内で定義したメソッドはそのクラスのインスタンスメソッドとなる。
class_evalでクラスをオープンした場合も同様で、レシーバのクラスがカレントクラスとなる。
class Hoge end Hoge.class_eval do # カレントクラスがHogeになる def meth end end Hoge.instance_methods(false) #=> [:meth]
class_evalはカレントオブジェクトも変更するので、
class_evalの動作は、「カレントオブジェクトとカレントクラスをレシーバのクラスに変更する」、と明確に定義することが出来るのだ。
ここら辺は今まで曖昧に理解していたので目から鱗だった。
ちなみにinstance_evalは、
「カレントオブジェクトをレシーバのオブジェクトに変更し、カレントクラスをレシーバのオブジェクトの特異クラスに変更する」。
そのためinstance_evalを使って、オブジェクトの特異メソッドを定義したり、クラスメソッドを定義することができる。
class Hoge end obj = Hoge.new obj2 = Hoge.new obj.instance_eval do # カレントクラスがobjの特異クラスになる def obj_meth puts 'obj' end end Hoge.instance_eval do # カレントクラスがHogeの特異クラスになる def hoge_meth puts 'hoge' end end obj.obj_meth #=> obj obj2.obj_meth #=> NoMethodErrorが発生 Hoge.hoge_meth #=> hoge
ところで、メソッドをネストした時のカレントクラスは意外なものになる。
class Hoge def meth1 def meth1_inner end end def self.meth2 def meth2_inner end end Hoge.new.meth1 # meth1_innerを定義する Hoge.meth3 # meth2_innerを定義する Hoge.instance_methods(false) #=> [:meth1, :meth1_inner, :meth2_inner] Hoge.singleton_methods #=> [:meth2]
meth1_innerはクロージャにならずに、Hogeクラスに定義される。
クラスメソッド内で定義したmeth2_innerも同様。
結局、カレントクラスについては、クラスをオープンした時にのみ変更されて、
たとえメソッド定義内であっても関係なく常にオープン中のクラスがカレントクラスになっていると考えれば良さそう。
カレントクラスは便利な概念なのでselfのようにプログラムから参照できたら良いのにと思っていたら、そういう提案が既にされていた。(http://redmine.ruby-lang.org/issues/4043)
Rails3のflashの新記法ではまった
Rails3のredirect_toで:noticeオプションを付けることでflashを使えるようになった。
ということで
flash[:notice] = 'message' redirect_to :action => 'index'
と書いていたものを
redirect_to {:action => 'index'}, :notice => 'message'
と修正したのだがこのままだとエラーになってしまう。
ネットで調べると、どうやら引数で渡したハッシュの「{」記号がブロックとして解釈されてしまうらしい。
redirect_to ({:action => 'index'}, :notice => 'message')
このように引数全体をカッコで括ってもだめ。
結局以下の書き方が正解だった。
redirect_to ({:action => 'index'}), :notice => 'message'
とても気持ち悪いけど仕方ないのかな?
RVMのインストール
開発環境のrubyをrvmで管理することにしたので、導入手順をまとめておく。
(参考 https://rvm.beginrescueend.com/rvm/install/)
rvmのインストールにはbashとcurlとgitが必要なので事前に入れておくこと。
rvmは以下のコマンドでインストールする。
$ bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
このコマンドを実行すると、gitレポジトリから最新バージョンのrvmを取ってきて、カレントユーザーのホームディレクトリ直下に、~/.rvm/というディレクトリを作成し、そこへインストールしてくれる。
この際に~/.rvm/bin/にあるスクリプト群が勝手に~/bin/にコピーされたのが気持ち悪かったので、これらを削除して~/.rvm/binにパスを通すことにした。
$ rm ~/bin/rvm* $ export PATH=$PATH:$HOME/.rvm/bin
インストールされたrvmのバージョンを確認してみる。
$ rvm --version rvm 1.6.14 by Wayne E. Seguin (wayneeseguin@gmail.com) [https://rvm.beginrescueend.com/]
これでrubyのインストールが可能になるのだが、その前にインストールに必要な依存ライブラリを確認しておく。
以下のコマンドで確認できる。
$ rvm notes …(省略) dependencies: # For RVM rvm: bash curl git # For Ruby (MRI & ree) you should install the following OS dependencies: ruby: /usr/bin/apt-get install build-essential bison openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev # For JRuby (if you wish to use it) you will need: jruby: /usr/bin/apt-get install curl g++ openjdk-6-jre-headless jruby-head: /usr/bin/apt-get install ant openjdk-6-jdk # In addition to ruby: dependencies, ruby-head: subversion # For IronRuby (if you wish to use it) you will need: ironruby: /usr/bin/apt-get install curl mono-2.0-devel
自分の環境に無いものをインストールする。
$ sudo aptitude install bison build-essential libreadline6-dev libssl-dev libyaml-dev sqlite3 libxslt-dev autoconf ncurses-dev
インストール可能なrubyのバージョンを確認をする。
$ rvm list known # MRI Rubies [ruby-]1.8.6[-p420] [ruby-]1.8.6-head [ruby-]1.8.7[-p334] [ruby-]1.8.7-head [ruby-]1.9.1-p378 [ruby-]1.9.1[-p431] [ruby-]1.9.1-head [ruby-]1.9.2[-p180] [ruby-]1.9.2-head ruby-head …(省略)
ruby-1.8.7-p334をインストールする。
$ rvm install 1.8.7 'gem' command not found, cannot select a gemset. Installing Ruby from source to: /home/ak/.rvm/rubies/ruby-1.8.7-p334, this may take a while depending on your cpu(s)... ruby-1.8.7-p334 - #fetching ruby-1.8.7-p334 - #downloading ruby-1.8.7-p334, this may take a while depending on your connection... % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 4092k 100 4092k 0 0 616k 0 0:00:06 0:00:06 --:--:-- 2746k ruby-1.8.7-p334 - #extracting ruby-1.8.7-p334 to /home/ak/.rvm/src/ruby-1.8.7-p334 ruby-1.8.7-p334 - #extracted to /home/ak/.rvm/src/ruby-1.8.7-p334 ruby-1.8.7-p334 - #configuring ruby-1.8.7-p334 - #compiling ruby-1.8.7-p334 - #installing Removing old Rubygems files... Installing rubygems dedicated to ruby-1.8.7-p334... Retrieving rubygems-1.6.2 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 236k 100 236k 0 0 47095 0 0:00:05 0:00:05 --:--:-- 2077k Extracting rubygems-1.6.2 ... Installing rubygems for /home/ak/.rvm/rubies/ruby-1.8.7-p334/bin/ruby Installation of rubygems completed successfully. ruby-1.8.7-p334 - adjusting #shebangs for (gem irb erb ri rdoc testrb rake). ruby-1.8.7-p334 - #importing default gemsets (/home/ak/.rvm/gemsets/) 'gem' command not found, cannot select a gemset. Install of ruby-1.8.7-p334 - #complete
このコマンドによって、
ruby1.8.7が
~/.rvm/rubies/ruby-1.8.7-p337/に、
rubygems1.6.2が
~/.rvm/gems/ruby-1.8.7-p334と
~/.rvm/gems/ruby-1.8.7-p334@globalにインストールされた。
同様にruby-1.9.2-p180をインストールする。
$ rvm install 1.9.2 'gem' command not found, cannot select a gemset. Installing Ruby from source to: /home/ak/.rvm/rubies/ruby-1.9.2-p180, this may take a while depending on your cpu(s)... ruby-1.9.2-p180 - #fetching ruby-1.9.2-p180 - #downloading ruby-1.9.2-p180, this may take a while depending on your connection... % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 8609k 100 8609k 0 0 1139k 0 0:00:07 0:00:07 --:--:-- 3698k ruby-1.9.2-p180 - #extracting ruby-1.9.2-p180 to /home/ak/.rvm/src/ruby-1.9.2-p180 ruby-1.9.2-p180 - #extracted to /home/ak/.rvm/src/ruby-1.9.2-p180 ruby-1.9.2-p180 - #configuring ruby-1.9.2-p180 - #compiling ruby-1.9.2-p180 - #installing Removing old Rubygems files... Installing rubygems dedicated to ruby-1.9.2-p180... Installing rubygems for /home/ak/.rvm/rubies/ruby-1.9.2-p180/bin/ruby Installation of rubygems completed successfully. ruby-1.9.2-p180 - adjusting #shebangs for (gem irb erb ri rdoc testrb rake). ruby-1.9.2-p180 - #importing default gemsets (/home/ak/.rvm/gemsets/) 'gem' command not found, cannot select a gemset. Install of ruby-1.9.2-p180 - #complete
インストールされたものを確認してみる。
$ ls -l ~/.rvm/rubies/ ruby-1.8.7-p334/ ruby-1.9.2-p180/ $ ls -l ~/.rvm/gems/ cache/ ruby-1.8.7-p334/ ruby-1.8.7-p334@global/ ruby-1.9.2-p180/ ruby-1.9.2-p180@global/
rubyのバージョンごとに複数のrubygemsを作成することが出来るようになっており、
rubyのバージョン同様rubygemsを自由に切り替えることが出来る。
デフォルトでは、一つのrubyのバージョンに対して、「名前無し」と「global」というrubygemsが作られる。
インストール済みのrubyを確認する。
$ rvm list rvm rubies ruby-1.9.2-p180 [ i386 ] ruby-1.8.7-p334 [ i386 ]
この時点でrubyコマンドやirbコマンドなどを使えるのだが、
$ ruby-1.8.7-p334 $ irb-ruby-1.9.2-p180
のようにバージョン付きのコマンドを使い分けなければならない。
これでは意味が無いので、rubyやirbと指定しただけで特定のバージョンのコマンドを実行できるように設定する。
この機能を使うには以下を.bashrcに記述する必要がある。
[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm"
後は以下のようにコマンドを実行すると、rubyバージョンとrubygemsを切り替えることが出来る。
rvm @
$ rvm 1.8.7 # ruby(1.8.7), rubygems(名前無し)に切り替わる $ ruby --version ruby 1.8.7 (2011-02-18 patchlevel 334) [i686-linux] $ rvm 1.9.2@global # ruby(1.9.2), rubygems(global)に切り替わる $ ruby --version ruby 1.9.2p180 (2011-02-18 revision 30909) [i686-linux]
この設定はシェルを閉じると無効になってしまう。
シェルを閉じても設定を維持させるには以下のように--defaultオプションを付けて指定する。
$ rvm --default 1.9.2
新しくrubygemsを作成する場合は、
$ rvm 1.8.7
のように作成先のrubyバージョンを指定してから
$ rvm gemset create rails235
と実行する。
ちゃんとrubygemsが作成されたか確認してみる。
$ rvm gemset list gemsets for ruby-1.8.7-p334 (found in /home/ak/.rvm/gems/ruby-1.8.7-p334) global rails235
gem installコマンドを使うと設定中のrubygemsにのみインストールされる。
ただしglobalなrubygemsにインストールしたライブラリは特別扱いされ、そのrubygemsが所属するrubyバージョンを設定している間は常に利用できる。
例えば、ruby-1.8.7@rails235に設定している時でもruby-1.8.7@globalにインストールしたライブラリを参照できる。
rubygemsは自由に切り分けることが出来るが、Railsのバージョンが異なると依存する多くのライブラリも変わってくるのでRailsのバージョンごとにrubygemsを作るのが良さそう。
rvm自体をアップデートするには以下のコマンドを実行する。
$ rvm get latest $ rvm reload
rvmをアンインストールする場合は、~/.rvmディレクトリを丸ごと削除すればよい。
rvmコマンドのヘルプ参照は以下の通り。
$ rvm help
公式HPもドキュメントが充実してるので要参照。