Module: IdentityCache::ConfigurationDSL::ClassMethods

Defined in:
lib/identity_cache/configuration_dsl.rb

Instance Method Summary collapse

Instance Method Details

#cache_attribute(attribute, by: :id, unique: true) ⇒ Object

Will cache a single attribute on its own blob, it will add a fetch_attribute_by_id (or the value of the by option).

Example:

class Product
  include IdentityCache
  cache_attribute :quantity, by: :name
  cache_attribute :quantity, by: [:name, :vendor]
end

Parameters

attribute Symbol with the name of the attribute being cached

Options

  • by: Other attribute or attributes in the model to keep values indexed. Default is :id

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


176
177
178
# File 'lib/identity_cache/configuration_dsl.rb', line 176

def cache_attribute(attribute, by: :id, unique: true)
  cache_attribute_by_alias(attribute.inspect, attribute, by: by, unique: unique)
end

#cache_has_many(association, embed: :ids, inverse_name: nil) ⇒ Object

Will cache an association to the class including IdentityCache. The embed option, if set, will make IdentityCache keep the association values in the same cache entry as the parent.

Embedded associations are more effective in offloading database work, however they will increase the size of the cache entries and make the whole entry expire when any of the embedded members change.

Example:

class Product
  include IdentityCache
  has_many :options
  has_many :orders
  has_many :buyers
  cache_has_many :options, embed: :ids
  cache_has_many :orders
  cache_has_many :buyers, inverse_name: 'line_item'
end

Parameters

association Name of the association being cached as a symbol

Options

  • embed: If set to true, will cause IdentityCache to keep the values for this association in the same cache entry as the parent, instead of its own.

  • inverse_name: The name of the parent in the association if the name is not the lowercase pluralization of the parent object's class


109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/identity_cache/configuration_dsl.rb', line 109

def cache_has_many(association, embed: :ids, inverse_name: nil)
  ensure_base_model
  check_association_for_caching(association)
  options = { embed: embed, inverse_name: inverse_name }
  self.cached_has_manys[association] = options

  case embed
  when true
    build_recursive_association_cache(association, options)
  when :ids
    build_id_embedded_has_many_cache(association, options)
  else
    raise NotImplementedError
  end
end

#cache_has_one(association, embed: true, inverse_name: nil) ⇒ Object

Will cache an association to the class including IdentityCache. IdentityCache will keep the association values in the same cache entry as the parent.

Example:

class Product
  cache_has_one :store, embed: true
  cache_has_one :vendor
end

Parameters

association Symbol with the name of the association being cached

Options

  • embed: Only true is supported, which is also the default, so IdentityCache will keep the values for this association in the same cache entry as the parent, instead of its own.

  • inverse_name: The name of the parent in the association ( only necessary if the name is not the lowercase pluralization of the parent object's class)


146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/identity_cache/configuration_dsl.rb', line 146

def cache_has_one(association, embed: true, inverse_name: nil)
  ensure_base_model
  check_association_for_caching(association)
  options = { embed: embed, inverse_name: inverse_name }
  self.cached_has_ones[association] = options

  if options[:embed] == true
    build_recursive_association_cache(association, options)
  else
    raise NotImplementedError
  end
end

#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

Raises:

  • (NotImplementedError)

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/identity_cache/configuration_dsl.rb', line 40

def cache_index(*fields, unique: false)
  raise NotImplementedError, "Cache indexes need an enabled primary index" unless primary_cache_index_enabled
  cache_attribute_by_alias('primary_key', 'id', by: fields, unique: unique)

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

  if unique
    self.instance_eval(ruby = <<-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 ActiveRecord::RecordNotFound
      end
    CODE
  else
    self.instance_eval(ruby = <<-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
    self.instance_eval(ruby = <<-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