class SignedGlobalID

def ==(other)

def ==(other)
  super && @purpose == other.purpose
end

def encoded_expiration

def encoded_expiration
  expires_at.utc.iso8601(3) if expires_at
end

def initialize(gid, options = {})

def initialize(gid, options = {})
  super
  @verifier = self.class.pick_verifier(options)
  @purpose = self.class.pick_purpose(options)
  @expires_at = pick_expiration(options)
end

def parse(sgid, options = {})

def parse(sgid, options = {})
  if sgid.is_a? self
    sgid
  else
    super verify(sgid, options), options
  end
end

def pick_expiration(options)

def pick_expiration(options)
  return options[:expires_at] if options.key?(:expires_at)
  if expires_in = options.fetch(:expires_in) { self.class.expires_in }
    expires_in.from_now
  end
end

def pick_purpose(options)

def pick_purpose(options)
  options.fetch :for, DEFAULT_PURPOSE
end

def pick_verifier(options)

Raise ArgumentError if neither is available.
Grab the verifier from options and fall back to SignedGlobalID.verifier.
def pick_verifier(options)
  options.fetch :verifier do
    verifier || raise(ArgumentError, 'Pass a `verifier:` option with an `ActiveSupport::MessageVerifier` instance, or set a default SignedGlobalID.verifier.')
  end
end

def raise_if_expired(expires_at)

def raise_if_expired(expires_at)
  if expires_at && Time.now.utc > Time.iso8601(expires_at)
    raise ExpiredMessage, 'This signed global id has expired.'
  end
end

def to_h

def to_h
  # Some serializers decodes symbol keys to symbols, others to strings.
  # Using string keys remedies that.
  { 'gid' => @uri.to_s, 'purpose' => purpose, 'expires_at' => encoded_expiration }
end

def to_s

def to_s
  @sgid ||= @verifier.generate(to_h)
end

def verify(sgid, options)

def verify(sgid, options)
  metadata = pick_verifier(options).verify(sgid)
  raise_if_expired(metadata['expires_at'])
  metadata['gid'] if pick_purpose(options) == metadata['purpose']
rescue ActiveSupport::MessageVerifier::InvalidSignature, ExpiredMessage
  nil
end