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.



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

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.



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

def cached_ids_name
  @cached_ids_name
end

#ids_variable_nameObject (readonly)

Returns the value of attribute ids_variable_name.



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

def ids_variable_name
  @ids_variable_name
end

Instance Method Details

#buildObject



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

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 (loaded_by_idc? || 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



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

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



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

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

#fetch_async(load_strategy, records) ⇒ Object



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
83
# File 'lib/identity_cache/cached/reference/has_many.rb', line 56

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



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

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

#write(record, ids) ⇒ Object



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

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