From 82090cb7803fb21f7e3fb4d42710aed1f570ece7 Mon Sep 17 00:00:00 2001 From: Matt Aimonetti Date: Tue, 7 Jul 2009 23:55:20 -0700 Subject: [PATCH] modified the timestamp parsing to run faster, making a big difference when loading huge datasets --- lib/couchrest/mixins/properties.rb | 40 +++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/lib/couchrest/mixins/properties.rb b/lib/couchrest/mixins/properties.rb index 6a69b44..5d3e8ed 100644 --- a/lib/couchrest/mixins/properties.rb +++ b/lib/couchrest/mixins/properties.rb @@ -1,6 +1,25 @@ require 'time' require File.join(File.dirname(__FILE__), '..', 'more', 'property') +class Time + # returns a local time value much faster than Time.parse + def self.mktime_with_offset(string) + string =~ /(\d{4})\/(\d{2})\/(\d{2}) (\d{2}):(\d{2}):(\d{2}) ([\+\-])(\d{2})/ + # $1 = year + # $2 = month + # $3 = day + # $4 = hours + # $5 = minutes + # $6 = seconds + # $7 = time zone direction + # $8 = tz difference + # utc time with wrong TZ info: + time = mktime($1, RFC2822_MONTH_NAME[$2.to_i - 1], $3, $4, $5, $6, $7) + tz_difference = ("#{$7 == '-' ? '+' : '-'}#{$8}".to_i * 3600) + time + tz_difference + zone_offset(time.zone) + end +end + module CouchRest module Mixins module Properties @@ -24,7 +43,7 @@ module CouchRest self.class.properties.each do |property| key = property.name.to_s # let's make sure we have a default - unless property.default.nil? + if property.default if property.default.class == Proc self[key] = property.default.call else @@ -37,10 +56,11 @@ module CouchRest def cast_keys return unless self.class.properties self.class.properties.each do |property| + next unless property.casted key = self.has_key?(property.name) ? property.name : property.name.to_sym # Don't cast the property unless it has a value - next unless self[key] + next unless self[key] target = property.type if target.is_a?(Array) klass = ::CouchRest.constantize(target[0]) @@ -48,19 +68,21 @@ module CouchRest # Auto parse Time objects obj = ( (property.init_method == 'new') && klass == Time) ? Time.parse(value) : klass.send(property.init_method, value) obj.casted_by = self if obj.respond_to?(:casted_by) - obj + obj end else # Auto parse Time objects - self[property.name] = if ((property.init_method == 'new') && target == 'Time') - self[key].is_a?(String) ? Time.parse(self[key].dup) : self[key] + self[property.name] = if ((property.init_method == 'new') && target == 'Time') + # Using custom time parsing method because Ruby's default method is toooo slow + self[key].is_a?(String) ? Time.mktime_with_offset(self[key].dup) : self[key] else # Let people use :send as a Time parse arg klass = ::CouchRest.constantize(target) - klass.send(property.init_method, self[key].dup) - end + klass.send(property.init_method, self[key].dup) + end self[property.name].casted_by = self if self[property.name].respond_to?(:casted_by) - end + end + end end @@ -122,4 +144,4 @@ module CouchRest end end -end +end \ No newline at end of file