Class: IdentityCache::Cached::Reference::HasMany

Inherits:
Association
  • Object
show all
Defined in:
lib/identity_cache/cached/reference/has_many.rb

Overview

:nodoc:

Instance Attribute Summary collapse

Attributes inherited from Association

#cached_accessor_name, #name, #records_variable_name, #reflection

Instance Method Summary collapse

Methods inherited from Association

#embedded?, #embedded_by_reference?, #embedded_recursively?, #inverse_name, #validate

Constructor Details

#initialize(name, reflection:) ⇒ HasMany

Returns a new instance of HasMany.



6
7
8
9
10
# File 'lib/identity_cache/cached/reference/has_many.rb', line 6

def initialize(name, reflection:)
  super
  @cached_ids_name = "fetch_#{ids_name}"
  @ids_variable_name = :"@#{ids_cached_reader_name}"
end

Instance Attribute Details

#cached_ids_nameObject (readonly)

Returns the value of attribute cached_ids_name.



12
13
14
# File 'lib/identity_cache/cached/reference/has_many.rb', line 12

def cached_ids_name
  @cached_ids_name
end

#ids_variable_nameObject (readonly)

Returns the value of attribute ids_variable_name.



12
13
14
# File 'lib/identity_cache/cached/reference/has_many.rb', line 12

def ids_variable_name
  @ids_variable_name
end

Instance Method Details

#buildObject



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/identity_cache/cached/reference/has_many.rb', line 14

def build
  reflection.active_record.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
    attr_reader :#{ids_cached_reader_name}

    def #{cached_ids_name}
      #{ids_variable_name} ||= #{ids_name}
    end

    def #{cached_accessor_name}
      assoc = association(:#{name})
      if assoc.klass.should_use_cache? && !assoc.loaded? && assoc.target.blank?
        #{records_variable_name} ||= #{reflection.class_name}.fetch_multi(#{cached_ids_name})
      else
        #{name}.to_a
      end
    end
  RUBY

  ParentModelExpiration.add_parent_expiry_hook(self)
end

#clear(record) ⇒ Object



43
44
45
46
47
48
49
# File 'lib/identity_cache/cached/reference/has_many.rb', line 43

def clear(record)
  [ids_variable_name, records_variable_name].each do |ivar|
    if record.instance_variable_defined?(ivar)
      record.remove_instance_variable(ivar)
    end
  end
end

#fetch(records) ⇒ Object



51
52
53
# File 'lib/identity_cache/cached/reference/has_many.rb', line 51

def fetch(records)
  fetch_async(LoadStrategy::Eager, records) { |child_records| child_records }
end

#fetch_async(load_strategy, records) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/identity_cache/cached/reference/has_many.rb', line 55

def fetch_async(load_strategy, records)
  fetch_embedded_async(load_strategy, records) do
    ids_to_parent_record = records.each_with_object({}) do |record, hash|
      child_ids = record.send(cached_ids_name)
      child_ids.each do |child_id|
        hash[child_id] = record
      end
    end

    load_strategy.load_multi(
      reflection.klass.cached_primary_index,
      ids_to_parent_record.keys
    ) do |child_records_by_id|
      parent_record_to_child_records = Hash.new { |h, k| h[k] = [] }

      child_records_by_id.each do |id, child_record|
        parent_record = ids_to_parent_record.fetch(id)
        parent_record_to_child_records[parent_record] << child_record
      end

      parent_record_to_child_records.each do |parent, children|
        parent.instance_variable_set(records_variable_name, children)
      end

      yield child_records_by_id.values.compact
    end
  end
end

#read(record) ⇒ Object



35
36
37
# File 'lib/identity_cache/cached/reference/has_many.rb', line 35

def read(record)
  record.public_send(cached_ids_name)
end

#write(record, ids) ⇒ Object



39
40
41
# File 'lib/identity_cache/cached/reference/has_many.rb', line 39

def write(record, ids)
  record.instance_variable_set(ids_variable_name, ids)
end