Class: TopSecret::Category

Inherits:
Object
  • Object
show all
Defined in:
lib/top_secret/category.rb

Overview

Represents a category of sensitive information (e.g., email, person, credit_card).

Each category derives a set of method names from its type and can resolve those methods against a mapping to return filtered results.

Examples:

category = TopSecret::Category.new(:email)
category.plural          # => :emails
category.predicate       # => :emails?
category.mapping_method  # => :email_mapping

Constant Summary collapse

MAPPING_SUFFIX =
"_mapping"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type) ⇒ Category

Returns a new instance of Category.

Parameters:

  • type (String, Symbol)

    the category type



44
45
46
# File 'lib/top_secret/category.rb', line 44

def initialize(type)
  @type = type.to_s
end

Instance Attribute Details

#typeString (readonly)

Returns the category type (e.g., “email”, “credit_card”).

Returns:

  • (String)

    the category type (e.g., “email”, “credit_card”)



20
21
22
# File 'lib/top_secret/category.rb', line 20

def type
  @type
end

Class Method Details

.from(mapping:, filters:) ⇒ Array<Category>

Builds categories from a mapping’s keys and a list of filters.

Parameters:

Returns:

  • (Array<Category>)

    unique categories derived from the mapping and filters



27
28
29
30
31
32
33
# File 'lib/top_secret/category.rb', line 27

def self.from(mapping:, filters:)
  types_from_mapping = mapping.keys.map { |key| type_from_key(key).downcase }

  types_from_filters = filters.map { |filter| filter.label.downcase }

  (types_from_mapping + types_from_filters).uniq.map { |type| new(type) }
end

.type_from_key(key) ⇒ String

Extracts the label type from a key symbol.

Parameters:

  • key (Symbol)

    a label key (e.g., :EMAIL_1, :CREDIT_CARD_2)

Returns:

  • (String)

    the label type (e.g., “EMAIL”, “CREDIT_CARD”)



39
40
41
# File 'lib/top_secret/category.rb', line 39

def self.type_from_key(key)
  key.to_s.rpartition(TopSecret::LABEL_DELIMITER).first
end

Instance Method Details

#mapping_methodSymbol

Returns the mapping method name (e.g., :email_mapping).

Returns:

  • (Symbol)

    the mapping method name (e.g., :email_mapping)



67
68
69
70
71
72
73
# File 'lib/top_secret/category.rb', line 67

def mapping_method
  if @type.end_with?(MAPPING_SUFFIX)
    :"#{@type.pluralize}#{MAPPING_SUFFIX}"
  else
    :"#{@type}#{MAPPING_SUFFIX}"
  end
end

#mapping_predicateSymbol

Returns the mapping predicate method name (e.g., :email_mapping?).

Returns:

  • (Symbol)

    the mapping predicate method name (e.g., :email_mapping?)



76
77
78
# File 'lib/top_secret/category.rb', line 76

def mapping_predicate
  :"#{mapping_method}?"
end

#matches?(mapping) ⇒ Boolean

Whether the mapping contains any keys belonging to this category.

Parameters:

  • mapping (Hash)

    the label-to-value mapping

Returns:

  • (Boolean)


84
85
86
# File 'lib/top_secret/category.rb', line 84

def matches?(mapping)
  mapping.any? { |key, _| key.to_s.match?(key_pattern) }
end

#pluralSymbol

Returns the pluralized type (e.g., :emails).

Returns:

  • (Symbol)

    the pluralized type (e.g., :emails)



57
58
59
# File 'lib/top_secret/category.rb', line 57

def plural
  @type.pluralize.to_sym
end

#predicateSymbol

Returns the predicate method name (e.g., :emails?).

Returns:

  • (Symbol)

    the predicate method name (e.g., :emails?)



62
63
64
# File 'lib/top_secret/category.rb', line 62

def predicate
  :"#{plural}?"
end

#resolve(method_name, mapping) ⇒ Hash, ...

Resolves a method name against the mapping, returning the appropriate result.

Parameters:

Returns:

  • (Hash, Array, Boolean)

    filtered mapping, values, or boolean depending on the method

Raises:

  • (ArgumentError)

    if the method name is not recognized



94
95
96
97
98
99
100
101
102
103
104
# File 'lib/top_secret/category.rb', line 94

def resolve(method_name, mapping)
  filtered = filter_mapping(mapping)

  case method_name
  when mapping_method then filtered
  when plural then filtered.values
  when predicate, mapping_predicate then filtered.any?
  else
    raise ArgumentError, "#{method_name} is not a recognized method for category '#{@type}'"
  end
end

#respond_to_method?(method_name) ⇒ Boolean

Whether this category recognizes the given method name.

Parameters:

  • method_name (Symbol)

    the method name to check

Returns:

  • (Boolean)


52
53
54
# File 'lib/top_secret/category.rb', line 52

def respond_to_method?(method_name)
  method_names.include?(method_name)
end