Notes posted by LacKac

RSS feed
October 2, 2008
1 thank

Setting ttl

Use the expires_in option to set a TTL for the cached item.

Rails.cache.write("top_items", :expires_in => 5.minutes)

You can use this with the fetch method as well:

Rails.cache.fetch("top_items", :expires_in => 5.minutes) do
  # some very expensive calculations

Note: this only works with supporting cache stores, like the MemCacheStore

September 3, 2008
1 thank

Creating additional cache stores

This method can be used to create additional cache stores for your application:

# creates a new Memory Store
mem_store = ActiveSupport::Cache.lookup_store
# creates a new MemCache Store
mem_cache_store = ActiveSupport::Cache.lookup_store :mem_cache_store, 'localhost:11212', :namespace => 'other_stuff'

The method takes the same arguments as the cache_store config. For more information about that go to ActionController::Caching.

August 17, 2008
6 thanks

Re: Convert an Array of Arrays to a Hash using inject

If you’re sure you have a two-level array (no other arrays inside the pairs) and exactly two items in each pair, then it’s faster and shorter to use this:

array = [['A', 'a'], ['B', 'b'], ['C', 'c']]
hash = Hash[*array.flatten]

For more than two-level deep arrays this will give the wrong result or even an error (for some inputs).

array = [['A', 'a'], ['B', 'b'], ['C', ['a', 'b', 'c']]]
hash = Hash[*array.flatten]
# => {"A"=>"a", "B"=>"b", "C"=>"a", "b"=>"c"}

But if you’re running Ruby 1.8.7 or greater you can pass an argument to Array#flatten and have it flatten only one level deep:

# on Ruby 1.8.7+
hash = Hash[*array.flatten(1)]
# => {"A"=>"a", "B"=>"b", "C"=>["a", "b", "c"]}
August 13, 2008
7 thanks

Re: Helper method taking a block

The same using the ActionView::Helpers::TagHelper#content_tag and ActionView::Helpers::CaptureHelper#capture methods:

def render_tree(collection, &block)
      collection.collect { |item|
        content_tag(:li, capture(item, &block))

The benefit is that it’s easier to improve with html attributes (just add a hash of options to the content_tag call) and it makes just one call to concat (which probably makes it faster).

August 4, 2008
0 thanks

How to handle the MultiparameterAssignmentErrors exception

If you expect to get this error, do this in your controller:

def create
  @event = Event.new
  @event.attributes = params[:event]
rescue ActiveRecord::MultiparameterAssignmentErrors => e
  e.errors.each do |error|
    @event.errors.add(error.attribute, ActiveRecord::Errors.default_error_messages[:invalid])
rescue ActiveRecord::RecordInvalid
  # event is invalid
  if @event.errors.empty? and not @event.new_record?
    redirect_to event_path(@event)
    render :action => :new

If attribute assignment gives the MultiparameterAssignmentErrors exception we handle it by adding ‘invalid’ errors to the attributes involved. We also rescue the RecordInvalid exception and handle all the redirecting/rendering in the ensure block.

July 25, 2008
2 thanks

If you need something more

Use the brilliant chronic gem: http://chronic.rubyforge.org/

require 'chronic'
Time.now # => Fri Jul 25 00:00:25 0200 2008
Chronic.parse 'tomorrow 8 in the evening'  # => Sat Jul 26 20:00:00 0200 2008
Chronic.parse 'next Monday noon'           # => Mon Jul 28 12:00:00 0200 2008
Chronic.parse 'first Wednesday of Aug'     # => Wed Aug 06 12:00:00 0200 2008
Chronic.parse 'first Wednesday of Aug 7pm' # => Wed Aug 06 19:00:00 0200 2008