Flowdock

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
end

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)
  concat(
    content_tag(:ul,
      collection.collect { |item|
        content_tag(:li, capture(item, &block))
      }.join("\n")
    ),
    block.binding
  )
end

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]
  @event.save!
rescue ActiveRecord::MultiparameterAssignmentErrors => e
  e.errors.each do |error|
    @event.errors.add(error.attribute, ActiveRecord::Errors.default_error_messages[:invalid])
  end
rescue ActiveRecord::RecordInvalid
  # event is invalid
ensure
  if @event.errors.empty? and not @event.new_record?
    redirect_to event_path(@event)
  else
    render :action => :new
  end
end

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