Module: IdentityCache::WithPrimaryIndex::ClassMethods

Defined in:
lib/identity_cache/with_primary_index.rb

Instance Method Summary collapse

Instance Method Details

#cache_index(*fields, unique: false) ⇒ Object

Declares a new index in the cache for the class where IdentityCache was included.

IdentityCache will add a fetch_by_field1_and_field2_and_…field for every index.

Example:

class Product
  include IdentityCache
  cache_index :name, :vendor
end

Will add Product.fetch_by_name_and_vendor

Parameters

fields Array of symbols or strings representing the fields in the index

Options

  • unique: if the index would only have unique values. Default is false



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
83
84
85
86
87
88
89
90
91
92
# File 'lib/identity_cache/with_primary_index.rb', line 55

def cache_index(*fields, unique: false)
  attribute_proc = -> { primary_key }
  cache_attribute_by_alias(attribute_proc, alias_name: :id, by: fields, unique: unique)

  field_list = fields.join("_and_")
  arg_list = (0...fields.size).collect { |i| "arg#{i}" }.join(',')

  if unique
    instance_eval(<<-CODE, __FILE__, __LINE__ + 1)
      def fetch_by_#{field_list}(#{arg_list}, includes: nil)
        id = fetch_id_by_#{field_list}(#{arg_list})
        id && fetch_by_id(id, includes: includes)
      end

      # exception throwing variant
      def fetch_by_#{field_list}!(#{arg_list}, includes: nil)
        fetch_by_#{field_list}(#{arg_list}, includes: includes) or raise IdentityCache::RecordNotFound
      end
    CODE
  else
    instance_eval(<<-CODE, __FILE__, __LINE__ + 1)
      def fetch_by_#{field_list}(#{arg_list}, includes: nil)
        ids = fetch_id_by_#{field_list}(#{arg_list})
        ids.empty? ? ids : fetch_multi(ids, includes: includes)
      end
    CODE
  end

  if fields.length == 1
    instance_eval(<<-CODE, __FILE__, __LINE__ + 1)
      def fetch_multi_by_#{field_list}(index_values, includes: nil)
        ids = fetch_multi_id_by_#{field_list}(index_values).values.flatten(1)
        return ids if ids.empty?
        fetch_multi(ids, includes: includes)
      end
    CODE
  end
end

#cached_primary_indexObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



25
26
27
# File 'lib/identity_cache/with_primary_index.rb', line 25

def cached_primary_index
  @cached_primary_index ||= Cached::PrimaryIndex.new(self)
end

#exists_with_identity_cache?(id) ⇒ Boolean

Similar to ActiveRecord::Base#exists? will return true if the id can be found in the cache or in the DB.

Returns:

  • (Boolean)


96
97
98
# File 'lib/identity_cache/with_primary_index.rb', line 96

def exists_with_identity_cache?(id)
  !!fetch_by_id(id)
end

#expire_primary_key_cache_index(id) ⇒ Object

Invalidates the primary cache index for the associated record. Will not invalidate cached attributes.



131
132
133
# File 'lib/identity_cache/with_primary_index.rb', line 131

def expire_primary_key_cache_index(id)
  cached_primary_index.expire(id)
end

#fetch(id, includes: nil) ⇒ Object

Default fetcher added to the model on inclusion, it behaves like ActiveRecord::Base.find, but will raise IdentityCache::RecordNotFound if the id is not in the cache.



113
114
115
116
117
# File 'lib/identity_cache/with_primary_index.rb', line 113

def fetch(id, includes: nil)
  fetch_by_id(id, includes: includes) || raise(
    IdentityCache::RecordNotFound, "Couldn't find #{name} with ID=#{id}"
  )
end

#fetch_by_id(id, includes: nil) ⇒ Object

Default fetcher added to the model on inclusion, it behaves like ActiveRecord::Base.where(id: id).first



102
103
104
105
106
107
108
# File 'lib/identity_cache/with_primary_index.rb', line 102

def fetch_by_id(id, includes: nil)
  ensure_base_model
  raise_if_scoped
  record = cached_primary_index.fetch(id)
  prefetch_associations(includes, [record]) if record && includes
  record
end

#fetch_multi(*ids, includes: nil) ⇒ Object

Default fetcher added to the model on inclusion, if behaves like ActiveRecord::Base.find_all_by_id



121
122
123
124
125
126
127
128
# File 'lib/identity_cache/with_primary_index.rb', line 121

def fetch_multi(*ids, includes: nil)
  ensure_base_model
  raise_if_scoped
  ids.flatten!(1)
  records = cached_primary_index.fetch_multi(ids)
  prefetch_associations(includes, records) if includes
  records
end

#primary_cache_index_enabledObject



29
30
31
# File 'lib/identity_cache/with_primary_index.rb', line 29

def primary_cache_index_enabled
  true
end