Class: ActiveRegistry

Inherits:
Set
  • Object
show all
Defined in:
lib/active_registry.rb

Defined Under Namespace

Classes: MoreThanOneRecordFound

Constant Summary collapse

VERSION =
"0.1.1"
DEFAULT_INDEX =
:object_id

Instance Method Summary collapse

Constructor Details

#initialize(*args, indexes: []) ⇒ ActiveRegistry

Returns a new instance of ActiveRegistry.



9
10
11
12
13
# File 'lib/active_registry.rb', line 9

def initialize(*args, indexes: [])
  @indexed = {}
  super(*args)
  reindex!(indexes)
end

Instance Method Details

#add(item) ⇒ Object Also known as: <<



41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/active_registry.rb', line 41

def add(item)
  @indexed.each do |idx, store|
    watch_setter(item, idx) unless include?(item)
    begin
      idx_value = item.send(idx)
      (store[idx_value] ||= Set.new) << (item)
    rescue NoMethodError => e
      raise "#{item.name} cannot be added because indexable attribute (#{idx}) is missing."
    end
  end
  super(item)
end

#delete(item) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/active_registry.rb', line 27

def delete(item)
  @indexed.each do |idx, store|
    ignore_setter(item, idx) if include?(item)
    begin
      idx_value = item.send(idx)
      (store[idx_value] ||= Set.new).delete(item)
      store.delete(idx_value) if store[idx_value].empty?
    rescue NoMethodError => e
      raise "#{item.name} cannot be added because indexable attribute (#{idx}) is missing."
    end
  end
  super(item)
end

#find(search_criteria) ⇒ Object



59
60
61
# File 'lib/active_registry.rb', line 59

def find(search_criteria)
  _find(search_criteria) { warn "There were more than 1 records found" }
end

#find!(search_criteria) ⇒ Object



55
56
57
# File 'lib/active_registry.rb', line 55

def find!(search_criteria)
  _find(search_criteria) { raise MoreThanOneRecordFound, "There were more than 1 records found" }
end

#index(*indexes) ⇒ Object



74
75
76
77
78
79
80
81
82
# File 'lib/active_registry.rb', line 74

def index(*indexes)
  indexes.each do |idx|
    warn "Index #{idx} already exists!" and next if @indexed.key?(idx)
    each { |item| watch_setter(item, idx) }
    indexed_records = group_by { |a| a.send(idx) }
    indexed_sets = Hash[indexed_records.keys.zip(indexed_records.values.map { |e| Set.new(e) })]
    @indexed[idx] = indexed_sets
  end
end

#indexesObject



23
24
25
# File 'lib/active_registry.rb', line 23

def indexes
  @indexed.keys - [:object_id]
end

#inspectObject



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

def inspect
  to_a.inspect
end

#reindex!(indexes = []) ⇒ Object



84
85
86
87
# File 'lib/active_registry.rb', line 84

def reindex!(indexes = [])
  @indexed = {}
  index(*([DEFAULT_INDEX] | indexes))
end

#to_hObject



19
20
21
# File 'lib/active_registry.rb', line 19

def to_h
  @indexed
end

#where(search_criteria) ⇒ Object



63
64
65
66
67
68
69
70
71
72
# File 'lib/active_registry.rb', line 63

def where(search_criteria)
  sets = search_criteria.inject([]) do |sets, (idx, value)|
    raise "No '#{idx}' index! Add it with '.index(:#{idx})'" unless @indexed.include?(idx)
    sets << (@indexed.dig(idx, value) || Set.new)
  end

  subset_records = sets.reduce(sets.first, &:&)
  subset_registry = ActiveRegistry.new(subset_records, indexes: indexes)
  subset_registry
end