Class: Annotato::ColumnFormatter
- Inherits:
-
Object
- Object
- Annotato::ColumnFormatter
- Defined in:
- lib/annotato/column_formatter.rb
Class Method Summary collapse
-
.build_default_block(value) ⇒ Object
Returns nil for non-JSON/empty values, or an Array of un-indented inner lines for multiline formatting: e.g.
-
.format(model, connection) ⇒ Object
Main entry: returns an array of comment lines per column, flattened.
Class Method Details
.build_default_block(value) ⇒ Object
Returns nil for non-JSON/empty values, or an Array of un-indented inner lines for multiline formatting: e.g. [""A",", ""B""] for a JSON array.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/annotato/column_formatter.rb', line 70 def self.build_default_block(value) return nil if value.nil? || !value.is_a?(String) s = value.strip return nil unless s.start_with?("[") || s.start_with?("{") parsed = JSON.parse(s) rescue nil return nil unless parsed.is_a?(Array) || parsed.is_a?(Hash) if parsed.is_a?(Array) return nil if parsed.empty? # JSON array of strings parsed.map.with_index do |e, i| comma = i == parsed.size - 1 ? "" : "," %Q{"#{e}"#{comma}} end else return nil if parsed.empty? # JSON hash → key/value pairs parsed.map.with_index do |(k, v), i| comma = i == parsed.size - 1 ? "" : "," %Q{"#{k}": #{v.inspect}#{comma}} end end end |
.format(model, connection) ⇒ Object
Main entry: returns an array of comment lines per column, flattened.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/annotato/column_formatter.rb', line 8 def self.format(model, connection) table_name = model.table_name primary_key = model.primary_key unique_indexes = connection.indexes(table_name).select(&:unique) columns = connection.columns(table_name) # Collect native PG enum type names once up front (avoids N+1 queries). pg_enum_types = pg_enum_type_names(connection) # Compute max widths for name and sql_type so that the table lines up. name_width = columns.map(&:name).map(&:length).max type_width = columns.map(&:sql_type).map(&:length).max columns.flat_map do |col| name = col.name type = col.sql_type # Build the left-hand side and calculate indent. left = "# %-#{name_width}s :%-#{type_width}s" % [name, type] # " default(" is 9 chars; +2 gives the extra gap. indent_size = left.length + 1 indent_str = " " * indent_size closing_indent_str = " " * (indent_size - 2) # Gather all options, pulling out default_lines if multiline. opts = [] default_block = build_default_block(col.default) if default_block opts << "__MULTILINE__" # placeholder elsif !col.default.nil? opts << "default(#{col.default.inspect})" end opts << "not null" unless col.null opts << "primary key" if name == primary_key opts << "is an Array" if type.end_with?("[]") opts << "unique" if unique_indexes.any? { |idx| idx.columns == [name] } opts << "enum" if pg_enum_types.include?(type.delete_suffix("[]")) opts << "comment: #{col.comment.inspect}" if col.respond_to?(:comment) && col.comment && !col.comment.empty? # Emit either a multiline block or a single line. if default_block # 1) opening line lines = ["#{left} default(#{col.default[0]}"] # 2) each interior line, prefixed by "# " + indent_str lines += default_block.map { |l| "# #{indent_str}#{l}" } # 3) closing line with trailing options closing = "# #{closing_indent_str}#{col.default[-1]})" trailing = opts.reject { |o| o == "__MULTILINE__" } closing += ", #{trailing.join(', ')}" unless trailing.empty? lines << closing lines else # single-line comment line = left line += " #{opts.join(', ')}" unless opts.empty? [line.rstrip] end end end |