# Support for enum. (Currently Mysql adapter only) # # add_column :animals, :name, :enum, :enum_values => %w(bunnitard wolphin orca), :default => 'wolphin', :null => false # unless defined?(MigrationEnumSupport) module MigrationEnumSupport module AbstractEnumSchema def self.included(base) base.class_eval do alias_method_chain :native_database_types, :enum unless method_defined?(:native_database_types_without_enum) alias_method_chain :add_column_options!, :enum unless method_defined?(:add_column_options_without_enum!) end end def native_database_types_with_enum types = native_database_types_without_enum types[:enum] = native_database_type_enum if respond_to?(:native_database_type_enum) types end def add_column_options_with_enum!(sql, options) add_enum_options!(sql, options) if options[:enum_values] add_column_options_without_enum!(sql, options) end def add_enum_options!(sql, options) enum_coulumn_sql options[:enum_values] if options[:enum_values] super end end #name other adapters the same as module MysqlAdapter def self.included(base) base.send :include, AbstractEnumSchema end #override for specific adapter if necessary def native_database_type_enum { :name => "enum" } end def enum_coulumn_sql(sql, options) enum_values = Array(options[:enum_values]).collect{|val| quote(val.to_s)}.join(', ') sql << "(#{enum_values})" end #parse the sql column definition to get the enumerated vals # ex. enum('a','b','c') def enum_sql_to_enum_vals(column) match = column.sql_type.match(/enum\s?\((.*)\)/) (match ? match[1].split(/,\s*/) : []) end end end #dirty filthy hack to fix the dumper #this is in place of replacing the really table method to account for enum module SchemaDumperReplace def self.included(base) base.class_eval do private alias_method_chain :table, :enum unless method_defined?(:table_without_enum) end end def table_with_enum(table_name, stream) table_stream = StringIO.new table_without_enum table_name, table_stream table_stream.rewind if (table_schema_txt = table_stream.read).include?(":string, :limit => 0") columns = @connection.columns(table_name) columns.each {|column| enum_vals = @connection.enum_sql_to_enum_vals column next if enum_vals.blank? table_schema_txt.gsub!("t.column \"#{column.name}\", :string, :limit => 0", "t.column \"#{column.name}\", :enum, :enum_values => #{enum_vals.inspect}" ) } end stream.print table_schema_txt end end #ActiveRecord::SchemaDumper.send(:include, SchemaDumperReplace) ActiveRecord::ConnectionAdapters::MysqlAdapter.send :include, MigrationEnumSupport::MysqlAdapter end