#!/usr/bin/ruby
=begin
  parser/activerecord.rb - parser for ActiveRecord

  Copyright (C) 2005  Masao Mutoh
 
  You may redistribute it and/or modify it under the same
  license terms as Ruby.

  $Id: activerecord.rb,v 1.5 2006/01/14 13:48:23 mutoh Exp $
=end

require 'gettext'
require 'gettext/parser/ruby'

include GetText

module GetText
  module ActiveRecordParser
    extend GetText
    include GetText
    GetText.bindtextdomain("rgettext")

    @config = {
      :db_yml => "config/database.yml",
      :db_mode => "development",
      :activerecord_classes => ["ActiveRecord::Base"],
      :use_classname => true,
    }

    @ar_re = nil

    module_function
    def require_rails(file)
      begin
	require file
      rescue MissingSourceFile
	$stderr.puts _("'%{file}' is not found.") % {:file => file}
      end
    end

    def init(config)
      if config
	config.each{|k, v|
	  @config[k] = v
	}
      end
      @ar_re = /class.*(#{@config[:activerecord_classes].join("|")})/
    end

    def parse(file, targets = [])
      old_constants = constants
      begin
        eval(open(file).read)
      rescue
        $stderr.puts _("Ignored '%{file}'. Solve dependencies first.") % {:file => file}
        $stderr.puts $! 
      end
      loaded_constants = constants - old_constants
      loaded_constants.each do |classname|
	klass = eval(classname)
	if klass < ActiveRecord::Base
	  targets << [::Inflector.singularize(klass.table_name.gsub(/_/, " ")), "#{file}:-"]
	  tablename = klass.class_name
	  begin
	    klass.columns.each do |column|
	      if @config[:use_classname]
		targets << [tablename + "|" +  klass.human_attribute_name(column.name), "#{file}:-"]
	      else
		targets << [klass.human_attribute_name(column.name), "#{file}:-"]
	      end
	    end
	  rescue
	    $stderr.puts _("No database is available.")
	    $stderr.puts $!
	  end
	end
      end
      if RubyParser.target?(file)
	targets = RubyParser.parse(file, targets)
      end
      targets.uniq!
      targets
    end

    def target?(file)
      init(nil) unless @ar_re
      data = IO.readlines(file)
      data.each do |v|
	if @ar_re =~ v
	  unless @db
	    require 'rubygems'
	    require 'active_record'
	    yml = YAML.load(ERB.new(IO.read(@config[:db_yml])).result)
	    ENV["RAILS_ENV"] = @config[:db_mode]
	    require_rails 'config/boot.rb'
	    require_rails 'config/environment.rb'
	    require_rails 'app/controllers/application.rb'
	  end
	  return true
	end
      end
      false
    end
  end
end

if __FILE__ == $0
  # ex) ruby model1.rb model2.rb 
  ARGV.each do |file|
    if GetText::ActiveRecordParser.target?(file)
      p file
      p GetText::ActiveRecordParser.parse(file)
    end
  end
end