Module: Familia::Features::Relationships::ClassMethods

Includes:
ScoreEncoding
Defined in:
lib/familia/features/relationships.rb

Constant Summary

Constants included from ScoreEncoding

ScoreEncoding::MAX_METADATA, ScoreEncoding::METADATA_PRECISION, ScoreEncoding::PERMISSION_CATEGORIES, ScoreEncoding::PERMISSION_FLAGS, ScoreEncoding::PERMISSION_ROLES

Instance Method Summary collapse

Methods included from ScoreEncoding

add_permissions, #add_permissions, categorize_scores, category?, category_score_range, current_score, #current_score, decode_permission_flags, decode_score, #decode_score, encode_score, #encode_score, filter_by_category, meets_category?, permission?, #permission?, permission_decode, #permission_decode, permission_encode, #permission_encode, permission_level_value, permission_range, #permission_range, permission_tier, remove_permissions, #remove_permissions, score_range, #score_range

Instance Method Details

#create_temp_key(base_name, ttl = 300) ⇒ Object

Class method wrapper for create_temp_key



219
220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/familia/features/relationships.rb', line 219

def create_temp_key(base_name, ttl = 300)
  timestamp = Time.now.to_i
  random_suffix = SecureRandom.hex(3)
  temp_key = "temp:#{base_name}:#{timestamp}:#{random_suffix}"

  # Set immediate expiry to ensure cleanup even if operation fails
  if respond_to?(:dbclient)
    dbclient.expire(temp_key, ttl)
  else
    Familia.dbclient.expire(temp_key, ttl)
  end

  temp_key
end

#create_with_relationships(attributes = {}) ⇒ Object

Create a new instance with relationships initialized



212
213
214
215
216
# File 'lib/familia/features/relationships.rb', line 212

def create_with_relationships(attributes = {})
  instance = new(attributes)
  instance.initialize_relationships
  instance
end

#generate_identifierObject

Generate a secure temporary identifier



152
153
154
# File 'lib/familia/features/relationships.rb', line 152

def generate_identifier
  SecureRandom.hex(8)
end

#identifier(field = nil) ⇒ Symbol

Define the identifier for this class (replaces identifier_field) This is a compatibility wrapper around the existing identifier_field method

Examples:

identifier :domain_id

Parameters:

  • field (Symbol) (defaults to: nil)

    The field to use as identifier

Returns:

  • (Symbol)

    The identifier field



145
146
147
148
149
# File 'lib/familia/features/relationships.rb', line 145

def identifier(field = nil)
  return identifier_field(field) if field

  identifier_field
end

#relationship_configsObject

Get all relationship configurations for this class



157
158
159
160
161
162
163
164
165
# File 'lib/familia/features/relationships.rb', line 157

def relationship_configs
  configs = {}

  configs[:tracking] = tracking_relationships if respond_to?(:tracking_relationships)
  configs[:indexing] = indexing_relationships if respond_to?(:indexing_relationships)
  configs[:membership] = membership_relationships if respond_to?(:membership_relationships)

  configs
end

#validate_relationships!Object

Validate relationship configurations

Raises:



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/familia/features/relationships.rb', line 168

def validate_relationships!
  errors = []

  # Check for method name collisions
  method_names = []

  if respond_to?(:tracking_relationships)
    tracking_relationships.each do |config|
      context_name = config[:context_class_name].downcase
      collection_name = config[:collection_name]

      method_names << "in_#{context_name}_#{collection_name}?"
      method_names << "add_to_#{context_name}_#{collection_name}"
      method_names << "remove_from_#{context_name}_#{collection_name}"
    end
  end

  if respond_to?(:membership_relationships)
    membership_relationships.each do |config|
      owner_name = config[:owner_class_name].downcase
      collection_name = config[:collection_name]

      method_names << "in_#{owner_name}_#{collection_name}?"
      method_names << "add_to_#{owner_name}_#{collection_name}"
      method_names << "remove_from_#{owner_name}_#{collection_name}"
    end
  end

  # Check for duplicates
  duplicates = method_names.group_by(&:itself).select { |_, v| v.size > 1 }.keys
  errors << "Method name collisions detected: #{duplicates.join(', ')}" if duplicates.any?

  # Validate identifier field exists
  id_field = identifier
  unless instance_methods.include?(id_field) || method_defined?(id_field)
    errors << "Identifier field '#{id_field}' is not defined"
  end

  raise RelationshipError, "Relationship validation failed: #{errors.join('; ')}" if errors.any?

  true
end