Class: RailsLens::Schema::Annotation

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_lens/schema/annotation.rb

Constant Summary collapse

MARKER_FORMAT =
'rails-lens:schema'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeAnnotation

Returns a new instance of Annotation.



10
11
12
# File 'lib/rails_lens/schema/annotation.rb', line 10

def initialize
  @content = []
end

Instance Attribute Details

#contentObject (readonly)

Returns the value of attribute content.



8
9
10
# File 'lib/rails_lens/schema/annotation.rb', line 8

def content
  @content
end

Class Method Details

.extract(file_content) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/rails_lens/schema/annotation.rb', line 44

def self.extract(file_content)
  start_marker = "# <#{MARKER_FORMAT}:begin>"
  end_marker = "# <#{MARKER_FORMAT}:end>"

  start_index = file_content.index(start_marker)
  return nil unless start_index

  end_index = file_content.index(end_marker, start_index)
  return nil unless end_index

  {
    start_index: start_index,
    end_index: end_index + end_marker.length,
    content: file_content[start_index..(end_index + end_marker.length - 1)]
  }
end

.insert_after_line(file_content, line_pattern, annotation_text) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/rails_lens/schema/annotation.rb', line 77

def self.insert_after_line(file_content, line_pattern, annotation_text)
  lines = file_content.split("\n")
  insert_index = nil

  lines.each_with_index do |line, index|
    if line.match?(line_pattern)
      insert_index = index + 1
      break
    end
  end

  return file_content unless insert_index

  # Insert the annotation
  lines.insert(insert_index, annotation_text)
  lines.join("\n")
end

.parse_content(annotation_block) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/rails_lens/schema/annotation.rb', line 113

def self.parse_content(annotation_block)
  return {} unless annotation_block

  lines = annotation_block.split("\n").map { |line| line.sub(/^#\s?/, '') }

  # Remove marker lines
  lines = lines[1..-2] if lines.first&.match?(/<.*:begin>/) && lines.last&.match?(/<.*:end>/)

  sections = {}
  current_section = nil
  current_content = []

  lines.each do |line|
    if line.match?(/^==\s+(.+)/)
      # Save previous section if any
      sections[current_section] = current_content.join("\n").strip if current_section

      current_section = line.strip
      current_content = []
    else
      current_content << line
    end
  end

  # Save last section
  sections[current_section] = current_content.join("\n").strip if current_section

  sections
end

.remove(file_content) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/rails_lens/schema/annotation.rb', line 61

def self.remove(file_content)
  # Remove all occurrences of the annotation blocks
  result = file_content.dup

  while (annotation = extract(result))
    # Preserve one newline if the annotation was followed by a newline
    replacement = ''
    replacement = "\n" if annotation[:end_index] < result.length && result[annotation[:end_index]] == "\n"

    result[annotation[:start_index]...annotation[:end_index]] = replacement
  end

  # Clean up multiple consecutive blank lines
  result.gsub(/\n\n\n+/, "\n\n")
end

.update_or_insert(file_content, annotation_text, line_pattern) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/rails_lens/schema/annotation.rb', line 95

def self.update_or_insert(file_content, annotation_text, line_pattern)
  # First, try to find and update existing annotation
  if (existing = extract(file_content))
    # Replace existing annotation
    before = file_content[0...existing[:start_index]]
    after = file_content[existing[:end_index]..]

    # Ensure proper spacing
    before = "#{before.rstrip}\n"
    after = "\n#{after.lstrip}" if after && !after.start_with?("\n")

    return before + annotation_text + after
  end

  # No existing annotation, insert new one
  insert_after_line(file_content, line_pattern, annotation_text)
end

Instance Method Details

#add_line(line) ⇒ Object



22
23
24
# File 'lib/rails_lens/schema/annotation.rb', line 22

def add_line(line)
  @content << line
end

#add_lines(lines) ⇒ Object



26
27
28
# File 'lib/rails_lens/schema/annotation.rb', line 26

def add_lines(lines)
  @content.concat(lines)
end

#end_markerObject



18
19
20
# File 'lib/rails_lens/schema/annotation.rb', line 18

def end_marker
  "# <#{MARKER_FORMAT}:end>"
end

#start_markerObject



14
15
16
# File 'lib/rails_lens/schema/annotation.rb', line 14

def start_marker
  "# <#{MARKER_FORMAT}:begin>"
end

#to_sObject



30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/rails_lens/schema/annotation.rb', line 30

def to_s
  return '' if @content.empty?

  lines = []
  lines << start_marker

  @content.each do |line|
    lines << (line.empty? ? '#' : "# #{line}")
  end

  lines << end_marker
  lines.join("\n")
end