• 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
 
 

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

   1  % bundle exec unicorn

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

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

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

   1  % rvm gemset create foo-app

作成したgemsetは

   1  % rvm gemset use foo-app

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

   1  % gem list
   2  
   3  *** LOCAL GEMS ***
   4  
   5  bundler (1.0.2)
   6  rake (0.8.7)

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

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

   1  % bundler install --system

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

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

   1  rvm use ruby-1.8.7-p302@foo-app

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

Bye bye gem hell!

posted by Png genki on Sat 28 May 2011 at 21:49

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

   1  def foo
   2    puts "hello world :-)"
   3  rescue
   4    puts "something wrong :'-("
   5  end

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

   1  def foo(bar = 0)
   2    puts bar
   3    raise 
   4  rescue
   5    bar += 1
   6    retry if bar < 10
   7  end
   8  
   9  foo

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

   1  0
   2  1
   3  2
   4  3
   5  4
   6  5
   7  6
   8  7
   9  8
  10  9

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

request.host などがちゃんとリモートホストのドメイン名を指すように、 以下のように設定します。

   1  location / {
   2    # ..snip..
   3  
   4    proxy_redirect     off;
   5    proxy_set_header   Host             $host;
   6    proxy_set_header   X-Real-IP        $remote_addr;
   7    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
   8  
   9    # ..snip..
  10  }

ちょっと設定を忘れていてRSS中のGUIDがlocalhsotを指すという問題が発生しておりました。現在は復旧しております。 ご不便をおかけいたしましたことをお詫びいたします。

posted by Png genki on Wed 25 May 2011 at 23:13

またプロセスがハングアップする問題が発生したため、システム構成を見直し。 passengerからunicornに切り替えました。 正確な構成は、

  • rails-2.3.11
  • rack-1.1.2
  • unicorn-3.6.2
  • nginx-1.0.0

という感じです。

unicornのマスタープロセスのPIDを取得するために、以下のようなスクリプトを使ってます。

unicorn_master.rb

   1  port = ARGV.shift
   2  pids = `lsof -i:#{port} | awk "{print \\$2}"`.split("\n")[1..-1]
   3  pids.each do |pid|
   4    puts pid if `ps --ppid #{pid}`.split("\n").size > 1
   5  end
   6  
   7  # USAGE:
   8  #   ruby unicorn_master.rb <#port>

またしばらく様子をみてみます。

posted by Png genki on Wed 25 May 2011 at 13:05

rackupしようとすると、1.3.0と1.1.0でコンフリクトして無理、というお馴染みのメッセージが出ていて困ったのですが、bundlerを使っている場合、

   1  % bundle exec rackup

すればOKなようだ。

posted by Png genki on Wed 25 May 2011 at 09:23

古いRailsアプリをBundler仕様にする場合、

   1  config.gem "foo",
   2    :version => "0.0.1",
   3    :lib => "bar",
   4    :source => "http://gems.github.com"

と等価なGemfileの記述方法は

   1  source "http://gems.github.com"
   2  gem "foo", "0.0.1", :require => "bar"

で良いようです。バージョン指定をしない場合は第二引数を省略可。

posted by Png genki on Wed 25 May 2011 at 08:10

本日の午前中、比較的長期間当ブログにアクセス出来ない状態が発生しておりました。ご不便をおかけいたしましたことをお詫びいたします。

原因としては、Railsプロセスが暴走していたことが考えられます。 そのため、当blogで使用しているRailsのバージョンを 2.3.5から2.3.11に アップグレードいたしました。 またしばらく様子を見て対応を考えます。

よろしくお願いいたします。

posted by Png genki on Sun 15 May 2011 at 04:38

Rubygemsが新しすぎると、掲題のようなエラーが出る場合があります。 とりあえず回避するには

   1  # gem update --system 1.6.2

までダウングレードすればok

posted by Png genki on Sun 15 May 2011 at 04:19

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

   1  # gem update --system 1.7.1

posted by Png genki on Sun 15 May 2011 at 04:05

溶けたiPhone事件の後、新しいiPhoneにしてからエラーが出だしたのですが、これのお陰でバックアップが出来なくなってしまいました。
で、バックアップに失敗するので、iOSのアップデートにも失敗するという事になってしまい………ついに解決を目指す事に。

iOSのアップデート失敗時に下記を見るように指示されたので、Resolutionの項を一つ一つ試して行きます。

Update and restore alert messages on iPhone, iPad, and iPod touch
http://support.apple.com/kb/TS1275

でもだめです、解決しません。
アップデートをする際に、ステップの一部としてバックアップをするようになっているのですが、そこで失敗しているようです。

というわけで、まずはバックアップが成功するのを目指すことにしました。
ですが通常のバックアップも(ちゃんと)失敗して、下記のメッセージが表示されてしまいます…:

itunes_error_sync_services.png

iTunes was unable to load dataclass information from Sync Services. Reconnect or try again later.

メッセージ内容で検索してみたら下記が出てきました。 2008年7月の質問ですが、返信の中に「治ったー!」という報告がいくつかあったので試してみることに。

MacRumors Forums:"iTunes was unable to load dataclass information from Sync Services.... Jul 17, 2008, 03:42 AM
http://forums.macrumors.com/showthread.php?t=524354

回答として挙げられていたのは下記のリンク。

iTunes: How to remove and reinstall the Apple Mobile Device Service on Mac OS X
http://support.apple.com/kb/HT1747?viewlocale=en_US

下の方にある、OS XのApple Mobile Device Serviceを削除・再インストールする方法をやってみました。ざっくりと訳します。

OS XのApple Mobile Device Serviceを削除・再インストールする方法

  1. iPhone、iPad、iPodをMacと繋がっているケーブルから外す
  2. FinderでApplicationsフォルダ内にあるiTunes.appファイルをごみ箱に捨てる。iTunesアイコンも捨てる。
  3. FinderのメニューでGo > Go to Folderを選択、下記を開く:
    /System/Library/Extensions

  4. AppleMobileDevice.kextファイルをごみ箱に捨てる

  5. FinderのメニューでGo > Go to Folderを選択、下記を開く:
    /Library/Receipts/

  6. AppleMobileDeviceSupport.pkgファイルをごみ箱に捨てる。認証ダイアログが出てきたら、administratorパスワードを入力する。
    注意:Mac OS X v10.6以降の場合は、このファイルがないかもしれない。その場合は次のステップへ。

  7. Macを再起動する
  8. FinderメニューでFinder > Empty Trashを選択、Macを再起動する。
  9. iTunesの最新版をダウンロード、再インストール。
  10. Macにデバイスを接続して、iTunesを開く

さてこの作業後、iPhoneを接続してみたら…みごとバックアップも成功、iOSも更新できました!

posted by Png satoko on Wed 11 May 2011 at 05:58 with 1 comment