class
Detector::Ruby::Rails
- Detector::Ruby::Rails
- Detector
- Reference
- Object
Defined in:
detector/detectors/ruby/rails.crConstant Summary
-
RAILS_CODE_MARKERS =
[/(^|\W)[A-Za-z_:][\w:]*\.routes\.draw\b/, /(^|\W)Rails\.application\b/, /(^|\W)Rails::Application\b/, /(^|\s)require\s+["']rails\/all["']/] -
Rails APIs that cannot appear in a project that is not Rails, so a single
.rbor.rufile is enough to place the whole tree.The dependency declaration is the better marker when it is there, but it is only there when the scan reaches the manifest. Point noir at a Rails app's
config/directory, at an engine whose gemspec does not name the framework, or at a service inside a monorepo scanned app-by-app, and there is no Gemfile in the walk — the app detects as nothing, the Rails analyzer never runs, and every route the app declares is lost. That is the same gap the Django detector closes for DRF-only apps, and it is worth closing here because the file the analyzer actually reads,config/routes.rb, is itself proof:.routes.drawis the Rails routing DSL and belongs to no other framework. -
RAILS_GEMS =
["rails", "railties"] -
Modern Rails apps frequently skip the umbrella
railsdependency and pull the individual frameworks they actually use (railties + actionpack + activerecord + ...). Treatrailtiesas a unique marker — it has no standalone use outside Rails — so those apps are still detected. Multi-engine projects (Spree, Solidus) push their Gemfile togemspecand declare the dependency inside<gem>.gemspecinstead; the tolerant matchers accept thes.add_dependency('rails', ...)parenthesized call form those gemspecs commonly use.
Class Method Summary
-
.tech_name : String
The tech name without needing an instance, so the registry can be read off the classes themselves rather than from a parallel list.
Instance Method Summary
-
#applicable?(filename : String) : Bool
Cheap filename-only filter the detector pass uses to skip
#detecton files the detector cannot possibly match. - #detect(filename : String, file_contents : String) : Bool
- #set_name
Instance methods inherited from class Detector
applicable?(filename : String) : Bool
applicable?,
base_relative_path(filename : String) : String
base_relative_path,
content_matches?(file_contents : String, markers : Regex) : Bool
content_matches?,
detect(filename : String, file_contents : String) : Bool
detect,
gemfile_dependency?(file_contents : String, gem_name : String) : Bool
gemfile_dependency?,
gemspec_dependency?(file_contents : String, gem_name : String) : Bool
gemspec_dependency?,
idempotent? : Bool
idempotent?,
logger : NoirLogger
logger,
name : String
name,
path_sensitive? : Bool
path_sensitive?,
record_unparsable_document(filename : String, error : Exception) : Nil
record_unparsable_document
Constructor methods inherited from class Detector
new(options : Hash(String, YAML::Any))
new
Macros inherited from class Detector
detector_for(tech, extensions = nil, basenames = nil, path_segments = nil, idempotent = nil)
detector_for
Class Method Detail
The tech name without needing an instance, so the registry can be read off the classes themselves rather than from a parallel list.
Instance Method Detail
Cheap filename-only filter the detector pass uses to skip
#detect on files the detector cannot possibly match. The
default true preserves prior behavior (every detector runs on
every file). Override with the same predicate the body of
#detect starts with — e.g., filename.ends_with?(".py") for a
Python framework detector — so the detector loop avoids the
#detect dispatch on files outside the detector's language.
On large codebases (saleor's 4255 .py files) this lifts ~100
virtual #detect calls per file out of the hot loop because
most detectors' inner first-line is exactly this kind of cheap
filename check.