Last Updated 2014-10-03
開発マシンがWindowsで、本番サーバーがLinuxということは良くあります。 そのような状況の場合、データベースの作成や修正をWindowsではバッチファイルでやり、 Linuxではシェルスクリプトを今まで使っていました。しかし、WindowsとLinuxにRubyが インストールされていればRakeが使用できるので、RakefileをWindowsとLinuxの両方で 動作するように書けば良いと思い、作ってみました。
また、どうせ作るならrailsのRakeのコマンドに似せようと思って、似たようなコマンドにしました。
PostgreSQLとMySQLの両方に対応したRakefileのサンプルを作成しました。
PASSWORD = "" DBNAME = "mydb_test" MIGRATE_DDL = "test.ddl" MYUSER = "root" PGUSER = "postgres" if /windows/i =~ ENV['OS'] then MYPATH = "C:\\xampp\\mysql\\bin\\" PGPATH = "\"c:/Program Files/PostgreSQL/8.3/bin/\"" else MYPATH = "" PGPATH = "" end load File.join(File.dirname(__FILE__), 'rakefile.mysql') load File.join(File.dirname(__FILE__), 'rakefile.psql') task :default => [ "myql:default" ]
このRakefileは以下のMySQL用とPostgreSQL用のタスクの定義ファイルを読み込んでいます。
開発やテスト等では1ファイルの方が便利なので、1つにまとめたRakefileも作成しました。
サンプルでは以下のように使用します。
rakeのみで実行すると、defaultのタスクが実行されます。このサンプルでは mysqlのdefaultタスクが実行され、mysql:create => mysql:migrate => mysql:drop の順に実行されます。
> rake上記を実行すると、データベースへ接続するパスワード入力を求められます。 パスワード(以下の例では"dbpass")を入力すると3つのタスク、mysql:create、mysql:migrate、mysql:dropが順番に実行されます。
C:\ruby\work\test\rake>rake (in C:/ruby/work/test/rake) input database password dbpass C:\xampp\mysql\bin\mysql -u root -e "create database mydb_test" C:\xampp\mysql\bin\mysql -u root -D mydb_test < test.ddl C:\xampp\mysql\bin\mysql -u root -e "drop database mydb_test"パスワード入力を毎回したくない場合は、Rakefileの先頭の
PASSWORD = "" ・・・の箇所にパスワードを設定しておきます。
MySQL用のタスクを指定して実行する場合は以下のようになります。
> rake mysql:[タスク名]
> rake mysql:create
PostgreSQL用のタスクを実行する場合は以下のようになります。
> rake psql:[タスク名]
C:\ruby\work\test\rake>rake psql:default (in C:/ruby/work/test/rake) input database password dbpass "c:/Program Files/PostgreSQL/8.3/bin/"createdb -U postgres mydb_test "c:/Program Files/PostgreSQL/8.3/bin/"psql -U postgres -d mydb_test < test.ddl CREATE TABLE "c:/Program Files/PostgreSQL/8.3/bin/"dropdb -U postgres mydb_test
このRakefileのタスクの一覧は以下になります。
C:\ruby\work\test\rake>rake -T (in C:/ruby/work/test/rake) rake mysql:create # create database rake mysql:databases # show databases rake mysql:desc[table_name] # describe table (mysql:desc[TABLENAME]) rake mysql:drop # drop database rake mysql:exec[query] # execute query (mysql:exec["QUERY"]) rake mysql:migrate # migrate database rake mysql:tables # show tables rake psql:create # create database rake psql:databases # show databases rake psql:desc[table_name] # describe table (psql:desc[TABLENAME]) rake psql:drop # drop database rake psql:exec[query] # execute query (psql:exec["QUERY"]) rake psql:migrate # migrate database rake psql:tables # show tables (\d)
データベース一覧、テーブル一覧や、テーブルの詳細の表示はよく使用するので、タスクとして登録しています。
$ rake mysql:desc[access] (in /home/uname/ruby/rake) input database password mysql -u root -D mydb_test -e "desc access" +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id | int(11) | YES | | NULL | | | name | text | YES | | NULL | | +-------+---------+------+-----+---------+-------+
タスクを指定しない場合は、:defaultタスクが実行されます。 サンプルでは3つのタスクの実行が指定されています。 その指定をしている部分を抜き出すと以下のようになります。
task :default => [ :"mysql:default" ] namespace :mysql do task :default => [:create, :migrate, :drop] end実行されると最初に task :default => [ :"mysql:default" ] が実行され、次に [ :"mydb:default" ] の部分から namespace :mysql のtask :default => [:create, :migrate, :drop] が実行されます。
task :default => [ :"mysql:default" ] namespace :mysql do task :default => [:migrate] end
データベース名は以下の3か所のどれかで指定できます。複数指定されている場合は以下の上位側が優先されます。
データベース名を決定している箇所を抜き出すと以下になります。 以下の例では定数DBNAMEに定義されているのが使用されます。
DBNAME = "mysql_test"
ENV_MYDBNAME = "mysql_dbname"
def get_mysql_dbname()
if DBNAME && !DBNAME.empty? then
return DBNAME
elsif ENV.include?(ENV_MYDBNAME) then
return ENV[ENV_MYDBNAME]
else
puts "input database name"
dbname = STDIN.gets
ENV[ENV_MYDBNAME] = dbname.chop
return ENV[ENV_MYDBNAME]
end
end
実行時に入力したい場合は以下のように定数DBNAMEを変更します。
環境変数dbnameが指定されていなければ dbname = STDIN.gets が実行されて入力が要求されます。
DBNAME = ""
現在使用しているOSは環境変数で判別することができます。 例えば、WindowsXPのDOS窓では環境変数OSに”Windows_NT”が設定されているので、以下のようにチェックすれば Windowsとその他のOSの区別することもできると思います。
if /windows/i =~ ENV['OS'] then
・・・
end
Rakeにはwin23.rbでWindowsかどうかを判断するメソッドがあるので、それを使用する方法もあります。
if Rake::Win32.windows? then
PGPATH = "\"c:/Program Files/PostgreSQL/8.3/bin/\""
else
PGPATH = ""
end
その他として、RUBY_PLATFORMにプラットホームを示す文字列が入っているようなので、 これでチェックする方法もあります。
if /cygwin/i =~ RUBY_PLATFORM then
・・・
end
ただし、この方法ではWindows版rubyを上手く判別できない可能性があります。
Windows版rubyではバージョンが同じものが複数あり、そのそれぞれでRUBY_PLATFORMの文字列が異なります。
そのためWindows用rubyを変更した場合、想定していないRUBY_PLATFORMの文字列になるかもしれません。
ix86-mingw32 ix86-msdosdjgpp ix86-mswin32
参考 rake.rb (バージョン 0.8.7)では以下のようにunixとwindowsのチェックを分けています。
require 'rake/win32'
・・・
def unix?
RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
end
def windows?
Win32.windows?
end
さらにrake/win32.rb を調べると、環境変数APPDATAをチェックしてWindowsかどうかを判定していました。 そこでWindowsXPの環境変数APPDATAを確認すると、下記のようになっていました。([username]にはユーザー名が入ります)
APPDATA=C:\Documents and Settings\[username]\Application Data
module Rake
# Win 32 interface methods for Rake. Windows specific functionality
# will be placed here to collect that knowledge in one spot.
module Win32
class << self
# True if running on a windows system.
if File::ALT_SEPARATOR == '\\' # assume other DOSish systems are extinct.
def windows?; true end
else
def windows?; false end
end
end
class << self
# The standard directory containing system wide rake files on
# Win 32 systems. Try the following environment variables (in
# order):
#
# * APPDATA
# * HOME
# * HOMEDRIVE + HOMEPATH
# * USERPROFILE
#
# If the above are not defined, retruns the personal folder.
def win32_system_dir #:nodoc:
win32_shared_path = ENV['APPDATA']
if !win32_shared_path or win32_shared_path.empty?
win32_shared_path = '~'
end
File.expand_path('Rake', win32_shared_path)
end
# Normalize a win32 path so that the slashes are all forward slashes.
def normalize(path)
path.tr('\\', '/')
end
end if windows?
end
if Win32.windows?
def standard_system_dir
Win32.win32_system_dir
end
end
end