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