Class: TwirpGenerator

Inherits:
Rails::Generators::NamedBase
  • Object
show all
Defined in:
lib/twirp_rails/generators/twirp/twirp_generator.rb

Constant Summary collapse

PROTO_RPC_REGEXP =
/\brpc\s+(\S+)\s*\(\s*(\S+)\s*\)\s*returns\s*\(\s*(\S+)\s*\)/m.freeze

Instance Method Summary collapse

Instance Method Details

#check_requirementsObject



34
35
36
37
38
39
40
41
42
# File 'lib/twirp_rails/generators/twirp/twirp_generator.rb', line 34

def check_requirements
  in_root do
    abort "#{proto_file_name} not found" unless File.exist?(proto_file_name)
  end

  protoc.check_requirements(check_swagger: gen_swagger?) do |msg|
    abort msg
  end
end

#create_module_filesObject



87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/twirp_rails/generators/twirp/twirp_generator.rb', line 87

def create_module_files
  return if regular_class_path.empty?

  class_path.length.times do |i|
    current_path = class_path[0..i]

    create_file File.join('app/rpc', "#{current_path.join('/')}.rb"), <<~RUBY
      # :nocov:
      #{module_hier(current_path.map(&:camelize))}# :nocov:
    RUBY
  end
end

#generate_handlerObject



102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/twirp_rails/generators/twirp/twirp_generator.rb', line 102

def generate_handler
  methods = proto_content.scan(PROTO_RPC_REGEXP).map do |method, _arg_type, _result_type|
    optimize_indentation <<~RUBY, 2
      def #{method.underscore}(req, _env)
      end
    RUBY
  end.join("\n")

  # Let us assume that the service name is the same file name
  create_file "app/rpc/#{file_path}_handler.rb", <<~RUBY
    class #{class_name}Handler
    #{methods}end
  RUBY
end

#generate_routeObject



117
118
119
# File 'lib/twirp_rails/generators/twirp/twirp_generator.rb', line 117

def generate_route
  route "mount_twirp '#{file_path}'"
end

#generate_rspec_filesObject



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/twirp_rails/generators/twirp/twirp_generator.rb', line 121

def generate_rspec_files
  in_root do
    return unless File.exist?('spec')

    methods = proto_content.scan(PROTO_RPC_REGEXP).map do |method, _arg_type, result_type|
      result_type = proto_type_to_ruby(result_type)
      optimize_indentation <<~RUBY, 2
        context '##{method.underscore}' do
          rpc { [:#{method.underscore}, 'arg'] }

          it do
            expect { #{result_type}.new(subject) }.to_not raise_exception
            should match({})
          end
        end
      RUBY
    end.join("\n")

    create_file "spec/rpc/#{file_path}_handler_spec.rb", <<~RUBY
      require 'rails_helper'

      describe #{class_name}Handler do

      #{methods}end
    RUBY
  end
end

#generate_twirp_filesObject



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/twirp_rails/generators/twirp/twirp_generator.rb', line 57

def generate_twirp_files
  in_root do
    FileUtils.mkdir_p dst_path

    protos_mask = File.join src_path, '**/*.proto'
    proto_files = Dir.glob protos_mask

    protoc_files_count = 0
    swagger_files_count = 0

    proto_files.each do |file|
      gen_swagger = gen_swagger? && file =~ %r{/#{file_name}\.proto$}

      FileUtils.mkdir_p cfg.swagger_output_path if gen_swagger

      cmd = protoc.cmd(file, gen_swagger)

      protoc_files_count += 1
      swagger_files_count += gen_swagger ? 1 : 0

      `#{cmd}`

      abort "protoc failure: #{cmd}" unless $?.success?
    end

    msg = "#{protoc_files_count} proto files processed, #{swagger_files_count} with swagger"
    say_status :protoc, msg, :green
  end
end

#rm_old_twirp_filesObject



44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/twirp_rails/generators/twirp/twirp_generator.rb', line 44

def rm_old_twirp_files
  return unless cfg.purge_old_twirp_code

  in_root do
    removed_files = protoc.rm_old_twirp_files

    if removed_files
      msg = "#{removed_files.size} twirp and pb files purged from #{dst_path}"
      say_status :protoc, msg, :green
    end
  end
end

#smart_detect_proto_file_nameObject



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/twirp_rails/generators/twirp/twirp_generator.rb', line 9

def smart_detect_proto_file_name
  return if File.exist?(proto_file_name) # dont detect when file exists
  return if class_path.any? # dont detect when file with path

  in_root do
    [file_name, "#{file_name}_api"].each do |file|
      mask = File.join src_path, "**/#{file}.proto"
      matched_files = Dir.glob(mask)

      next if matched_files.empty?

      abort "many proto files matched the #{file_name}: #{matched_files.join(' ')}" if matched_files.size > 1

      matched_file = Pathname.new(matched_files.first).relative_path_from Pathname.new(src_path)
      matched_file = matched_file.to_s[0..-(matched_file.extname.length + 1)] # remove extension

      @file_path = nil # reset cache

      say_status :detect, "Smart detect #{file_name} as #{matched_file}", :yellow
      assign_names!(matched_file)
      break
    end
  end
end