RVMでRuby環境の切り替えを簡単に!

Rvm image
Ruby 開発を始める時はまずgem管理ツールを入れておくと便利です。
実行環境やプロダクトに応じ、Ruby本体やgemパッケージの依存するバージョンが異なる事も多々あります。これらのバージョンを管理して切り替えを容易にしてくれるのがRVM(Ruby Version Manager)やBundlerといった管理ツールなのです。

今回はRVMのインストール手順をまとめました。それでは続きをどうぞ。 続きを読む RVMでRuby環境の切り替えを簡単に!

トラブルシューティング – portsdb.rb で cross-thread violation on rb_gc()

ある日 portversion と portupgrade で ports をアップデートしようとしたところ、portsdb.rb で次のようなエラーが出るようになり portupgrade 関係のプログラムがまったく動作しなくなってしまった。

/usr/local/lib/ruby/site_ruby/1.8/portsdb.rb:116:[BUG] cross-thread violation on rb_gc()
ruby 1.8.6 (2007-09-24) [i386-freebsd7]
 
SIGABRT (Abort trap: 6)

ちなみに環境は FreeBSD 7.0 + ruby_1.8.6_p111_2,1。
ports から ruby, portupgrade 入れなおしても
ソースを辿ったところ, libpthread が有効になっている時のみこのエラーが出るようになっているということが判明したため、

# cd /usr/ports/lang/ruby18
# make config

で LIB_PTHREAD を無効化した上で make install しなおしたところ無事解決しました。

ruby でランダムな文字列を生成

“ランダムなパスワードを生成する” の ruby バージョン。
[2005-04-25] (JavaScript 版)
[2005-05-31] (PHP 版)

# ランダムな文字列を生成する。
# 引数 _length_ を指定すると生成桁数を指定することができます(デフォルト 8 桁)。
def getRandomString (length = 8)
  source=(“a”..”z”).to_a + (“A”..”Z”).to_a + (0..9).to_a + [“_”,”-“,”.”]
  key=””
  length.times{ key+= source[rand(source.size)].to_s }
  return key
end
 
# 10 桁の文字列を取得
p getRandomString 10

FreeBSD6 + jail + httpd22 + fcgid/fastcgi + Ruby on Rails

久しぶりにものすごくはまったのでメモ。
 
目的:
FreeBSD jail 上の httpd + suexec 環境に ruby on rails を入れたが、
CGI で動かすと遅いので fcgi 対応にしたい。
 
手順:
– jail host の /etc/rc.conf に以下の記述を追加

sysvipc_enable=”YES”
jail_sysvipc_allow=”YES” # jail 環境で httpd を動かしている場合のみ追加

fastcgi を追加(ruby_fcgi 用)

$ wget http://www.fastcgi.com/dist/fcgi-2.4.1-SNAP-0311112127.tar.gz # http://www.fastcgi.com/dist/ の fastcgi の最新版
$ tar xvzf fcgi-2.4.1-SNAP-0311112127.tar.gz
$ cd fcgi-2.4.1-SNAP-0311112127
$ ./configure –prefix=/usr/local/fastcgi # /usr/local/fastcgi 以下に展開(*1)
$ sudo make install

ruby_fcgi を追加(gem install fcgi では each_cgi がないと怒られる場合があるため、ソースからビルド)

$ wget http://rubyforge.org/frs/download.php/11368/ruby-fcgi-0.8.7.tar.gz
$ tar xvzf ruby-fcgi-0.8.7.tar.gz
$ cd ruby-fcgi-0.8.7
$ ruby install.rb config — –with-fcgi-dir=/usr/local/fastcgi # (*1) で指定したフォルダ。(*1)で –prefix を指定しなかった場合、ここで config を実行しなくてよい。
$ sudo ruby install.rb

– mod_fcgid または mod_fastcgi をビルド/インストール
mod_fastcgi の場合:

$ wget http://www.fastcgi.com/dist/mod_fastcgi-2.4.6.tar.gz
$ tar xvzf mod_fastcgi-2.4.6.tar.gz
$ cd mod_fastcgi-2.4.6
$ cp Makefile.AP2 Makefile
$ make
$ sudo make install
$ # httpd2 が /usr/local/apache2 になければ Makefile を編集して top_dir を変更するか、次のようにする
$ sudo make top_dir=/opt/httpd/2.0.40
$ sudo make install top_dir=/opt/httpd/2.0.40

mod_fcgid の場合:

