Easily turn a Ruby Hash to QuickBooks XML
I recently released a new Gem called to_qbxml. I created it in response to the current de facto Ruby Gem, Qbxml. Let me state right off the bat that I used much of that Gem's code for to_qbxml and want to thank the author, Alexsey, for all his OSS QuickBooks contributions.
Here are some of the issues I had with the Qbxml Gem:
- QBXML requires repeatable nodes such as the
InvoiceLineAddnode in the sample below but I had no idea how to do this with theQbxmlGem. - Reliance on ActiveSupport::Inflector to handle QBXML case conversions Since Inflector is used within Rails autoload this can adversely effect autoloading when included into an existing Rails app. Instead,
- Built-in validation is not needed. In my experience, it is best to use the OCR docs and the QBXML validator and SDKTest utilities that come bundled with the standard QBSDK installation.
- Turning QBXML into a Ruby hash is not useful when it comes to reading QBXML Instead use the rich parsing and searching of Nokogiri. With
<?xml version="1.0" encoding="utf-8"?>
<?qbxml version="7.0"?>
<QBXML>
<QBXMLMsgsRq onError="stopOnError">
<InvoiceAddRq requestID="1">
<InvoiceAdd>
<InvoiceLineAdd>
<!-- omitted -->
</InvoiceLineAdd>
<InvoiceLineAdd>
<!-- omitted -->
</InvoiceLineAdd>
</InvoiceAdd>
</InvoiceAddRq>
</QBXMLMsgsRq>
</QBXML>
I am sure that Qbxml Gem does support this as it is a crucial part of creating valid QBXML but instead I created a solution that uses a reserved hash key, repeat, that can be passed an array of hashes to create the above XML.
# ----
# to_qbxml gem example of creating repeatable nodes
# ----
def line_item(line_number)
{
invoice_line_add: {
item_ref: {
list_id: '3243'
},
desc: "Line #{line_number}",
amount: 10.99,
is_taxable: true,
quantity: 3,
rate_percent: 0,
repeat: [{
line: {
desc: 'inside'
}
}]
}
}
end
hash = { repeat: [ line_item(1), line_item(2) ] }
xml = ToQbxml.new(hash).make(:invoice)
to_qbxml removes that dependency and uses a simple regular expression to achieve the same result.
to_qbxml you can return a Nokogiri document back to by passing doc: true into the initialization options. Below is an example of using Nokogiri's rich CSS selector support to parse QBXML.
n = ToQbxml.new(hash, doc: true).make(:invoice, action: :query)
expect(n.at('InvoiceQueryRq > IncludeLineItems').content).to eq 'true'
expect(n.at('InvoiceQueryRq > ModifiedDateRangeFilter > FromModifiedDate').content).to eq hash[:modified_date_range_filter][:from_modified_date]
expect(n.at('InvoiceQueryRq > ModifiedDateRangeFilter > ToModifiedDate').content).to eq hash[:modified_date_range_filter][:to_modified_date]
end
Hence a new Gem is born
Therefore, I ripped out these and some other "features" to create a lightweight and flexible but yet powerful Ruby Hash to QBXML library. Enjoy, and check out the screencast for more commentary.
- Pushed on 10/07/2014 by Christian
- QuickBooks Integration Consulting
