module RecordCache::Strategy::Util
Constants
- ATTRIBUTES_KEY
- CLASS_KEY
- NIL_COMES_FIRST
If
x.nil?
this class will return -1 for +x <=> y+
Public Class Methods
deserialize(serialized)
click to toggle source
deserialize a cached record
# File lib/record_cache/strategy/util.rb, line 18 def deserialize(serialized) record = serialized[CLASS_KEY].constantize.allocate attributes = serialized[ATTRIBUTES_KEY].clone record.class.serialized_attributes.keys.each do |attribute| if attributes[attribute].respond_to?(:unserialize) if attributes[attribute].method(:unserialize).arity > 0 attributes[attribute] = attributes[attribute].unserialize(attributes[attribute].value) else attributes[attribute] = attributes[attribute].unserialize end end end record.init_with('attributes' => attributes) record end
filter!(records, wheres)
click to toggle source
Filter the cached records in memory only simple x = y or x IN (a,b,c) can be handled string comparison is case insensitive Example:
RecordCache::Strategy::Util.filter!(Apple.all, :price => [0.49, 0.59, 0.69], :name => "Green Apple")
# File lib/record_cache/strategy/util.rb, line 39 def filter!(records, wheres) wheres.each_pair do |attr, value| attr = attr.to_sym if value.is_a?(Array) where_values = Set.new(value.first.respond_to?(:downcase) ? value.map(&:downcase) : value) records.to_a.select! do |record| attribute_value = record.send(attr) attribute_value = attribute_value.downcase if attribute_value.respond_to?(:downcase) where_values.include?(attribute_value) end else where_value = value.respond_to?(:downcase) ? value.downcase : value records.to_a.select! do |record| attribute_value = record.send(attr) attribute_value = attribute_value.downcase if attribute_value.respond_to?(:downcase) attribute_value == where_value end end end end
serialize(record)
click to toggle source
serialize one record before adding it to the cache creates a shallow clone with a version and without associations
# File lib/record_cache/strategy/util.rb, line 12 def serialize(record) {CLASS_KEY => record.class.name, ATTRIBUTES_KEY => record.instance_variable_get(:@attributes).dup} end
sort!(records, *sort_orders)
click to toggle source
Sort the cached records in memory, similar to MySql sorting rules including collatiom Simply provide the Symbols of the attributes to sort in Ascending order, or use
- <attribute>, false
-
for Descending order.
Example:
RecordCache::Strategy::Util.sort!(Apple.all, :name) RecordCache::Strategy::Util.sort!(Apple.all, [:name, false]) RecordCache::Strategy::Util.sort!(Apple.all, [:price, false], :name) RecordCache::Strategy::Util.sort!(Apple.all, [:price, false], [:name, true]) RecordCache::Strategy::Util.sort!(Apple.all, [[:price, false], [:name, true]])
# File lib/record_cache/strategy/util.rb, line 69 def sort!(records, *sort_orders) return records if records.empty? || sort_orders.empty? if sort_orders.first.is_a?(Array) && sort_orders.first.first.is_a?(Array) sort_orders = sort_orders.first else sort_orders = sort_orders.map{ |order| order.is_a?(Array) ? order : [order, true] } unless sort_orders.all?{ |order| order.is_a?(Array) } end records.sort!(&sort_proc(records.first.class, sort_orders)) Collator.clear records end
Private Class Methods
sort_proc(base, sort_orders)
click to toggle source
Retrieve the Proc based on the order by attributes Note: Case insensitive sorting with collation is used for Strings
# File lib/record_cache/strategy/util.rb, line 85 def sort_proc(base, sort_orders) # [['(COLLATER.collate(x.name) || NIL_COMES_FIRST)', 'COLLATER.collate(y.name)'], ['(y.updated_at || NIL_COMES_FIRST)', 'x.updated_at']] sort = sort_orders.map do |attr, asc| attr = attr.to_s lr = ["x.", "y."] lr.reverse! unless asc lr.each{ |s| s << attr } lr.each{ |s| s.replace("Collator.collate(#{s})") } if base.columns_hash[attr].type == :string lr[0].replace("(#{lr[0]} || NIL_COMES_FIRST)") lr end # ['[(COLLATER.collate(x.name) || NIL_COMES_FIRST), (y.updated_at || NIL_COMES_FIRST)]', '[COLLATER.collate(y.name), x.updated_at]'] sort = sort.transpose.map{|s| s.size == 1 ? s.first : "[#{s.join(',')}]"} # Proc.new{ |x,y| { ([(COLLATER.collate(x.name) || NIL_COMES_FIRST), (y.updated_at || NIL_COMES_FIRST)] <=> [COLLATER.collate(y.name), x.updated_at]) || 1 } eval("Proc.new{ |x,y| (#{sort[0]} <=> #{sort[1]}) || 1 }") end