$ wget http://downloads.sourceforge.net/mod-fcgid/mod_fcgid.2.2.tgz?modtime=1185976592&big_mirror=0
$ tar xvzf mod_fcgid.2.2.tgz
$ cd mod_fcgid.2.2
$ make
$ sudo make install
$ # httpd2 が /usr/local/apache2 にない場合はmod_fastcgi の場合と同様の手法で top_dir 変数を変更する。

– mod_fcgid または mod_fastcgi を httpd にロード/設定
httpd.conf:

# mod_fastcgi を使う場合コメントアウト:
#LoadModule fastcgi_module modules/mod_fastcgi.so
<IfModule fastcgi_module>
   AddHandler fastcgi-script .fcgi
# ソケットの場所(省略時は httpd の log/fastcgi/ )
# FastCgiIpcDir /var/run/fastcgi
   FastCgiConfig -autoUpdate -idle-timeout 20 -killInterval 3600 -maxClassProcesses 2
   # suexec を使う場合必要
   FastCgiWrapper /usr/local/apache2/bin/suexec
</IfModule>
# mod_fcgid を使う場合コメントアウト:
#LoadModule fcgid_module modules/mod_fcgid.so
<IfModule fcgid_module>
   AddHandler fcgid-script .fcgi
   SocketPath /tmp/fcgidsock
   SharememPath /tmp/fcgidshm
   IPCCommTimeout 40
   IPCConnectTimeout 10
   # suexec を使う場合も使わない場合も FCGIWrapper は設定しなくてよい
</IfModule>
 
# suexec 例(SuexecUserGroup が肝):
<VirtualHost 192.168.10.123>
    ServerAdmin webmaster@example.com
    DocumentRoot /usr/local/apache2/htdocs/
    ServerName example.com
    SuexecUserGroup john web
</VirtualHost>

 
– rails の設定を変更
{rails_root}/public/.htaccess

– AddHandler fastcgi-script .fcgi
– RewriteRule ^(.*)$ dispatch.cgi [QSA,L]
+ RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
– DefaultInitEnv RAILS_ENV development
+ SetEnv RAILS_ENV development

DefaultInitEnv とか SetEnv で変数がわたらない環境の場合は
{rails_root}/config/environment.rb の次の項目をコメントアウトして編集する

# Uncomment below to force Rails into production mode when
# you don’t control web/app server and can’t set it the proper way
#ENV[‘RAILS_ENV’] ||= ‘production’

 
– エラーが出る場合のヒント
http://ontherails.jp/2007/10/13/25 などを参考に。
ログファイルを見る:

httpd の error_log, suexec_log
rails の log/fastcgi.crash.log, log/development.log, log/production.log

など。
特に fastcgi/fcgid をかませた時のみ

Application error
Rails application failed to start properly

とページ表示される場合は rails の fastcgi のログを見るのが有効そうです。
 
参考:
configuration – The mod_fcgid Home Page
Apache2 + fcgid + Ruby on Railsメモ – sakuramateo
FreeBSD + Apache2 + mod_fcgid + Ruby On Rails(ふわふわな毎日)
_ fcgid(valda’s diary)
FastCGI 化(ふぇみにん日記)
Rails Apache + FastCGI 環境構築のはまりパターン
lighttpd + fcgi で each_cgi なるメソッドは知らないといわれる(Don’tStopMusic)

Ruby on Rails はじめの一歩

今更ですが、最近ようやく Rails を触ってみました。
 
10分で作る Rails アプリ for Windows
– Ruby on Rails 公式 – [http://www.rubyonrails.org/]
 
10 分でできる Rails アプリは、本当に 10 分で Ruby on Rails の手軽さが分かるのでお勧めです。
10分で作る…が Windows + MySQL なので,とりあえず FreeBSD で DB を使わない Hello World を表示する場合のメモを残しておきます。
 
あまりまとまったものではないですが..
 

 
1.Ruby + RubyGems をインストール
 FreeBSD の場合、Ruby, RubyGems のいずれも ports からインストール可能です(RubyGems は lang/ruby-extensions に含まれる)。

# portinstall lang/ruby lang/ruby-extensions

 
2. RubyGems の gem コマンドで Ruby on Rails をインストール

$ gem install rails

上のコマンドで一発インストール。依存関係について聞かれるのが嫌なら

$ gem install -y rails

とすればプロンプトなしでインストールされるはずです。
 
3.$rails アプリケーションサーバの構築

$ rails foo

このコマンドひとつで、カレントディレクトリに以下のものをすべてふくむフォルダ foo/ を作成します。
– 管理用スクリプト(script/)
  たとえば script/server はスタンドアロンサーバであり、
  script/generate は目的に応じたクラスやフォルダの自動生成を行うスクリプトです。
– 公開ディレクトリ(public/)
  実際の URL マッピングは public/.htaccess および、public/dispatches.cgi で行われています。
  rails サーバのデフォルトのトップページは public/index.html です。
  
-コントローラ格納フォルダ(app/controllers)
  MVC の controller 格納先
  サンプルとして最初からコントローラの雛型(app/controllers/Application.rb)が含まれています。
  コントローラ作成時はコマンド(scriot/generate controller <コントローラ名>) で作成すると便利です。
 
-ビュー格納フォルダ(app/views)
  MVC の view 格納先。
  ここに .rhtml (eRuby) 形式のテンプレートファイルで view を記述します。
-モデル格納フォルダapp/models)
  MVC の model 格納先。
  script/generate model <モデルクラス名> 等で作成したモデルが格納されます。
 
