Module: Familia::Features::Relationships::Indexing::ModelInstanceMethods

Defined in:
lib/familia/features/relationships/indexing.rb

Overview

Instance methods for indexed objects

Instance Method Summary collapse

Instance Method Details

#current_indexingsArray<Hash>

Get all indexes this object appears in Note: For instance-scoped indexes, this only shows class-level indexes since instance-scoped indexes require a specific scope instance

Returns:

  • (Array<Hash>)

    Array of index information



210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
# File 'lib/familia/features/relationships/indexing.rb', line 210

def current_indexings
  return [] unless self.class.respond_to?(:indexing_relationships)

  memberships = []

  self.class.indexing_relationships.each do |config|
    field = config.field
    index_name = config.index_name
    cardinality = config.cardinality
    field_value = send(field)

    next unless field_value

    # Class-level indexes have within: nil (unique_index) or within: :class (multi_index)
    # Instance-scoped indexes have within: SomeClass (a specific class)
    if config.within.nil? || config.within == :class
      if cardinality == :unique
        # Class-level unique index - check hash key using DataType
        index_hash = self.class.send(index_name)
        next unless index_hash.key?(field_value.to_s)

        memberships << {
          scope_class: 'class',
          index_name: index_name,
          field: field,
          field_value: field_value,
          index_key: index_hash.dbkey,
          cardinality: cardinality,
          type: 'unique_index',
        }
      else
        # Class-level multi index - check set membership using factory method
        index_set = self.class.send("#{index_name}_for", field_value)
        next unless index_set.member?(identifier)

        memberships << {
          scope_class: 'class',
          index_name: index_name,
          field: field,
          field_value: field_value,
          index_key: index_set.dbkey,
          cardinality: cardinality,
          type: 'multi_index',
        }
      end
    else
      # Instance-scoped index (unique_index or multi_index with within:) - cannot check without scope instance
      # This would require scanning all possible scope instances
      memberships << {
        scope_class: config.scope_class_config_name,
        index_name: index_name,
        field: field,
        field_value: field_value,
        index_key: 'scope_dependent',
        cardinality: cardinality,
        type: cardinality == :unique ? 'unique_index' : 'multi_index',
        note: 'Requires scope instance for verification',
      }
    end
  end

  memberships
end

#indexed_in?(index_name) ⇒ Boolean

Check if this object is indexed in a specific scope For class-level indexes, checks the hash key (unique) or set membership (multi) For instance-scoped indexes, returns false (requires scope instance)

Returns:

  • (Boolean)


277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/familia/features/relationships/indexing.rb', line 277

def indexed_in?(index_name)
  return false unless self.class.respond_to?(:indexing_relationships)

  config = self.class.indexing_relationships.find { |rel| rel.index_name == index_name }
  return false unless config

  field = config.field
  field_value = send(field)
  return false unless field_value

  # Class-level indexes have within: nil (unique_index) or within: :class (multi_index)
  # Instance-scoped indexes have within: SomeClass (a specific class)
  if config.within.nil? || config.within == :class
    if config.cardinality == :unique
      # Class-level unique index - check hash key using DataType
      index_hash = self.class.send(index_name)
      index_hash.key?(field_value.to_s)
    else
      # Class-level multi index - check set membership using factory method
      index_set = self.class.send("#{index_name}_for", field_value)
      index_set.member?(identifier)
    end
  else
    # Instance-scoped index (with within:) - cannot verify without scope instance
    false
  end
end

#remove_from_all_indexes(scope_context = nil) ⇒ Object

Remove from all indexes for a given scope context For class-level indexes (unique_index without within:), scope_context should be nil For instance-scoped indexes (with within:), scope_context should be the scope instance



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/familia/features/relationships/indexing.rb', line 182

def remove_from_all_indexes(scope_context = nil)
  return unless self.class.respond_to?(:indexing_relationships)

  self.class.indexing_relationships.each do |config|
    index_name = config.index_name

    # Determine which remove method to call based on scope type
    # Class-level: within is nil (unique_index default) or :class (multi_index default)
    # Instance-scoped: within is a specific class
    if config.within.nil? || config.within == :class
      # Class-level index (auto-indexed on save)
      send("remove_from_class_#{index_name}")
    else
      # Instance-scoped index - requires explicit scope context
      next unless scope_context

      # Use config_name for method naming
      scope_class_config = Familia.resolve_class(config.scope_class).config_name
      send("remove_from_#{scope_class_config}_#{index_name}", scope_context)
    end
  end
end

#update_all_indexes(old_values = {}, scope_context = nil) ⇒ Object

Update all indexes for a given scope context For class-level indexes (unique_index without within:), scope_context should be nil For instance-scoped indexes (with within:), scope_context should be the scope instance



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/features/relationships/indexing.rb', line 154

def update_all_indexes(old_values = {}, scope_context = nil)
  return unless self.class.respond_to?(:indexing_relationships)

  self.class.indexing_relationships.each do |config|
    field = config.field
    index_name = config.index_name
    old_field_value = old_values[field]

    # Determine which update method to call based on scope type
    # Class-level: within is nil (unique_index default) or :class (multi_index default)
    # Instance-scoped: within is a specific class
    if config.within.nil? || config.within == :class
      # Class-level index (auto-indexed on save)
      send("update_in_class_#{index_name}", old_field_value)
    else
      # Instance-scoped index - requires explicit scope context
      next unless scope_context

      # Use config_name for method naming
      scope_class_config = Familia.resolve_class(config.scope_class).config_name
      send("update_in_#{scope_class_config}_#{index_name}", scope_context, old_field_value)
    end
  end
end