Class: UsageCredits::Operation

Inherits:
Object
  • Object
show all
Defined in:
lib/usage_credits/models/operation.rb

Overview

A DSL to define an operation that consumes credits when performed.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, &block) ⇒ Operation

Returns a new instance of Operation.



12
13
14
15
16
17
18
# File 'lib/usage_credits/models/operation.rb', line 12

def initialize(name, &block)
  @name = name
  @cost_calculator = Cost::Fixed.new(0)  # Default to free
  @validation_rules = []
  @metadata = {}
  instance_eval(&block) if block_given?
end

Instance Attribute Details

#cost_calculatorObject (readonly)

Operation identifier (e.g., :process_video)



7
8
9
# File 'lib/usage_credits/models/operation.rb', line 7

def cost_calculator
  @cost_calculator
end

#metadataObject (readonly)

Operation identifier (e.g., :process_video)



7
8
9
# File 'lib/usage_credits/models/operation.rb', line 7

def 
  @metadata
end

#nameObject (readonly)

Operation identifier (e.g., :process_video)



7
8
9
# File 'lib/usage_credits/models/operation.rb', line 7

def name
  @name
end

#validation_rulesObject (readonly)

Operation identifier (e.g., :process_video)



7
8
9
# File 'lib/usage_credits/models/operation.rb', line 7

def validation_rules
  @validation_rules
end

Instance Method Details

#calculate_cost(params = {}) ⇒ Integer

Calculate how many credits this operation will cost

Parameters:

  • params (Hash) (defaults to: {})

    Operation parameters (e.g., file size)

Returns:

  • (Integer)

    Number of credits



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/usage_credits/models/operation.rb', line 60

def calculate_cost(params = {})
  normalized_params = normalize_params(params)
  validate!(normalized_params)  # Ensure params are valid before calculating

  # Calculate raw cost
  total = case cost_calculator
          when Proc
            result = cost_calculator.call(normalized_params)
            raise ArgumentError, "Credit amount must be a whole number (got: #{result})" unless result == result.to_i
            raise ArgumentError, "Credit amount cannot be negative (got: #{result})" if result.negative?
            result
          else
            cost_calculator.calculate(normalized_params)
          end

  # Apply configured rounding strategy
  CreditCalculator.apply_rounding(total)
end

#costs(amount_or_calculator) ⇒ Object Also known as: cost

Set how many credits this operation costs

Parameters:

  • amount_or_calculator (Integer, Lambda)

    Fixed amount or dynamic calculator costs 10 # Fixed cost costs ->(params) { params } # Dynamic cost



29
30
31
32
33
34
35
36
# File 'lib/usage_credits/models/operation.rb', line 29

def costs(amount_or_calculator)
  @cost_calculator = case amount_or_calculator
  when Cost::Base
    amount_or_calculator
  else
    Cost::Fixed.new(amount_or_calculator)
  end
end

#meta(hash) ⇒ Object

Add custom metadata



49
50
51
# File 'lib/usage_credits/models/operation.rb', line 49

def meta(hash)
  @metadata = @metadata.merge(hash.transform_keys(&:to_s))
end

#to_audit_hash(params = {}) ⇒ Object

Create an audit record of this operation



106
107
108
109
110
111
112
113
114
115
# File 'lib/usage_credits/models/operation.rb', line 106

def to_audit_hash(params = {})
  {
    operation: name,
    cost: calculate_cost(params),
    params: params,
    metadata: ,
    executed_at: Time.current,
    gem_version: UsageCredits::VERSION
  }
end

#validate(condition, message = nil) ⇒ Object

Add a validation rule for this operation Example: can’t process images bigger than 100MB

Parameters:

  • condition (Lambda)

    Returns true if valid

  • message (String) (defaults to: nil)

    Error message if invalid



44
45
46
# File 'lib/usage_credits/models/operation.rb', line 44

def validate(condition, message = nil)
  @validation_rules << [condition, message || "Operation validation failed"]
end

#validate!(params = {}) ⇒ Object

Check if the operation can be performed

Parameters:

  • params (Hash) (defaults to: {})

    Operation parameters to validate

Raises:



86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/usage_credits/models/operation.rb', line 86

def validate!(params = {})
  normalized = normalize_params(params)

  validation_rules.each do |condition, message|
    next unless condition.is_a?(Proc)

    begin
      result = condition.call(normalized)
      raise InvalidOperation, message unless result
    rescue StandardError => e
      raise InvalidOperation, "Validation error: #{e.message}"
    end
  end
end