– 設定ファイル(config/)、
コントローラと URL のマッピングを設定する config/routes.rb,
アプリケーション上のすべての Ruby スクリプトに影響する環境設定を行う config/environment.rb,
MySQL 等のデータベース接続用の設定(アカウント、接続先 DB 名等)を設定する config/database.yml 等があります。
 
– アプリケーションで利用する追加 ruby ライブラリ格納フォルダ(lib/)
  ここにいれておくと ruby スクリプトでのrequire でパス指定なしで参照できるようになります。
  例: lib/my_library.rb があれば、rails アプリケーションからの参照時は require ‘my_library’ とするだけでよい。
 
4. コントローラ作成

script/generate controller Foo

  デフォルトでは HTTP リクエスト URL の最初のディレクトリ表記がコントローラ、次が呼び出すメソッド(action)となっています。
  たとえば

http://localhost:3000/foo/edit

へのアクセスは、ファイル app/controllers/foo_controller.rb の

FooController#edit()

が実行されます。
また、

http://localhost:3000/foo

のように、アクションを省略した場合は、Foo#index メソッドが呼び出されます。
一般的な Web サーバにおける index.html が、コントローラでは index メソッドとなると考えれば分かりやすいと思います。
 
 
5. Hello world を出力する(view, model を使わない場合)
ActionController::Base#render() を使うのが基本です。
具体的にはコントローラのアクション定義メソッド(例: FooController#index)を以下のようにします。
app/controllers/foo_controller.rb

# 前略
def index
    render :text => “hello world!!”
end
# 後略

 
6.コントローラでテキストの出力を行う(view を使う場合)
まず以下のファイルを作成します。
app/views/foo/index.rhtml

<html>
 <head>
   <title>Hello Example</title>
 </head>
 <body>
 <%= @message %>
 </body>
</html>

次に、さきほどのfoo_controller.rb の def index を次のように書き換えれば自動的に index.rhtml を参照します。

def index
   @message = “Hello, world!”
   render
end

具体的には、参照される view のファイル名は

app/<コントローラ名>/<アクション名>.rhtml

です。

yield

– 処理を場合に応じて自由に変えられる。スマートになった Visitor パターンみたいなものかなぁ..
イテレーションを Iterator パターンなしでできる(内部で Iterator パターンを使って外には each メソッドを公開する等)。

class Iterator
  @values
  @nIndex
  
  def initialize(*values)
    @values = values.dup
    @nIndex = 0
  end
  
  def each
    yield(getNext) while hasNext
  end
  
  def hasNext
    return @nIndex < @values.size
  end
   
  private :hasNext
   
  def getNext
    throw RangeError.new(“no element for next”) if !hasNext
    
    res = @values[@nIndex]
    @nIndex += 1
    return res
  end
  
  private :getNext
end
 
iterator = Iterator.new(0,1,2,3,4)
iterator.each{ |i|
  print( i * 2, “, ” )
}
# result:
# 0, 2, 4, 6, 8,
#

この例はそのまま [0,1,2,3,4].each{|i| … } とした時の動作と同じだけど、マスターデータが膨大になりうる時などは自分で yield するメソッドを実装するとコスト削減になってよい。
 
参考:
<http://www.ruby-lang.org/ja/man/?cmd=view;name=%A5%E1%A5%BD%A5%C3%A5
%C9%B8%C6%A4%D3%BD%D0%A4%B7#yield
>

可変長引数メソッド

def foo ( *args )

のように引数を一つだけ、最初に * をつけて定義すると、引数を配列(Array インスタンス)として扱える。

  def main(* args)
    print args.size, ” arguments: “
    args.each { |i|
      print i, “, “
    }
    print “\n”
  end
  
  main(1,2,3)
  main(“foo”, 2)
  main()
# result:
# 3 arguments: 1, 2, 3,
# 2 arguments: foo, 2,
# 0 arguments:
#