Module: Familia::Utils

Included in:
Familia
Defined in:
lib/familia/utils.rb

Instance Method Summary collapse

Instance Method Details

#debug?Boolean

Checks if debug mode is enabled

e.g. Familia.debug = true

Returns:

  • (Boolean)

    true if debug mode is on, false otherwise



15
16
17
# File 'lib/familia/utils.rb', line 15

def debug?
  @debug == true
end

#distinguisher(value_to_distinguish, strict_values = true) ⇒ Object

This method determines the appropriate value to return based on the class of the input argument. It uses a case statement to handle different classes:

  • For Symbol, String, Integer, and Float classes, it traces the operation and converts the value to a string.

  • For Familia::Horreum class, it traces the operation and returns the identifier of the value.

  • For TrueClass, FalseClass, and NilClass, it traces the operation and converts the value to a string (“true”, “false”, or “”).

  • For any other class, it traces the operation and returns nil.

Alternative names for ‘value_to_distinguish` could be `input_value`, `value`, or `object`.



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/familia/utils.rb', line 135

def distinguisher(value_to_distinguish, strict_values = true)
  case value_to_distinguish
  when ::Symbol, ::String, ::Integer, ::Float
    #Familia.trace :TOREDIS_DISTINGUISHER, redis, "string", caller(1..1) if Familia.debug?
    # Symbols and numerics are naturally serializable to strings
    # so it's a relatively low risk operation.
    value_to_distinguish.to_s

  when ::TrueClass, ::FalseClass, ::NilClass
    #Familia.trace :TOREDIS_DISTINGUISHER, redis, "true/false/nil", caller(1..1) if Familia.debug?
    # TrueClass, FalseClass, and NilClass are high risk because we can't
    # reliably determine the original type of the value from the serialized
    # string. This can lead to unexpected behavior when deserializing. For
    # example, if a TrueClass value is serialized as "true" and then later
    # deserialized as a String, it can cause errors in the application. Worse
    # still, if a NilClass value is serialized as an empty string we lose the
    # ability to distinguish between a nil value and an empty string when
    #
    raise Familia::HighRiskFactor, value_to_distinguish if strict_values
    value_to_distinguish.to_s #=> "true", "false", ""

  when Familia::Base, Class
    #Familia.trace :TOREDIS_DISTINGUISHER, redis, "base", caller(1..1) if Familia.debug?
    if value_to_distinguish.is_a?(Class)
      value_to_distinguish.name
    else
      value_to_distinguish.identifier
    end

  else
    #Familia.trace :TOREDIS_DISTINGUISHER, redis, "else1 #{strict_values}", caller(1..1) if Familia.debug?

    if value_to_distinguish.class.ancestors.member?(Familia::Base)
      #Familia.trace :TOREDIS_DISTINGUISHER, redis, "isabase", caller(1..1) if Familia.debug?
      value_to_distinguish.identifier

    else
      #Familia.trace :TOREDIS_DISTINGUISHER, redis, "else2 #{strict_values}", caller(1..1) if Familia.debug?
      raise Familia::HighRiskFactor, value_to_distinguish if strict_values
      nil
    end
  end
end

#generate_id(length: 32, encoding: 36) ⇒ String

Generates a unique ID using SHA256 and base-36 encoding

Examples:

Generate a default ID

Familia.generate_id
# => "kuk79w6uxg81tk0kn5hsl6pr7ic16e9p6evjifzozkda9el6z"

Generate a shorter ID with 16 bytes input

Familia.generate_id(length: 16)
# => "z6gqw1b7ftzpvapydkt0iah0h0bev5hkhrs4mkf1gq4nq5csa"

Generate an ID with hexadecimal encoding

Familia.generate_id(encoding: 16)
# => "d06a2a70cba543cd2bbd352c925bc30b0a9029ca79e72d6556f8d6d8603d5716"

Generate a shorter ID with custom encoding

Familia.generate_id(length: 8, encoding: 32)
# => "193tosc85k3u513do2mtmibchpd2ruh5l3nsp6dnl0ov1i91h7m7"

Parameters:

  • length (Integer) (defaults to: 32)

    length of the random input in bytes (default: 32)

  • encoding (Integer) (defaults to: 36)

    base encoding for the output (default: 36)

Returns:

  • (String)

    a unique identifier

Raises:

  • (ArgumentError)


40
41
42
43
44
45
# File 'lib/familia/utils.rb', line 40

def generate_id(length: 32, encoding: 36)
  raise ArgumentError, "Encoding must be between 2 and 32" unless (1..32).include?(encoding)

  input = SecureRandom.hex(length)
  Digest::SHA256.hexdigest(input).to_i(16).to_s(encoding)
end

#generate_sha_hash(*elements) ⇒ Object



122
123
124
125
# File 'lib/familia/utils.rb', line 122

def generate_sha_hash(*elements)
  concatenated_string = Familia.join(*elements)
  DIGEST_CLASS.hexdigest(concatenated_string)
end

#join(*val) ⇒ String

Joins array elements with Familia delimiter

Parameters:

  • val (Array)

    elements to join

Returns:



50
51
52
# File 'lib/familia/utils.rb', line 50

def join(*val)
  val.compact.join(Familia.delim)
end

#qstamp(quantum = 10.minutes, pattern: nil, time: nil) ⇒ Integer, String

A quantized timestamp

Examples:

Familia.qstamp  # Returns an integer timestamp rounded to the nearest 10 minutes
Familia.qstamp(1.hour)  # Uses 1 hour quantum
Familia.qstamp(10.minutes, pattern: '%H:%M')  # Returns a formatted string like "12:30"
Familia.qstamp(10.minutes, time: 1302468980)  # Quantizes the given Unix timestamp
Familia.qstamp(10.minutes, time: Time.now)  # Quantizes the given Time object
Familia.qstamp(10.minutes, pattern: '%H:%M', time: 1302468980)  # Formats a specific time

Parameters:

  • quantum (Integer) (defaults to: 10.minutes)

    The time quantum in seconds (default: 10 minutes).

  • pattern (String, nil) (defaults to: nil)

    The strftime pattern to format the timestamp.

  • time (Integer, Float, Time, nil) (defaults to: nil)

    A specific time to quantize (default: current time).

Returns:

  • (Integer, String)

    A unix timestamp or formatted timestamp string.



109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/familia/utils.rb', line 109

def qstamp(quantum = 10.minutes, pattern: nil, time: nil)
  time ||= Familia.now
  time = time.to_f if time.is_a?(Time)

  rounded = time - (time % quantum)

  if pattern
    Time.at(rounded).utc.strftime(pattern)
  else
    Time.at(rounded).utc.to_i
  end
end

#rediskey(*val) ⇒ String

Creates a Redis key from given values

Parameters:

  • val (Array)

    elements to join for the key

Returns:



64
65
66
# File 'lib/familia/utils.rb', line 64

def rediskey(*val)
  join(*val)
end

#redisuri(uri) ⇒ URI::Redis

Converts a generic URI to a Redis URI

Parameters:

  • uri (String, URI)

    URI to convert

Returns:

  • (URI::Redis)

    Redis URI object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/familia/utils.rb', line 71

def redisuri(uri)
  generic_uri = URI.parse(uri.to_s)

  # Create a new URI::Redis object
  URI::Redis.build(
    scheme: generic_uri.scheme,
    userinfo: generic_uri.userinfo,
    host: generic_uri.host,
    port: generic_uri.port,
    path: generic_uri.path,
    query: generic_uri.query,
    fragment: generic_uri.fragment
  )
end

#split(val) ⇒ Array

Splits a string using Familia delimiter

Parameters:

  • val (String)

    string to split

Returns:

  • (Array)

    split elements



57
58
59
# File 'lib/familia/utils.rb', line 57

def split(val)
  val.split(Familia.delim)
end