Module: OpenapiRuby::Generator::RakeTaskSupport
- Defined in:
- lib/openapi_ruby/generator/rake_task_support.rb
Overview
Helpers backing the openapi_ruby:generate rake task. Extracted
so the framework detection / script generation logic is testable
without booting Rake.
Constant Summary collapse
- HOST_ENV_VARS =
Environment variables the host reads to decide it is running under test. Sinatra takes APP_ENV first and falls back to RACK_ENV; other Rack apps read one or the other, so a Rack host gets both.
{ "rails" => ["RAILS_ENV"], "hanami" => ["HANAMI_ENV"], "rack" => ["APP_ENV", "RACK_ENV"] }.freeze
Class Method Summary collapse
- .default_pattern_for(framework) ⇒ Object
-
.detect_host ⇒ Object
Which framework hosts the app being generated for.
- .detect_test_framework ⇒ Object
- .generate_script(framework, pattern) ⇒ Object
- .glob_loads(pattern) ⇒ Object
-
.hybrid_script(pattern) ⇒ Object
Loads both adapters and both file globs in one process.
- .minitest_script(pattern) ⇒ Object
- .rspec_script(pattern) ⇒ Object
-
.subprocess_env(host = detect_host) ⇒ Object
Env for the generation subprocess: the host's own environment variables plus the flag that tells the gem it is generating rather than serving.
-
.suppress_autorun ⇒ Object
Prepended to every generated script, before any consumer file is required.
Class Method Details
.default_pattern_for(framework) ⇒ Object
62 63 64 65 66 67 68 |
# File 'lib/openapi_ruby/generator/rake_task_support.rb', line 62 def default_pattern_for(framework) case framework when "rspec" then "spec/**/*_spec.rb" when "minitest" then "test/**/*_test.rb" when "hybrid" then "spec/**/*_spec.rb,test/**/*_test.rb" end end |
.detect_host ⇒ Object
Which framework hosts the app being generated for. Detected from the filesystem as well as loaded constants: the rake process has not booted the app yet. Hanami keeps its app class in config/app.rb where Rails uses config/application.rb; a config.ru with neither is a Rack app (Sinatra, Roda, bare Rack).
32 33 34 35 36 37 38 39 40 41 |
# File 'lib/openapi_ruby/generator/rake_task_support.rb', line 32 def detect_host # Files describe the app being generated for; loaded constants only say # what the Rakefile happened to require, which in a mixed bundle can be # either framework. return "rails" if File.exist?("config/application.rb") return "hanami" if File.exist?("config/app.rb") return "rack" if File.exist?("config.ru") OpenapiRuby.host.to_s end |
.detect_test_framework ⇒ Object
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/openapi_ruby/generator/rake_task_support.rb', line 11 def detect_test_framework rspec = File.exist?("spec/spec_helper.rb") || File.exist?("spec/rails_helper.rb") minitest = File.exist?("test/test_helper.rb") if rspec && minitest "hybrid" elsif rspec "rspec" elsif minitest "minitest" else raise ArgumentError, "Could not detect test framework. Set FRAMEWORK=rspec, FRAMEWORK=minitest, or FRAMEWORK=hybrid." end end |
.generate_script(framework, pattern) ⇒ Object
70 71 72 73 74 75 76 77 78 |
# File 'lib/openapi_ruby/generator/rake_task_support.rb', line 70 def generate_script(framework, pattern) case framework when "rspec" then rspec_script(pattern) when "minitest" then minitest_script(pattern) when "hybrid" then hybrid_script(pattern) else raise ArgumentError, "Unknown test framework '#{framework}'." end end |
.glob_loads(pattern) ⇒ Object
166 167 168 169 170 |
# File 'lib/openapi_ruby/generator/rake_task_support.rb', line 166 def glob_loads(pattern) pattern.split(",").map do |p| %[Dir.glob(#{p.strip.inspect}).sort.each { |f| require File.expand_path(f) }] end.join("\n") end |
.hybrid_script(pattern) ⇒ Object
Loads both adapters and both file globs in one process. Useful
during a phased RSpec → Minitest migration where the suite
holds both DSL styles. Consumers can guard
require "rails/test_help" and require "rspec/rails" in
their test helpers with unless OpenapiRuby.schema_generating?
so the two test frameworks don't both register Rails lazy
hooks in the same process — only the DSL needs to be live for
schema generation.
Guarding is per-helper and optional: a suite that references
what the guarded require defines at load time (shared
examples, fixtures :all, include Devise::Test::... in a
class body) fails to load those files at all, which is worse
than the hook conflict. Such a helper stays unguarded and the
pattern narrows instead.
Each glob runs with its own framework's directory at the head
of $LOAD_PATH so the typical require "openapi_helper" /
require "rails_helper" / require "test_helper" resolves
to the right file. Without this, both spec/ and test/ getting
unshifted in one block leads to whichever was unshifted last
winning every lookup — and the wrong helper getting loaded
for the other side's files.
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/openapi_ruby/generator/rake_task_support.rb', line 135 def hybrid_script(pattern) globs = pattern.split(",").map(&:strip) spec_globs = globs.grep(%r{\bspec/}) test_globs = globs.grep(%r{\btest/}) other_globs = globs - spec_globs - test_globs <<~RUBY require "rspec/core" require "openapi_ruby/rspec" require "openapi_ruby/minitest" #{suppress_autorun} load_with_path = lambda do |dir, glob| path = File.expand_path(dir) added = !$LOAD_PATH.include?(path) $LOAD_PATH.unshift(path) if added begin Dir.glob(glob).sort.each { |f| require File.expand_path(f) } ensure $LOAD_PATH.delete(path) if added end end #{spec_globs.map { |g| "load_with_path.call(\"spec\", #{g.inspect})" }.join("\n ")} #{test_globs.map { |g| "load_with_path.call(\"test\", #{g.inspect})" }.join("\n ")} #{other_globs.map { |g| %[Dir.glob(#{g.inspect}).sort.each { |f| require File.expand_path(f) }] }.join("\n ")} OpenapiRuby::Generator::SchemaWriter.generate_all! RUBY end |
.minitest_script(pattern) ⇒ Object
102 103 104 105 106 107 108 109 110 |
# File 'lib/openapi_ruby/generator/rake_task_support.rb', line 102 def minitest_script(pattern) <<~RUBY require "openapi_ruby/minitest" #{suppress_autorun} $LOAD_PATH.unshift(File.expand_path("test")) unless $LOAD_PATH.include?(File.expand_path("test")) #{glob_loads(pattern)} OpenapiRuby::Generator::SchemaWriter.generate_all! RUBY end |
.rspec_script(pattern) ⇒ Object
92 93 94 95 96 97 98 99 100 |
# File 'lib/openapi_ruby/generator/rake_task_support.rb', line 92 def rspec_script(pattern) <<~RUBY require "rspec/core" #{suppress_autorun} $LOAD_PATH.unshift(File.expand_path("spec")) unless $LOAD_PATH.include?(File.expand_path("spec")) #{glob_loads(pattern)} OpenapiRuby::Generator::SchemaWriter.generate_all! RUBY end |
.subprocess_env(host = detect_host) ⇒ Object
Env for the generation subprocess: the host's own environment variables plus the flag that tells the gem it is generating rather than serving.
54 55 56 57 58 59 60 |
# File 'lib/openapi_ruby/generator/rake_task_support.rb', line 54 def subprocess_env(host = detect_host) env = HOST_ENV_VARS.fetch(host, HOST_ENV_VARS["rails"]).to_h do |var| [var, ENV.fetch(var, "test")] end env.merge("OPENAPI_RUBY_GENERATING" => "true") end |
.suppress_autorun ⇒ Object
Prepended to every generated script, before any consumer file is required. Loading the consumer's test files must neither run them (AutorunSuppressor) nor drag in a database (TestSchemaSuppressor).
83 84 85 86 87 88 89 90 |
# File 'lib/openapi_ruby/generator/rake_task_support.rb', line 83 def suppress_autorun <<~RUBY.chomp require "openapi_ruby/generator/autorun_suppressor" require "openapi_ruby/generator/test_schema_suppressor" OpenapiRuby::Generator::AutorunSuppressor.install! OpenapiRuby::Generator::TestSchemaSuppressor.install! RUBY end |