diff --git a/lib/annotate/annotate_models.rb b/lib/annotate/annotate_models.rb index fc503839..6e7d4c94 100644 --- a/lib/annotate/annotate_models.rb +++ b/lib/annotate/annotate_models.rb @@ -149,7 +149,7 @@ def get_schema_info(klass, header, options = {}) cols.each do |col| col_type = get_col_type(col) attrs = get_attributes(col, col_type, klass, options) - col_name = if with_comments?(klass, options) && col.comment + col_name = if with_column_comments?(klass, options) && col.comment "#{col.name}(#{col.comment.gsub(/\n/, "\\n")})" else col.name @@ -182,13 +182,16 @@ def get_schema_info(klass, header, options = {}) end def get_schema_header_text(klass, options = {}) + table_comment = with_table_comments?(klass, options) ? "(#{klass.connection.table_comment(klass.table_name).gsub(/\n/, "\\n")})" : "" + table_name = klass.table_name.to_s + table_comment + info = "#\n" if options[:format_markdown] - info << "# Table name: `#{klass.table_name}`\n" + info << "# Table name: `#{table_name}`\n" info << "#\n" info << "# ### Columns\n" else - info << "# Table name: #{klass.table_name}\n" + info << "# Table name: #{table_name}\n" end info << "#\n" end @@ -755,16 +758,22 @@ def classified_sort(cols) private - def with_comments?(klass, options) + def with_column_comments?(klass, options) options[:with_comment] && klass.columns.first.respond_to?(:comment) && klass.columns.any? { |col| !col.comment.nil? } end + def with_table_comments?(klass, options) + options[:with_comment] && + klass.connection.respond_to?(:table_comment) && + klass.connection.table_comment(klass.table_name).present? + end + def max_schema_info_width(klass, options) cols = columns(klass, options) - if with_comments?(klass, options) + if with_column_comments?(klass, options) max_size = cols.map do |column| column.name.size + (column.comment ? width(column.comment) : 0) end.max || 0 diff --git a/spec/lib/annotate/annotate_models_spec.rb b/spec/lib/annotate/annotate_models_spec.rb index c813139a..a5424c02 100644 --- a/spec/lib/annotate/annotate_models_spec.rb +++ b/spec/lib/annotate/annotate_models_spec.rb @@ -41,16 +41,17 @@ def mock_foreign_key(name, from_column, to_table, to_column = 'id', constraints on_update: constraints[:on_update]) end - def mock_connection(indexes = [], foreign_keys = []) + def mock_connection(indexes = [], foreign_keys = [], table_comment = nil) double('Conn', indexes: indexes, foreign_keys: foreign_keys, - supports_foreign_keys?: true) + supports_foreign_keys?: true, + table_comment: table_comment) end - def mock_class(table_name, primary_key, columns, indexes = [], foreign_keys = []) + def mock_class(table_name, primary_key, columns, connection = mock_connection) options = { - connection: mock_connection(indexes, foreign_keys), + connection: connection, table_exists?: true, table_name: table_name, primary_key: primary_key, @@ -217,7 +218,7 @@ def mock_column(name, type, options = {}) end let :klass do - mock_class(:users, primary_key, columns, indexes, foreign_keys) + mock_class(:users, primary_key, columns, mock_connection(indexes, foreign_keys, table_comment)) end let :indexes do @@ -228,6 +229,10 @@ def mock_column(name, type, options = {}) [] end + let :table_comment do + [] + end + context 'when option is not present' do let :options do {} @@ -400,7 +405,7 @@ def mock_column(name, type, options = {}) end let :klass do - mock_class(:posts, primary_key, columns, indexes, foreign_keys).tap do |mock_klass| + mock_class(:posts, primary_key, columns, mock_connection(indexes, foreign_keys)).tap do |mock_klass| allow(mock_klass).to receive(:translation_class).and_return(translation_klass) end end @@ -1061,6 +1066,60 @@ def mock_column(name, type, options = {}) { with_comment: 'yes' } end + context 'when table have comments' do + let :table_comment do + 'users table comment' + end + + let :columns do + [ + mock_column(:id, :integer, limit: 8), + ] + end + + let :expected_result do + <<~EOS + # Schema Info + # + # Table name: users(users table comment) + # + # id :integer not null, primary key + # + EOS + end + + it 'works with option "with_comment"' do + is_expected.to eq expected_result + end + end + + context 'when table have multiline comments' do + let :table_comment do + "Notes.\nUsers table comment" + end + + let :columns do + [ + mock_column(:id, :integer, limit: 8), + ] + end + + let :expected_result do + <<~EOS + # Schema Info + # + # Table name: users(Notes.\\nUsers table comment) + # + # id :integer not null, primary key + # + EOS + end + + it 'works with option "with_comment"' do + is_expected.to eq expected_result + end + end + context 'when columns have comments' do let :columns do [ @@ -1194,6 +1253,41 @@ def mock_column(name, type, options = {}) is_expected.to eq expected_result end end + + context 'when both table and columns have comments' do + let :table_comment do + 'users table comment' + end + + let :columns do + [ + mock_column(:id, :integer, limit: 8, comment: 'ID'), + mock_column(:active, :boolean, limit: 1, comment: 'Active'), + mock_column(:name, :string, limit: 50, comment: 'Name'), + mock_column(:notes, :text, limit: 55, comment: 'Notes'), + mock_column(:no_comment, :text, limit: 20, comment: nil) + ] + end + + let :expected_result do + <<~EOS + # Schema Info + # + # Table name: users(users table comment) + # + # id(ID) :integer not null, primary key + # active(Active) :boolean not null + # name(Name) :string(50) not null + # notes(Notes) :text(55) not null + # no_comment :text(20) not null + # + EOS + end + + it 'works with option "with_comment' do + is_expected.to eq expected_result + end + end end end end @@ -2570,14 +2664,14 @@ def annotate_one_file(options = {}) mock_column(:id, :integer), mock_column(:foreign_thing_id, :integer) ], - [], - [ - mock_foreign_key('fk_rails_cf2568e89e', - 'foreign_thing_id', - 'foreign_things', - 'id', - on_delete: :cascade) - ]) + mock_connection([], + [ + mock_foreign_key('fk_rails_cf2568e89e', + 'foreign_thing_id', + 'foreign_things', + 'id', + on_delete: :cascade) + ])) @schema_info = AnnotateModels.get_schema_info(klass, '== Schema Info', show_foreign_keys: true) annotate_one_file end @@ -2589,14 +2683,16 @@ def annotate_one_file(options = {}) mock_column(:id, :integer), mock_column(:foreign_thing_id, :integer) ], - [], - [ - mock_foreign_key('fk_rails_cf2568e89e', - 'foreign_thing_id', - 'foreign_things', - 'id', - on_delete: :restrict) - ]) + mock_connection( + [], + [ + mock_foreign_key('fk_rails_cf2568e89e', + 'foreign_thing_id', + 'foreign_things', + 'id', + on_delete: :restrict) + ] + )) @schema_info = AnnotateModels.get_schema_info(klass, '== Schema Info', show_foreign_keys: true) annotate_one_file expect(File.read(@model_file_name)).to eq("#{@schema_info}#{@file_content}")