openapi-ruby 4.0.1 → 4.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d1104f4d110622c6c94bce175fbb538fa07a5621ecc1d45901eac1d4f5ad1907
4
- data.tar.gz: e62100c294bd83d9ddfb8f435bd92af9df3ddfce68fbb0d1e194badb5b799f5a
3
+ metadata.gz: f4bf806084ec440728b07b1cb5105c2e2f8529852b143a087bb919111afd6498
4
+ data.tar.gz: d73357f612fa69222d354a2f122a496c63bf8d8259ddb15bdfb38c898c7fb335
5
5
  SHA512:
6
- metadata.gz: e04da5e753006dc5342abadf092ac9067ba46b661098eafcf090f9e64a861b6d73a46001ca3b69a21052dd6953cba2beed9fb44238dc186c465ec7fc1ceb1715
7
- data.tar.gz: 63bc2eeff43bbd5efbb82c66eb00239797b7f413ada695cd1b1afe1753872d9237bf419a735fcf48cd785f2c2c58074da5a289ae8761c73df382b7d9a11871b6
6
+ metadata.gz: ea9f2ab82f0cdae01a6a578daa13f7274914a77b2476ba4ff7bbaf4cfd991ea685c608dcd71eac23bb2bc9ebf0ce35d0ac764b63a89bbb35add7e95c73a9d048
7
+ data.tar.gz: b940f94f696df915e90eccc593ae3901b1bc63229b4158391da62ffddb7fef1932a788358c1bffe771054f3e7d5f68faae36ff549ebb2c1166c078ed8ee58c66
data/README.md CHANGED
@@ -469,13 +469,49 @@ rake openapi_ruby:generate
469
469
 
470
470
  This loads spec/test files to collect API definitions and writes schemas without running any tests. It auto-detects the test framework, or you can set `FRAMEWORK=rspec`, `FRAMEWORK=minitest`, or `FRAMEWORK=hybrid`. Custom patterns: `PATTERN="packs/*/spec/**/*_spec.rb"`.
471
471
 
472
+ Loading a test file normally *is* enough to run it: `rails/test_help` requires `active_support/testing/autorun`, and `rspec/autorun` does the equivalent — both register an `at_exit` hook that runs the suite. The generated script therefore installs `OpenapiRuby::Generator::AutorunSuppressor` before requiring anything of yours, so the hook is never registered. Generation stays a load-only operation no matter how your helpers are wired.
473
+
472
474
  Schemas are **only** written by the rake task — running tests (`bundle exec rspec`, `rails test`) does not generate or overwrite schema files. This prevents partial schema overwrites when running a subset of specs.
473
475
 
476
+ ### No database required
477
+
478
+ The document is built from your declarations, never from the database — but `rails/test_help` verifies the test schema at require time (`maintain_test_schema!`), and many hand-written helpers add `ActiveRecord::Migration.check_all_pending!`. Both open a connection, which would make a database a hard requirement for generating a document that doesn't need one.
479
+
480
+ Generation stubs both out, so `rake openapi_ruby:generate` runs with no database available. Nothing else about your helper changes, and the stubs exist only inside the generation subprocess — normal test runs still verify the schema as usual.
481
+
482
+ Only the schema *check* is skipped. A connection is still available if your declarations genuinely need one (an enum built from a query at load time, say); such a suite needs a database either way.
483
+
484
+ ### Making generation cheaper (optional)
485
+
486
+ Generation only needs your `path` / `api_path` declarations to register. Booting the full test framework and loading fixtures is dead weight, and on a large suite it dominates the runtime.
487
+
488
+ Guard that setup with `OpenapiRuby.schema_generating?`, which returns `true` only in the rake task's subprocess (it sets `OPENAPI_RUBY_GENERATING=true`):
489
+
490
+ ```ruby
491
+ # test/test_helper.rb
492
+ require "minitest/rails" # keep the spec DSL if your api_path classes use describe/it/let
493
+
494
+ return if OpenapiRuby.schema_generating?
495
+
496
+ require "rails/test_help"
497
+ # ...other test-time setup...
498
+ ```
499
+
500
+ This is purely an optimization — generation is already correct and database-free without it.
501
+
502
+ One caveat if you do guard: skipping `rails/test_help` also means `fixtures` is undefined, so any test file calling `fixtures :all` in its class body fails to *load*. Point `PATTERN` at just the files carrying `api_path` declarations:
503
+
504
+ ```bash
505
+ PATTERN="test/integration/api/**/*_test.rb" rake openapi_ruby:generate
506
+ ```
507
+
508
+ Suites using FactoryBot rather than fixtures don't hit this.
509
+
474
510
  ### Migrating from RSpec to Minitest (or vice versa)
