Module: ApiKeys::Models::Concerns::HasApiKeys::ClassMethods

Defined in:
lib/api_keys/models/concerns/has_api_keys.rb

Overview

Module containing class methods to be extended onto ActiveRecord::Base

Instance Method Summary collapse

Instance Method Details

#has_api_keys(**options, &block) ⇒ Object

Defines the association and allows configuration for the specific owner model.

Example:

class User < ApplicationRecord
  # Using keyword arguments:
  has_api_keys max_keys: 5, require_name: true

  # Or using a block:
  has_api_keys do
    max_keys 10
    require_name false
    default_scopes %w[read write]
  end
end


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/api_keys/models/concerns/has_api_keys.rb', line 29

def has_api_keys(**options, &block)
  # Include the concern's instance methods into the calling class (e.g., User)
  # Ensures any instance-level helpers in HasApiKeys are available on the owner.
  include ApiKeys::Models::Concerns::HasApiKeys unless included_modules.include?(ApiKeys::Models::Concerns::HasApiKeys)

  # Define the core association on the specific class calling this method
  has_many :api_keys,
           class_name: "ApiKeys::ApiKey",
           as: :owner,
           dependent: :destroy # Consider :nullify based on requirements

  # Define class_attribute for settings if not already defined.
  # This ensures inheritance works correctly (subclasses get their own copy).
  unless respond_to?(:api_keys_settings)
    class_attribute :api_keys_settings, instance_writer: false, default: {}
  end

  # Initialize settings for this specific class, merging defaults and options
  current_settings = {
    # Default to global config values first
    max_keys: ApiKeys.configuration&.default_max_keys_per_owner,
    require_name: ApiKeys.configuration&.require_key_name,
    default_scopes: ApiKeys.configuration&.default_scopes || []
  }.merge(options) # Merge keyword arguments first

  # Apply DSL block if provided, allowing overrides
  if block_given?
    dsl = DslProvider.new(current_settings)
    dsl.instance_eval(&block)
  end

  # Assign the final settings hash to the class attribute for this class
  self.api_keys_settings = current_settings

  # TODO: Add validation hook to check key limit on create?
  # validates_with ApiKeys::Validators::MaxKeysValidator, on: :create, if: -> { api_keys_settings[:max_keys].present? }
end