Class: Karst::Access::PopulationDiscovery

Inherits:
Object
  • Object
show all
Defined in:
lib/karst/access/population_discovery.rb

Overview

Finds zero-argument Rails scope declarations by parsing model source. Ripper is part of Ruby's standard library (including Ruby 2.7), so this does not raise Karst's minimum Ruby version or add a parser dependency. Discovery never calls a scope or any other model method.

Constant Summary collapse

FRAMEWORK_NAMESPACES =
%w[ActiveRecord ActiveStorage ActionText ActionMailbox].freeze
Candidate =
Value.define(:model_name, :method_name, :principal_source)
ModelGroup =
Value.define(:model_name, :candidate_names, :principal_source) do
  def candidates
    candidate_names.map do |method_name|
      Candidate.new(model_name: model_name, method_name: method_name, principal_source: principal_source)
    end
  end
end
Result =
Value.define(:model_groups, :load_warning) do
  def candidates
    model_groups.flat_map(&:candidates)
  end
end

Instance Method Summary collapse

Instance Method Details

#callObject



31
32
33
# File 'lib/karst/access/population_discovery.rb', line 31

def call
  Result.new(model_groups: model_groups, load_warning: @load_warning)
end

#confirms?(klass:, method_name:) ⇒ Boolean

Confirms one exact model/scope pair against the model's current source, executing nothing. Deliberately takes the class the caller already holds (always an already-configured principal source's own model, see Karst::Access::ApprovedPopulations) rather than a name to look up: a stored approval can therefore never cause Karst to constantize, autoload, or reach a class the application had not already pointed it at, and this check stays a single file parse instead of a full application eager load.

Fails closed by construction: it answers "would discovery list this candidate right now," so a scope that was deleted, renamed, given parameters, or replaced by an ordinary class method stops being confirmed as soon as the source changes.

Returns:

  • (Boolean)


48
49
50
51
# File 'lib/karst/access/population_discovery.rb', line 48

def confirms?(klass:, method_name:)
  name = method_name.to_sym
  klass.respond_to?(name) && scope_names(klass).include?(name)
end