475
511
 
476
512
  When both `spec/spec_helper.rb` and `test/test_helper.rb` are present, the rake task auto-selects `FRAMEWORK=hybrid` — it requires both adapters and loads both glob patterns (`spec/**/*_spec.rb,test/**/*_test.rb`) into one process. Style 1 `path(...)` and Style 2 `api_path(...)` definitions register into the same `MetadataStore`, so a single schema file holds paths contributed by either DSL.
477
513
 
478
- Two things to set up on the consumer side so the two test frameworks don't both wire themselves into Rails' lazy-load hooks during schema generation:
514
+ Here the guards described above stop being optional: without them both test frameworks wire themselves into Rails' lazy-load hooks in the same process.
479
515
 
480
516
  ```ruby
481
517
  # test/test_helper.rb
@@ -495,7 +531,7 @@ end
495
531
 
496
532
  `OpenapiRuby.schema_generating?` returns `true` when the rake task launched the current process (it sets `OPENAPI_RUBY_GENERATING=true` in the subprocess). With the guards in place, neither test framework boots its full Rails integration during generation — only the DSL needs to be live for `api_path` / `path` to register.
497
533
 
498
- The guards are only needed while both frameworks are live. Once the migration completes and only one test framework remains, the rake task auto-detects that framework and the guard becomes dead code that can be removed.
534
+ Once the migration completes and only one test framework remains, the rake task auto-detects that framework. The guard is then no longer *required* but it's still worth keeping for the reasons in "Making generation cheaper" above.
499
535
 
500
536
  ## Runtime Middleware
501
537
 
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenapiRuby
4
+ module Generator
5
+ # Schema generation loads the consumer's spec/test files purely to collect
6
+ # their `path` / `api_path` declarations. Loading them must not also *run*
7
+ # them.
8
+ #
9
+ # Both frameworks install an `at_exit` hook that runs the suite as a side
10
+ # effect of being required, and a consumer's helper almost always pulls one
11
+ # in transitively — `rails/test_help` requires
12
+ # `active_support/testing/autorun`, which calls `Minitest.autorun`; RSpec
13
+ # does the same via `rspec/autorun`. Without this, `rake openapi_ruby:generate`
14
+ # runs the entire suite and fails whenever any unrelated test fails.
15
+ #
16
+ # Installed by the generated script *before* any consumer file is required,
17
+ # so the hook is never registered in the first place.
18
+ module AutorunSuppressor
19
+ module_function
20
+
21
+ def install!
22
+ suppress_minitest!
23
+ suppress_rspec!
24
+ end
25
+
26
+ def suppress_minitest!
27
+ require "minitest"
28
+
29
+ ::Minitest.singleton_class.prepend(MinitestSilencer)
30
+ rescue LoadError
31
+ # Minitest isn't in the bundle — nothing to suppress.
32
+ end
33
+
34
+ def suppress_rspec!
35
+ return unless defined?(::RSpec::Core::Runner)
36
+
37
+ ::RSpec::Core::Runner.disable_autorun!
38
+ end
39
+
40
+ module MinitestSilencer
41
+ # Swallow the `at_exit` registration. Defined as a no-op rather than
42
+ # setting `@@installed_at_exit` so this doesn't depend on Minitest's
43
+ # internals.
44
+ def autorun
45
+ nil
46
+ end
47
+
48
+ # Belt and braces: if something registered the hook before this module
49
+ # was installed, the hook still fires but finds nothing to do.
50
+ def run(*)
51
+ true
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -42,9 +42,22 @@ module OpenapiRuby
42
42
  end
43
43
  end
44
44
 
45
+ # Prepended to every generated script, before any consumer file is
46
+ # required. Loading the consumer's test files must neither run them
47
+ # (AutorunSuppressor) nor drag in a database (TestSchemaSuppressor).
48
+ def suppress_autorun
49
+ <<~RUBY.chomp
50
+ require "openapi_ruby/generator/autorun_suppressor"
51
+ require "openapi_ruby/generator/test_schema_suppressor"
52
+ OpenapiRuby::Generator::AutorunSuppressor.install!
53
+ OpenapiRuby::Generator::TestSchemaSuppressor.install!
54
+ RUBY
55
+ end
56
+
45
57
  def rspec_script(pattern)
46
58
  <<~RUBY
47
59
  require "rspec/core"
60
+ #{suppress_autorun}
48
61
  $LOAD_PATH.unshift(File.expand_path("spec")) unless $LOAD_PATH.include?(File.expand_path("spec"))
49
62
  #{glob_loads(pattern)}
50
63
  OpenapiRuby::Generator::SchemaWriter.generate_all!
@@ -54,6 +67,7 @@ module OpenapiRuby
54
67
  def minitest_script(pattern)
55
68
  <<~RUBY
56
69
  require "openapi_ruby/minitest"
70
+ #{suppress_autorun}
57
71
  $LOAD_PATH.unshift(File.expand_path("test")) unless $LOAD_PATH.include?(File.expand_path("test"))
58
72
  #{glob_loads(pattern)}
59
73
  OpenapiRuby::Generator::SchemaWriter.generate_all!
@@ -86,6 +100,7 @@ module OpenapiRuby
86
100
  require "rspec/core"
87
101
  require "openapi_ruby/rspec"
88
102
  require "openapi_ruby/minitest"
103
+ #{suppress_autorun}
89
104
 
90
105
  load_with_path = lambda do |dir, glob|
91
106
  path = File.expand_path(dir)
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenapiRuby
4
+ module Generator
5
+ # Schema generation never runs tests, so keeping the test database's schema
6
+ # current is wasted work — but `rails/test_help` does it unconditionally at
7
+ # require time (`rails/testing/maintain_test_schema` → `maintain_test_schema!`),
8
+ # which opens a database connection. That makes a database a hard
9
+ # requirement for generating a document that doesn't depend on one.
10
+ #
11
+ # `maintain_test_schema!` is a no-op when the setting is off, so turning it
12
+ # off for the generation subprocess drops the requirement.
13
+ #
14
+ # This only skips the schema *check*. A connection is still available if the
15
+ # consumer's declarations genuinely need one (say, an enum built from a
16
+ # query at load time) — such a suite needs a database either way.
17
+ module TestSchemaSuppressor
18
+ module_function
19
+
20
+ def install!
21
+ return unless defined?(::ActiveSupport) && ::ActiveSupport.respond_to?(:on_load)
22
+
23
+ # Registered as a load hook so it applies whenever the consumer's helper
24
+ # boots Rails, rather than depending on require order.
25
+ ::ActiveSupport.on_load(:active_record) do
26
+ OpenapiRuby::Generator::TestSchemaSuppressor.disable!
27
+ end
28
+ end
29
+
30
+ # Neutralises the methods rather than clearing
31
+ # `ActiveRecord.maintain_test_schema`. The flag is reapplied from app
32
+ # config by the `active_record.set_configs` initializer, which runs after
33
+ # any load hook we can register from here — so setting it is silently
34
+ # undone before `rails/test_help` reads it.
35
+ def disable!
36
+ ::ActiveRecord::Migration.singleton_class.prepend(MigrationSilencer)
37
+ end
38
+
39
+ module MigrationSilencer
40
+ # Called by rails/test_help at require time.
41
+ def maintain_test_schema!
42
+ nil
43
+ end
44
+
45
+ # Not called by Rails during boot, but a common addition to a
46
+ # hand-written test_helper. Same intent as the above: assert the test
47
+ # database matches the migrations. Nothing is loaded from the database
48
+ # to build the document, so there is nothing to verify.
49
+ def check_all_pending!
50
+ nil
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OpenapiRuby
4
- VERSION = "4.0.1"
4
+ VERSION = "4.0.3"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openapi-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.1
4
+ version: 4.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Morten Hartvig
@@ -105,8 +105,10 @@ files:
105
105
  - lib/openapi_ruby/dsl/response_context.rb
106
106
  - lib/openapi_ruby/engine.rb
107
107
  - lib/openapi_ruby/errors.rb
108
+ - lib/openapi_ruby/generator/autorun_suppressor.rb
108
109
  - lib/openapi_ruby/generator/rake_task_support.rb
109
110
  - lib/openapi_ruby/generator/schema_writer.rb
111
+ - lib/openapi_ruby/generator/test_schema_suppressor.rb
110
112
  - lib/openapi_ruby/middleware/coercion.rb
111
113
  - lib/openapi_ruby/middleware/error_handler.rb
112
114
  - lib/openapi_ruby/middleware/path_matcher.rb