Class: ZodRails::Generator

Inherits:
Object
  • Object
show all
Defined in:
lib/zod_rails/generator.rb,
sig/zod_rails.rbs

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(output_dir:) ⇒ Generator

Returns a new instance of Generator.

Parameters:

  • output_dir: (String)


7
8
9
10
11
# File 'lib/zod_rails/generator.rb', line 7

def initialize(output_dir:)
  @output_dir = output_dir
  @file_writer = Generation::FileWriter.new(output_dir: output_dir)
  @emitter = Generation::TypescriptEmitter.new
end

Instance Attribute Details

#emitterObject (readonly)

Returns the value of attribute emitter.



5
6
7
# File 'lib/zod_rails/generator.rb', line 5

def emitter
  @emitter
end

#file_writerObject (readonly)

Returns the value of attribute file_writer.



5
6
7
# File 'lib/zod_rails/generator.rb', line 5

def file_writer
  @file_writer
end

#output_dirString (readonly)

Returns the value of attribute output_dir.

Returns:

  • (String)


5
6
7
# File 'lib/zod_rails/generator.rb', line 5

def output_dir
  @output_dir
end

Instance Method Details

#check(model_classes) ⇒ Array[Hash[Symbol, String | Symbol]]

Parameters:

  • (Array[singleton(ActiveRecord::Base)])

Returns:

  • (Array[Hash[Symbol, String | Symbol]])


51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/zod_rails/generator.rb', line 51

def check(model_classes)
  model_classes.each_with_object([]) do |klass, drift|
    target = generate_content(klass)
    full_path = File.join(output_dir, target[:filename])
    expected = file_writer.preview(filename: target[:filename], content: target[:content])

    if !File.exist?(full_path)
      drift << { filename: target[:filename], status: :missing }
    elsif File.read(full_path) != expected
      drift << { filename: target[:filename], status: :drifted }
    end
  end
end

#generate(model_class) ⇒ String

Parameters:

  • (singleton(ActiveRecord::Base))

Returns:

  • (String)


13
14
15
16
17
# File 'lib/zod_rails/generator.rb', line 13

def generate(model_class)
  result = generate_content(model_class)
  file_writer.write(filename: result[:filename], content: result[:content])
  result[:filename]
end

#generate_all(model_classes) ⇒ Array[String]

Parameters:

  • (Array[singleton(ActiveRecord::Base)])

Returns:

  • (Array[String])

Raises:



38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/zod_rails/generator.rb', line 38

def generate_all(model_classes)
  targets = model_classes.map { |klass| generate_content(klass) }
  duplicate = targets.group_by { |target| target[:filename] }.find { |_filename, matches| matches.size > 1 }
  raise ZodRails::Error, "Output filename collision: #{duplicate.first}" if duplicate

  files = targets.map do |target|
    file_writer.write(filename: target[:filename], content: target[:content])
    target[:filename]
  end
  run_post_generate_command
  files
end

#generate_content(model_class) ⇒ Hash[Symbol, String]

Parameters:

  • (singleton(ActiveRecord::Base))

Returns:

  • (Hash[Symbol, String])


19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/zod_rails/generator.rb', line 19

def generate_content(model_class)
  inspector = Introspection::ModelInspector.new(model_class)
  config = ZodRails.configuration
  builder = Generation::SchemaBuilder.new(
    inspector,
    excluded_columns: config.excluded_columns,
    schema_suffix: config.schema_suffix,
    input_schema_suffix: config.input_schema_suffix
  )

  response_schema = {
    name: builder.schema_name,
    type_name: builder.type_name,
    body: builder.build
  }
  content = emit_content(builder, response_schema, generate_input: config.generate_input_schemas)
  { filename: file_writer.output_path_for(inspector.model_name), content: content }
end