# frozen_string_literal: true require "set" module LiteCable module Connection module Identification # :nodoc: module ClassMethods # :nodoc: # Mark a key as being a connection identifier index # that can then be used to find the specific connection again later. def identified_by(*identifiers) Array(identifiers).each do |identifier| attr_writer identifier define_method(identifier) do return instance_variable_get(:"@#{identifier}") if instance_variable_defined?(:"@#{identifier}") fetch_identifier(identifier.to_s) end end self.identifiers += identifiers end end def self.prepended(base) base.class_eval do class << self attr_writer :identifiers def identifiers @identifiers ||= Set.new end include ClassMethods end end end def initialize(socket, identifiers: nil, **hargs) @encoded_ids = identifiers ? JSON.parse(identifiers) : {} super socket, **hargs end def identifiers self.class.identifiers end # Return a single connection identifier # that combines the value of all the registered identifiers into a single id. # # You can specify a custom identifier_coder in config # to implement specific logic of encoding/decoding # custom classes to identifiers. # # By default uses Raw coder. def identifier unless defined? @identifier values = identifiers_hash.values.compact @identifier = values.empty? ? nil : values.map(&:to_s).sort.join(":") end @identifier end # Generate identifiers info as hash. def identifiers_hash identifiers.each_with_object({}) do |id, acc| obj = instance_variable_get("@#{id}") next unless obj acc[id.to_s] = LiteCable.config.identifier_coder.encode(obj) end end def identifiers_json identifiers_hash.to_json end # Fetch identifier and deserialize if neccessary def fetch_identifier(name) val = @encoded_ids[name] val = LiteCable.config.identifier_coder.decode(val) unless val.nil? instance_variable_set( :"@#{name}", val ) end end end end