views:

81

answers:

1

I'd like to insert COMMENT, which is part of SQL the command, in my migration files.

As far as I know, I can add COMMENT to each table and column.

I can't remember a plugin name that lets me to write as follows:

    t.string  :name, :comment => "A user's fullname"
    t.string  :label, :comment => "name of color"
    t.text  :value, :comment => "self intro"
    t.integer  :position, :comment => "1 is left, 2 is right"

And that statement magically is translated into SQL, which is like

create table test (
  name varchar(255) not null COMMENT 'blahblah',
  label varchar(255) null COMMENT 'hahaha'
  text varchar(255) not null,
  position int(11)
);

Does anybody know the plug in name?


+2  A: 

I don't know of any plugin that will accomplish what you're asking for. You might be able to hack in what you want by looking at ActiveRecord::ConnectionAdapters::ColumnDefinition. (See active_record/connection_adapters/abstract/schema_definitions.rb.)

As you can see the Struct defines the various column options (like :limit and :default.) You could extended that struct with a :comment and then modify #to_sql to generate the required SQL. You would also need to modify TableDefinition#column to set the :comment attribute.

The following has been tested and works (for MySQL):

module ActiveRecord
  module ConnectionAdapters
    class ColumnDefinition
      attr_accessor :comment

      def to_sql_with_comment
        column_sql = to_sql_without_comment
        return column_sql if comment.nil?
       "#{column_sql} COMMENT '#{base.quote_string(comment)}'"
      end

      alias_method_chain :to_sql, :comment
    end

    class TableDefinition
      # Completely replaces (and duplicates the existing code, but there's
      # no place to really hook into the middle of this.)
      def column(name, type, options = {})
        column = self[name] || ColumnDefinition.new(@base, name, type)
        if options[:limit]
          column.limit = options[:limit]
        elsif native[type.to_sym].is_a?(Hash)
          column.limit = native[type.to_sym][:limit]
        end
        column.precision = options[:precision]
        column.scale = options[:scale]
        column.default = options[:default]
        column.null = options[:null]
        column.comment = options[:comment]
        @columns << column unless @columns.include? column
        self
      end
    end
  end
end
rjk
Thanks! Your answer is amazing. I haven't test your code, either. But I'll take your approach.
TK
It seems that the code isn't working.
TK
Which part isn't working? Did you add any logging to see if the methods are being called?
rjk
It didn't give me any error. But when I log into MySQL and type `show create table users`, it doesn't show `COMMENT` stuff. I haven't add any logging, I'll try adding some.
TK
Where have you defined `to_sql_without_comment`?
TK
The `alias_method_chain` defines the `to_sql_without_comment` method as being an alias to the _old_ `to_sql` method. See the documentation from `ActiveSupport::CoreExtensions::Module`.
rjk
@TK There was a spelling mistake in the example code. I've fixed it and confirmed that it does work when I placed the above code in `config/initializers/comment_migration.rb`. They only _gotcha_ is that the above code does not escape single-quotes, so your "A user's full name" generates a parse error. That should be easy enough to fix.
rjk
@TK And I've now updated the code to quote the comment string correctly, so the "A user's full name" is accepted and generates correct SQL.
rjk
Thanks. I can confirm that your code works.
TK