Rails caching with expires_in lambda

When expires_in gets complicated you can simply use
:expires_in => lambda{ Time.now.to_i % 100 }

Code

class ActionController::Base
  def write_fragment_with_lambda_expire(key, content, options = nil)
    if options.is_a? Hash and options[:expires_in].is_a? Proc
      options = options.merge(:expires_in  => options[:expires_in].call)
    end
    write_fragment_without_lambda_expire(key, content, options)
  end

  alias_method_chain :write_fragment, :lambda_expire
end

Finding the oldest element in memcached

We always wanted to know how full memcached is, and therefore know at which age an element is dropped. This hacky script will find it out, by inserting 30 values each day and taking out 30 untouched values from 30 previous days <-> if one is missing, thats how old your oldest element is.
(if you know a better way, let me know 😉 )

Usage
Run one time each day (via cron) and store output into a logfile after 26 days:

rake check_memcached_age
Stats for 2009-12-01:
0: still there...
1: still there...
2: still there...
3: still there...
...
23: still there...
24: still there...
25: 
26: 
...

Your cache is 24 days old!

Script

task :check_memcached_age => :environment do
  cache = ActionController::Base.cache_store
  # insert probes for today
  (0..30).each do |i|
    cache.write "memcached-probe-#{Date.today.to_s(:db)}--#{i}", 'still there...'
  end

  # extract old probes
  results = (0..30).to_a.map do |i|
    [i, cache.read("memcached-probe-#{(Date.today-i.days).to_s(:db)}--#{i}")]
  end

  puts "stats for #{Date.today.to_s(:db)}"
  puts results.map{|day, present| "#{day}: #{present}"} * "\n"  
end

ActiveRecord.touch_without_callbacks

When updating to 2.3.4 I noticed that touch is
no longer a simple ‘update :updated_at’, but a save!,
which caused some code to break
(e.g. touch`ing in after_save == loop)

Usage

User.first.touch_without_callbacks
User.touch_without_callbacks([User.first.id, User.last.id])

Install
Paste somewhere…

# Provide .touch as it was in 2.3.2, simply update the :updated_at field.
class ActiveRecord::Base
  def touch_without_callbacks
    now = Time.now.utc
    self.class.touch_without_callbacks(id, now)
    self.updated_at = now
  end

  def self.touch_without_callbacks(ids, time=Time.now.utc)
    update_all({:updated_at=>time}, :id=>ids)
  end
end

Hash.pass and Hash.block that also work with HashWithIndifferentAccess

A new version of the old pass/block hack, but this time they also work as expected on HashWithIndifferentAccess (params/session…)

When attr_protected or attr_accessible are just to complicated, a simple user.attributes = params[:user].pass(:name, :email) just works.
Or user.attributes = params[:user].block(:admin) for the opposite…

# lets through the keys in the argument
# >> {:one => 1, :two => 2, :three => 3}.pass(:one)
# => {:one=>1}
def pass(*selected_keys)
  tmp = self.dup
  dup.block(*selected_keys).keys.each{|k| tmp.delete k }
  tmp
end

# blocks the keys in the arguments
# >> {:one => 1, :two => 2, :three => 3}.block(:one)
# => {:two=>2, :three=>3}
def block(*blocked_keys)
  tmp = self.dup
  blocked_keys.each{|k| tmp.delete k }
  tmp
end