Class: Karst::Spec::Catalog
- Inherits:
-
Object
- Object
- Karst::Spec::Catalog
- Defined in:
- lib/karst/spec/catalog.rb
Overview
Read-only index over the JSON artifact Karst::Spec::Observer writes, answering "what scenarios have been observed for this controller/action" without requiring RSpec, Rails, or the host application's database to be loaded. This is pure data ingestion: JSON primitives in, immutable Scenario objects out. It never deserializes arbitrary Ruby objects, never constantizes a principal type, and never queries anything.
A Catalog is always in exactly one of three states:
- :missing -- the artifact does not exist yet (the suite has never been run with the observer installed).
- :invalid -- the artifact exists but could not be read as the expected
JSON array (empty file, malformed JSON, or an incompatible top-level
shape).
errorholds a human-readable reason. - :ready -- the artifact was a valid JSON array.
scenariosmay still be empty (a suite that observed zero browser-facing requests), which is deliberately distinct from :missing: "no scenarios cover this route" is not the same claim as "the catalog was never generated."
Malformed individual entries inside an otherwise valid array (a request missing its controller, an example with no requests at all) are skipped individually rather than invalidating the whole artifact. rubocop:disable Metrics/ClassLength
Instance Attribute Summary collapse
-
#error ⇒ Object
readonly
Returns the value of attribute error.
-
#scenarios ⇒ Object
readonly
Returns the value of attribute scenarios.
-
#status ⇒ Object
readonly
Returns the value of attribute status.
Class Method Summary collapse
-
.default_path ⇒ Object
Rails' own tmp/ convention when available, otherwise a plain relative path so this stays usable from a bare Ruby process (tests, a future CLI) with no Rails loaded.
- .load(path: default_path) ⇒ Object
Instance Method Summary collapse
-
#initialize(status, scenarios, error) ⇒ Catalog
constructor
A new instance of Catalog.
- #ready? ⇒ Boolean
-
#scenarios_for(controller:, action:, http_method: nil) ⇒ Object
Indexed primarily by controller/action -- Rails' own stable routing identity -- so "/things/1" and "/things/2" report as the same capability instead of fragmenting by dynamic id.
Constructor Details
#initialize(status, scenarios, error) ⇒ Catalog
Returns a new instance of Catalog.
163 164 165 166 167 168 169 |
# File 'lib/karst/spec/catalog.rb', line 163 def initialize(status, scenarios, error) @status = status @scenarios = scenarios @error = error @index = build_index(scenarios) freeze end |
Instance Attribute Details
#error ⇒ Object (readonly)
Returns the value of attribute error.
161 162 163 |
# File 'lib/karst/spec/catalog.rb', line 161 def error @error end |
#scenarios ⇒ Object (readonly)
Returns the value of attribute scenarios.
161 162 163 |
# File 'lib/karst/spec/catalog.rb', line 161 def scenarios @scenarios end |
#status ⇒ Object (readonly)
Returns the value of attribute status.
161 162 163 |
# File 'lib/karst/spec/catalog.rb', line 161 def status @status end |
Class Method Details
.default_path ⇒ Object
Rails' own tmp/ convention when available, otherwise a plain relative path so this stays usable from a bare Ruby process (tests, a future CLI) with no Rails loaded.
46 47 48 49 50 |
# File 'lib/karst/spec/catalog.rb', line 46 def default_path return DEFAULT_RELATIVE_PATH unless defined?(Rails) && Rails.respond_to?(:root) && Rails.root File.join(Rails.root.to_s, DEFAULT_RELATIVE_PATH) end |
.load(path: default_path) ⇒ Object
52 53 54 |
# File 'lib/karst/spec/catalog.rb', line 52 def load(path: default_path) new(*read(path)) end |
Instance Method Details
#ready? ⇒ Boolean
171 172 173 |
# File 'lib/karst/spec/catalog.rb', line 171 def ready? status == :ready end |
#scenarios_for(controller:, action:, http_method: nil) ⇒ Object
Indexed primarily by controller/action -- Rails' own stable routing
identity -- so "/things/1" and "/things/2" report as the same
capability instead of fragmenting by dynamic id. http_method
narrows further for the (uncommon) case where one controller/action
legitimately answers more than one verb; omitted, every scenario for
that controller/action is returned regardless of method.
181 182 183 184 185 186 187 |
# File 'lib/karst/spec/catalog.rb', line 181 def scenarios_for(controller:, action:, http_method: nil) matches = @index.fetch([controller, action], EMPTY) return matches if http_method.nil? normalized = http_method.to_s.upcase matches.select { |scenario| scenario.http_method == normalized }.freeze end |