仕事の Rails なアプリケーションが昔からあってバージョンが 2.0.2 くらいだったけれど、Rails3 も無事リリースされているし、そろそろ重い腰を上げてバージョンアップしないといかんと思って、まずは 2.3.11 へバージョンアップしてみたときの話。メジャーバージョンが 2 系のままなので、それほど大変ではなかったけれど、既存で使っている gem の差し替えがけっこう大変だった。
まずは、config/environment.rb を、次のように変更する。
RAILS_GEM_VERSION = '2.3.11' unless defined? RAILS_GEM_VERSION
Rails 2.3 から、bundler がサポートされているので、公式ページをみながら作業する。config/preinitializer.rb を作成して、RAILS_ROOT に Gemfile を作成する。Gemfile は、仕事の環境では自前の gem を含めた gem のミラーを作成してあるので、gem のインストール先を変更してあります。下記の URL は例です。
Gemfile
source 'http://rubygems.example.com/rubygems'
gem 'rails', '2.3.11'
gem 'mysql', '2.8.2'
gem 'nokogiri', '1.4.4'
gem 'rmagick', '2.13.1', :require => 'RMagick'
gem 'will_paginate', '2.3.15'
そして、RAILS_ROOT で bundle install するだけだけれど、mysql gem が mysql_config コマンドの場所が分からなくてエラーになってしまうので、事前に次のコマンドを実行する。
$ cd RAILS_ROOT
$ bundle config build.mysql --with-mysql-config=/usr/bin/mysql_config
これで bundle install すれば、Rails 2.3.11 がインストールされる。bundler を使えば、ちゃんと特定のバージョンの gem を使ってくれるし、RAILS_ROOT 以下に gem がインストールされるし、サーバ側で gem を管理しなくても済むので、とても便利です。(今まで一生懸命 puppet manifest に記述してあったので、ごそっと削除した。)サーバ側で管理する gem は、bundler と passenger くらいになった。
Rails アプリケーションをバージョンアップするのも忘れずに。
$ rake rails:update
次に、既存の gem を入れ替え作業にした。まずは、データベースまわりは仕事環境で 2 系統の mysql master – slave 構成になっているため、Rails 2.0 の頃は ActiveRecord cluster というのを使っていた。このライブラリはもうメンテナンスされていないので、探してみたところ data_fabric という gem を見つけた。この他にも 1 系統の master – slave 構成をサポートしている gem は見つかったけれど、2 系統の master – slave 構成をサポートしているのは data_fabric だけの様子だった。
data_fabric の使い方は、github のページに詳しく書かれているし、サンプルの Rails アプリケーションもあるので、すぐに使うことができると思う。まず、Gemfile に、data_fabric を使うように追加する。
gem 'data_fabric', '1.3.1'
database.yml は、次のようにする。次の例では、メイン系統のデータベース(master: 192.168.1.1, slave: 192.168.1.2)と cluster1 という系統のデータベース(master: 192.168.1.10, slave: 192.168.1.11)が、それぞれ master – slave 構成存在している場合の設定方法です。いくつか設定が重複しまうのは微妙だけれど、これは仕方がない。
development:
adapter: mysql
database: test_dev
host: localhost
username: root
password:
encoding: utf8
hoge_development:
adapter: mysql
database: test_dev
host: localhost
username: root
password:
encoding: utf8
production:
adapter: mysql
database: test_production
host: 192.168.1.1
username: hoge
password: hoge_password
encoding: utf8
production_master:
adapter: mysql
database: test_production
host: 192.168.1.1
username: hoge
password: hoge_password
encoding: utf8
production_slave:
adapter: mysql
database: test_production
host: 192.168.1.2
username: hoge
password: hoge_password
encoding: utf8
cluster1_production:
adapter: mysql
database: cluster1_production
host: 192.168.1.10
username: hoge
password: hoge_password
encoding: utf8
cluster1_production_master:
adapter: mysql
database: cluster1_production
host: 192.168.1.10
username: hoge
password: hoge_password
encoding: utf8
cluster1_production_slave:
adapter: mysql
database: cluster1_production
host: 192.168.1.11
username: hoge
password: hoge_password
encoding: utf8
application_controller.rb に、次のコードを追加する。
around_filter :select_shard
private
def select_shard(&block)
yield
end
開発環境のときは slave がないため、その設定を吸収する関数を定義しておく。
def get_replicated
(RAILS_ENV == 'production') ? true : false
end
あとはモデルを ActiveRecord Cluster を使った記述から data_fabric を使った記述に変更するだけとなる。
メイン系統のモデルは、次のようにする。
class Model1 < ActiveRecord::Base
data_fabric :replicated => get_replicated
...
end
cluster1 系統のモデルは、次のようにする。prefix をつけるだけ。
class Model10 < ActiveRecord::Base
data_fabric :prefix => 'cluster1', :replicated => get_replicated
end
そして、Passenger で動かすと「undefined method disconnect! at DataFabric::PoolProxy」というエラーが出てしまうということで作者の人に問い合わせてみたら、すぐにバージョンアップ(バージョン 1.3.1)にしてくれた。このバージョンで問題なく、Rails 2.3.11 + Passenger の環境で今でもちゃんと動いている。
次に gettext まわり、Rails 2.3 だと i18n という仕組みを使う方式に変更になっている。既存の gettext の仕組みを使う必要があったので、Gemfile に次の gem を追加した。
gem 'gettext', '2.1.0'
gem 'gettext_activerecord', '2.1.0'
gem 'gettext_rails', '2.1.0'
gem 'i18n', '0.5.0'
gem 'locale', '2.0.5'
gem 'locale_rails', '2.0.5'
さらに application_controller.rb に、次を追加した。
init_gettext "hoge"
before_filter :set_locale_info
def set_locale_info
set_locale("ja")
end
この他、最初に読み込まれる方法がかなり変わっていたので、config/environement.rb や config/initializers を整理した。
あと db の migrate ファイル名の形式が変わっているので、念のため既存の db migrate のファイル名を変更する即興プログラムを書いて対応した。もちろん、本番サーバでは db:migrate はリスクが大きすぎて実行はしていない。
あわせて、schema_info テーブルから schema_migrations テーブルに変わっているため、念のため本番サーバを修正しておく必要がある。
schema_migrations テーブルを作成する。
mysql> CREATE TABLE `schema_migrations` (`version` varchar(255) NOT NULL) ENGINE=InnoDB
drop table schema_info;
そして、また即興プログラムで db/migrate にあるファイル名を取得してバージョン情報を追加するプログラムを本番サーバで実行する。
こんな感じで、無事 Rails 2.0 系から Rails 2.3 系にバージョンアップすることができた。
次のターゲットは、Rails 2.3 系から 3.1 系へのバージョンアップを行う予定。
Recent Comments