class DbDiscoveryGenerator < Rails::Generator::Base default_options :skip_migration => false def initialize(runtime_args, runtime_options = {}) super if options[:help] then usage exit end @no_fields = options['no_fields'] end def manifest record do |m| m.directory 'app/models' generate_models.each do |table, model| m.template 'model.rb', "app/models/#{table.singularize.underscore}.rb", :assigns => { :table_name => table.singularize.underscore.camelize, :model => model, :no_fields => @no_fields } end end end protected def add_options!(opt) opt.separator '' opt.separator 'Options:' opt.on("--no-fields", "Don't show a list of available fields") { |v| options[:no_fields] = v } opt.on("-h","--help", "Show this help message") { |v| options[:help] = v } end def mysql_primary_key (table_name, name = nil)#:nodoc: sql = "SHOW FIELDS FROM #{table_name}" pk = [] @connection.execute(sql, name).each do |field| pk << field[0] if field[3] == 'PRI' end if pk.length > 1 then '' else pk[0] end end def generate_models @connection = ActiveRecord::Base.connection models = {} @connection.tables.each do | table | # Model class, unit test, and fixtures. if table =~ /[A-Z]/ then set_table_name = " self.table_name = %( #{@connection.quote_column_name(table)} )" else set_table_name = " self.table_name = \"#{table}\"" end columns = @connection.columns(@connection.quote_column_name(table)) adapterName = @connection.adapter_name pk = '' case adapterName when 'PostgreSQL' then pk, seq = @connection.pk_and_sequence_for(@connection.quote_column_name(table)) pk ||= '' when 'MySQL' then pk = mysql_primary_key(@connection.quote_column_name(table)) end models[table] = { :table => table, :columns => columns, :primary_key => pk, :table_name => set_table_name } end models.each do |table, model| model[:columns].each do |c| next if c.name.nil? next if model[:primary_key] && c.name == model[:primary_key] next if c.name !~ /^(.+)(?:_id|ID)$/ master = $1 master_model = models[master.pluralize] || models[master] if master_model then model[:belongs_to] = [] if model[:belongs_to].nil? model[:belongs_to] << master.singularize.underscore # TODO: Distinguish between has_one and has_many # TODO: HABTM - hint (relation)_(relation) master_model[:has_many] = [] if master_model[:has_many].nil? master_model[:has_many] << table.pluralize.underscore end end end models end end