libXML for Active Resource 2.0

Posted by Bart ten Brinke Mon, 25 Feb 2008 08:19:39 GMT

I received an email from Stevie Clifton today, asking about our libXML patch for rails 2.0. As we have been running 2.0 for quite some time now, I never realised I forgot to post the new overrides.

The file below goes into /config/initializers/libxml.rb

# This is actally a fix for activeresource as it
# will behave incorrectly when it encounters
# Complex xml files. This override fixes this,
# but it should be submitted to rails trunk.
module ActiveResource
  module Formats
    module XmlFormat
      private
      def from_xml_data(data)
          if data.is_a?(Hash) && data.keys.size == 1
            from_xml_data(data.values.first)
          else
            data
          end
        end      
    end
  end
end

module Nedap #:nodoc:
  module Hash #:nodoc:
    module Conversions

      def self.included(klass)
        require 'xml/libxml'
        klass.extend(ClassMethods)
      end

      module ClassMethods

        # Hash from_xml mixin that uses libxml.
        # This ensures a 20x speed increase
        # Compared to libxml. Plus it is less ugly.
        def from_xml(xml) 
          result = XML::Parser.string(xml).parse 
          return { result.root.name.to_s => xml_node_to_hash(result.root)} 
        end 

        def xml_node_to_hash(node) 
          # If we are at the root of the document, start the hash 
          if node.element? 
           if node.children? 
              result_hash = {} 

              node.each_child do |child| 
                result = xml_node_to_hash(child) 

              if child.name == "text"
                if !child.next? and !child.prev?
                  return result
                end
              elsif result_hash[child.name] 
                  if result_hash[child.name].is_a?(Object::Array) 
                    result_hash[child.name] << result 
                  else 
                    result_hash[child.name] = [result_hash[child.name]] << result 
                  end 
                else 
                  result_hash[child.name] = result 
                end              
              end 

              return result_hash 
            else 
              return nil 
           end 
           else 
            return node.content.to_s 
          end 
        end          

      end        
    end
  end
end 

Hash.send :include, Nedap::Hash::Conversions

There you go. You now have a blazingly fast active resource! If you want some more bang out of your resource, add the following mixins to the initializer too:

# Add inflate to NET class (zLib support)
module Net
  class HTTPResponse
     def inflate!
       require 'zlib'
       @body = Zlib::Inflate.inflate(@body)
     end
   end
 end

# Increase timeout and buffersize for big XML files
module Net
  class BufferedIO 
    def rbuf_fill
      timeout(3000) { 
        @rbuf << @io.sysread(32768) 
      }
    end 
  end
end

Posted in  | Tags , , ,  | no comments

Moving to 2.0

Posted by Andre Foeken Thu, 18 Oct 2007 13:27:19 GMT

Issues found so far:

  • Lots of small routing changes. Thank god for grep! : addresses_path(@employee) => employee_addresses_path(@employee) . (Don't forget the *_url methods!)

  • Several plugins failed due to extract_options_from_args!. This method has been replaced with the nicer: args.extract_options! (i.e acts_as_paranoid, acts_as_mappable, paginating_find)

  • acts_as_paranoid had minor issues: fix by replacing construct_count_with_legacy_args to construct_count_options_from_args

  • ActiveResource is now part of rails core. Be sure to freeze edge twice if you are upgrading from 1.2.3 or lower. All of our libXML additions had to be redone. (this time through /patches, tnx fngtps)

  • Different behavior of the render method. Before you could call render "addresses/show" if you wanted to, this has been changed to render :template => "addresses/show". This affects several plugins too (like rspec_on_rails)

  • We no longer need the mysql_tasks plugin, since this functionality is now build right in!

  • redhillonrails_core has some issues with connection adapters. Apparently rails 2.0 no longer loads adapters it doesn't need. This creates some issues with the redhills plugin since it tries to include stuff in those adapters. Adding a begin/rescue block around each include solves the issue.

  • The development environment no longer needs the config.breakpoint_server = true setting.

  • Polymorphic models are now saved with the base class as type in external objects.

  • Autocomplete textfields are now a plugin: ./script/plugin install auto_complete

  • If you have overridden the to_json methods, be sure to change that to to_json options={}, else they might fail.

  • Migrations no longer working? Try removing duplicate names. We have two migrations with the same name (but different id) and it just skipped the first one (!)

Benefits so far:

  • Speed! We did expect some speed increase, but this is major! Our pdf generating stuff uses a lot of ActiveRecord and we saw decreases of more than 50% request time.

Posted in ,  | Tags , , , ,  | 2 comments