最近になって ruby を使うようになりました.
といっても週一ぐらいの頻度なのですが.
を読んでいて,ActiveRecord 便利だなー,とか思いながら使ってました.
そんな中で ruby の勉強がてら,マイグレーションのまねごとをしてみた次第です.
勉強は,既存のコードを読んで自分なりに実践してみるのが一番かと.
参考にさせていただいた情報
参照したファイル/ディレクトリ
ubuntu 8.04 です.
- /usr/share/rails/activerecord/lib/active_record/migration.rb
- マイグレーションの本体
- /usr/share/rails/activesupport/lib/active_support/core_ext/
- ruby の拡張が定義されている.
- /usr/share/rails/activesupport/lib/active_support/inflector.rb
- Inflectorの定義がある.
成果物
バッチ処理してみました.
/${BATCH_ROOT} ├ run.rb ← これを 'ruby run.rb' する ├ 001_ope1.rb ├ 002_ope2.rb ├ 003_ope3.rb ...
# 拡張 class String def camelize(upcase_first_letter = true) if upcase_first_letter then return self.gsub(/\/(.?)/) { '::' + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase } else return self.first + self.camelize()[1..-1] end end def constantize return Object.module_eval("::#{self.camelize}") end end # バッチ実行 class BatchExecutor def initialize(directory, exclude_paths, call_method) @directory, @exclude_paths, @call_method = directory, exclude_paths, call_method end def run(arguments = nil) collect_classes(@directory, @exclude_paths).each {|k| # 今回は number を無視 if arguments then k.new.send(@call_method, arguments) else k.new.send(@call_method) end } end private def collect_classes(directory, exclude_paths) klasses = collect_files(directory, exclude_paths).inject([]) {|ks, f| load(f) number, name = get_number_and_classname(File.basename(f)) ks << create_numbering_class(name, number.to_i) } return klasses.sort_by {|e| e.number } end def collect_files(directory, exclude_paths) files = [] Dir.glob(directory + '/*.rb').each {|f| files << f if !exclude_paths.include?(f) } return files end def get_number_and_classname(filename) return *filename.scan(/([0-9]+)_([_a-z0-9]*).rb/).first end def create_numbering_class(name, number) klass = name.camelize.constantize class << klass attr_accessor :number end klass.number = number return klass end end
何というか,やりたい放題っすね.
実行部分.
if $0 == __FILE__ then self_path = File.expand_path(__FILE__) directory = File.dirname(self_path) exclude_paths = [self_path] BatchExecutor.new(directory, exclude_paths, :run).run(['引数渡したよ']) end
ruby 書きやすいですね.