Class: RecordCache::Index
- Inherits:
-
Object
- Object
- RecordCache::Index
- Includes:
- Deferrable
- Defined in:
- lib/record_cache/index.rb
Constant Summary collapse
- NULL =
'NULL'- @@disable_db =
false
Instance Attribute Summary collapse
-
#expiry ⇒ Object
readonly
Returns the value of attribute expiry.
-
#fields ⇒ Object
readonly
Returns the value of attribute fields.
-
#index_field ⇒ Object
readonly
Returns the value of attribute index_field.
-
#limit ⇒ Object
readonly
Returns the value of attribute limit.
-
#model_class ⇒ Object
readonly
Returns the value of attribute model_class.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#order_by ⇒ Object
readonly
Returns the value of attribute order_by.
-
#prefix ⇒ Object
readonly
Returns the value of attribute prefix.
Class Method Summary collapse
Instance Method Summary collapse
- #auto_name? ⇒ Boolean
- #cache ⇒ Object
- #cached_set(id) ⇒ Object
- #disallow_null? ⇒ Boolean
- #field_lookup(keys, model_class, field, flag = nil) ⇒ Object
- #fields_hash ⇒ Object
- #find_by_field(keys, model_class, type) ⇒ Object
- #find_by_ids(ids, model_class) ⇒ Object
- #find_method_name(type) ⇒ Object
- #full_record? ⇒ Boolean
- #includes_id? ⇒ Boolean
-
#initialize(opts) ⇒ Index
constructor
A new instance of Index.
- #invalidate(*keys) ⇒ Object
- #invalidate_from_conditions(conditions) ⇒ Object
- #invalidate_from_conditions_lambda(conditions) ⇒ Object
- #invalidate_model(model) ⇒ Object
- #namespace ⇒ Object
- #scope ⇒ Object
- #scope_query ⇒ Object
- #set_class ⇒ Object
- #to_s ⇒ Object
- #write_ahead? ⇒ Boolean
Constructor Details
#initialize(opts) ⇒ Index
Returns a new instance of Index.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/record_cache/index.rb', line 11 def initialize(opts) raise ':by => index_field required for cache' if opts[:by].nil? raise 'explicit name or prefix required with scope' if opts[:scope] and opts[:name].nil? and opts[:prefix].nil? @auto_name = opts[:name].nil? @write_ahead = opts[:write_ahead] @cache = opts[:cache].kind_of?(Symbol) ? Memcache.pool[opts[:cache]] : (opts[:cache] || CACHE) @expiry = opts[:expiry] @model_class = opts[:class] @set_class = opts[:set_class] || "#{@model_class}Set" @index_field = opts[:by].to_s @fields = opts[:fields].collect {|field| field.to_s} @prefix = opts[:prefix] @name = ( opts[:name] || [prefix, 'by', index_field].compact.join('_') ).to_s @order_by = opts[:order_by] @limit = opts[:limit] @disallow_null = opts[:null] == false @scope_query = opts[:scope] || {} end |
Instance Attribute Details
#expiry ⇒ Object (readonly)
Returns the value of attribute expiry.
7 8 9 |
# File 'lib/record_cache/index.rb', line 7 def expiry @expiry end |
#fields ⇒ Object (readonly)
Returns the value of attribute fields.
7 8 9 |
# File 'lib/record_cache/index.rb', line 7 def fields @fields end |
#index_field ⇒ Object (readonly)
Returns the value of attribute index_field.
7 8 9 |
# File 'lib/record_cache/index.rb', line 7 def index_field @index_field end |
#limit ⇒ Object (readonly)
Returns the value of attribute limit.
7 8 9 |
# File 'lib/record_cache/index.rb', line 7 def limit @limit end |
#model_class ⇒ Object (readonly)
Returns the value of attribute model_class.
7 8 9 |
# File 'lib/record_cache/index.rb', line 7 def model_class @model_class end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
7 8 9 |
# File 'lib/record_cache/index.rb', line 7 def name @name end |
#order_by ⇒ Object (readonly)
Returns the value of attribute order_by.
7 8 9 |
# File 'lib/record_cache/index.rb', line 7 def order_by @order_by end |
#prefix ⇒ Object (readonly)
Returns the value of attribute prefix.
7 8 9 |
# File 'lib/record_cache/index.rb', line 7 def prefix @prefix end |
Class Method Details
.disable_db ⇒ Object
224 225 226 |
# File 'lib/record_cache/index.rb', line 224 def self.disable_db @@disable_db = true end |
.enable_db ⇒ Object
228 229 230 |
# File 'lib/record_cache/index.rb', line 228 def self.enable_db @@disable_db = false end |
Instance Method Details
#auto_name? ⇒ Boolean
43 |
# File 'lib/record_cache/index.rb', line 43 def auto_name?; @auto_name; end |
#cache ⇒ Object
35 36 37 38 39 40 41 |
# File 'lib/record_cache/index.rb', line 35 def cache if RecordCache.config[:thread_safe] Thread.current[:record_cache] ||= @cache.clone else @cache end end |
#cached_set(id) ⇒ Object
251 252 253 254 255 256 257 |
# File 'lib/record_cache/index.rb', line 251 def cached_set(id) # Used for debugging. Gives you the RecordCache::Set that is currently in the cache. id = stringify([id]).first cache.in_namespace(namespace) do cache.get(id) end end |
#disallow_null? ⇒ Boolean
45 |
# File 'lib/record_cache/index.rb', line 45 def disallow_null?; @disallow_null; end |
#field_lookup(keys, model_class, field, flag = nil) ⇒ Object
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/record_cache/index.rb', line 141 def field_lookup(keys, model_class, field, flag = nil) keys = [*keys] keys = stringify(keys) field = field.to_s if field records_by_key = get_records(keys) field_by_index = {} all_fields = [] keys.each do |key| records = records_by_key[key] fields = field ? records.fields(field, model_class) : records.all_fields(model_class, :except => index_field) if flag == :all all_fields.concat(fields) elsif flag == :first next if fields.empty? field_by_index[index_column.type_cast(key)] = fields.first else field_by_index[index_column.type_cast(key)] = fields end end if flag == :all all_fields.uniq else field_by_index end end |
#fields_hash ⇒ Object
64 65 66 67 68 69 70 71 72 |
# File 'lib/record_cache/index.rb', line 64 def fields_hash if @fields_hash.nil? fields = full_record? ? model_class.column_names : self.fields md5 = Digest::MD5::new md5 << fields.sort.join(',') @fields_hash = md5.hexdigest end @fields_hash end |
#find_by_field(keys, model_class, type) ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/record_cache/index.rb', line 108 def find_by_field(keys, model_class, type) keys = [keys] if not keys.kind_of?(Array) keys = stringify(keys) records_by_key = get_records(keys) case type when :first keys.each do |key| model = records_by_key[key].instantiate_first(model_class, full_record?) return model if model end return nil when :all models = [] keys.each do |key| models.concat( records_by_key[key].instantiate(model_class, full_record?) ) end models when :set, :ids ids = [] keys.each do |key| ids.concat( records_by_key[key].ids(model_class) ) end type == :set ? set_class.new(ids) : ids when :raw raw_records = [] keys.each do |key| raw_records.concat( records_by_key[key].records(model_class) ) end raw_records end end |
#find_by_ids(ids, model_class) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/record_cache/index.rb', line 74 def find_by_ids(ids, model_class) expects_array = ids.first.kind_of?(Array) ids = ids.flatten.compact.collect {|id| id.to_i} ids = stringify(ids) if ids.empty? return [] if expects_array raise ActiveRecord::RecordNotFound, "Couldn't find #{model_class} without an ID" end records_by_id = get_records(ids) models = ids.collect do |id| records = records_by_id[id] model = records.instantiate_first(model_class, full_record?) if records # try to get record from db again before we throw an exception if model.nil? invalidate(id) records = get_records([id])[id] model = records.instantiate_first(model_class, full_record?) if records end raise ActiveRecord::RecordNotFound, "Couldn't find #{model_class} with ID #{id}" unless model model end if models.size == 1 and not expects_array models.first else models end end |
#find_method_name(type) ⇒ Object
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/record_cache/index.rb', line 232 def find_method_name(type) if name =~ /(^|_)by_/ if type == :first "find_#{name}" else "find_#{type}_#{name}" end else case type when :all "find_#{name}" when :first "find_#{type}_#{name.singularize}" else "find_#{name.singularize}_#{type}" end end end |
#full_record? ⇒ Boolean
47 48 49 |
# File 'lib/record_cache/index.rb', line 47 def full_record? fields.empty? end |
#includes_id? ⇒ Boolean
51 52 53 |
# File 'lib/record_cache/index.rb', line 51 def includes_id? full_record? or fields.include?('id') end |
#invalidate(*keys) ⇒ Object
168 169 170 171 172 173 174 175 176 177 |
# File 'lib/record_cache/index.rb', line 168 def invalidate(*keys) return if model_class.record_cache_config[:disable_write] keys = stringify(keys) cache.in_namespace(namespace) do keys.each do |key| cache.delete(key) end end end |
#invalidate_from_conditions(conditions) ⇒ Object
186 187 188 |
# File 'lib/record_cache/index.rb', line 186 def invalidate_from_conditions(conditions) invalidate_from_conditions_lambda(conditions).call end |
#invalidate_from_conditions_lambda(conditions) ⇒ Object
179 180 181 182 183 184 |
# File 'lib/record_cache/index.rb', line 179 def invalidate_from_conditions_lambda(conditions) sql = "SELECT #{index_field} FROM #{table_name} " model_class.send(:add_conditions!, sql, conditions, model_class.send(:scope, :find)) ids = db.select_values(sql) lambda { invalidate(*ids) } end |
#invalidate_model(model) ⇒ Object
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/record_cache/index.rb', line 190 def invalidate_model(model) attribute = model.read_attribute(index_field) attribute_was = model.attr_was(index_field) if scope.match_previous?(model) if write_ahead? remove_from_cache(model) else now_and_later do invalidate(attribute_was) end end end if scope.match_current?(model) if write_ahead? add_to_cache(model) elsif not (scope.match_previous?(model) and attribute_was == attribute) now_and_later do invalidate(attribute) end end end end |
#namespace ⇒ Object
59 60 61 62 |
# File 'lib/record_cache/index.rb', line 59 def namespace record_cache_class = model_class.record_cache_class "#{record_cache_class.name}_#{record_cache_class.version}_#{RecordCache.version}_#{fields_hash}:#{name}" end |
#scope ⇒ Object
219 220 221 |
# File 'lib/record_cache/index.rb', line 219 def scope @scope ||= Scope.new(model_class, scope_query) end |
#scope_query ⇒ Object
214 215 216 217 |
# File 'lib/record_cache/index.rb', line 214 def scope_query @scope_query[:type] ||= model_class.to_s if sub_class? @scope_query end |
#set_class ⇒ Object
55 56 57 |
# File 'lib/record_cache/index.rb', line 55 def set_class @set_class.constantize end |
#to_s ⇒ Object
31 32 33 |
# File 'lib/record_cache/index.rb', line 31 def to_s "<RecordCache::Index #{@model_class} by #{@index_field} (#{@name})>" end |
#write_ahead? ⇒ Boolean
44 |
# File 'lib/record_cache/index.rb', line 44 def write_ahead?; @write_ahead; end |