After searching for a while in the RoR Documentation I wasn't able to find the inverse functionality of
to_xml. So now, it seems, I have an opportunity to contribute back to the Rails community with an a functional improvement of my own. I announce to you the
build_from_xml method to ActiveRecord.
Just place the below code in your
require "rexml/document" module ActiveRecord class Base def self.build_from_xml(xml) xml = REXML::Document.new(xml) if xml.class == String ar = self.new xml.elements.elements.each do | ele | sym = ele.name.underscore.to_sym # An association if ele.has_elements? klass = self.reflect_on_association(sym).klass ar.__send__(sym) << klass.build_from_xml(ele) # An attribute else ar[sym] = ele.text end end return ar end end end
You can call this from the main class of any ActiveRecord object. Here is an example.
This ruby code:
firm_xml = File.new("firm_data.xml").read firm = Firm.build_from_xml(firm_xml)
Will convert this XML file into a fully functional ActiveRecord object, including the associations.
<firm> <rating type="integer">1</rating> <name>37signals</name> <clients> <client> <rating type="integer">1</rating> <name>Summit</name> <id type="integer">1</id> <firm-id type="integer">1</firm-id> </client> <client> <rating type="integer">1</rating> <name>Microsoft</name> <id type="integer">2</id> <firm-id type="integer">1</firm-id> </client> </clients> <accounts> <account> <id type="integer">1</id> <firm-id type="integer">1</firm-id> <credit-limit type="integer">50</credit-limit> </account> </accounts> <id type="integer">1</id> </firm>
You may have noticed one caveat. This function accepts well formed XML code only that conforms to your model. If it doesn't, it may produce unpredictable results but will probably raise the usual ActiveRecord exceptions in most non-trivial error cases. Oh, and it requires REXML, but you knew that already right.
I will probably convert this to a plugin in the not-to-distant future. That is if the code isn't included in Rails' release branch (hint, hint).