Monday, June 8, 2009

jQuery: Edit In-Place

I came across a need for in-place editing, but not the kind that automatically updates the server via ajax. I just needed to click a little link, have it turn into an input box, type and press enter, and have a callback run on that value.

So I created a jquery plugin to do just that. It's so short and sweet though, I can post it right here!

Thursday, March 26, 2009

QuickBooks HTTP Connector

I've just finished making an EXE for Windows, with a tray icon, that listens to a network port for normal HTTP requests containing QBXML, which it will then port to QuickBooks and relay the response. It's really handy for any integration you want to do with QuickBooks -- oftentimes you want to integrate QuickBooks with some other software that isn't on the same computer. That's not easy -- or I mean, it IS easy now! Besides not having to be on the same computer, you don't have to deal with the whole WinOLE stuff, or deal with the API connection or session. It ... Just Works™.

You may have your own QBXML skills up to par and want to just send raw QBXML data; or you might have some library that generates the xml for you. You might want to consider using the QuickBooks rubygem for that (get that here - it's well worth it!). The gem hides all of the complexities of ... 1) connecting, 2) managing a session, 3) network communication, 4) generating qbxml, 5) parsing qbxml. Oh, and 6) studying the QBXML specifications for hours and hours. The gem makes literally QuickBooks as easy to work with as ActiveRecord makes SQL.

(You see, it gives you nice validation messages too, instead of just saying "Sorry, you're doing it all wrong" like the QB SDK and their handy little validator pretty much does. The gem will actually tell you something like "You need at least one of [:Name, :Age, or :Relation]!". A lot more handier.)

Anyway, back to the HTTP Connector. It runs on port 56225 (the word LOCAL on a phone keypad). The quickbooks http adapter is rigged to that port by default, so it'll work on a local network without you needing to care about it. When using the gem, all you need to do is mention you're using the http adapter, and the IP to talk to:

Quickbooks.use_adapter :http, "192.168.1.105"
If you're doing some port-forwarding and need to specify a different port for the gem, just add a port number on to that as another argument.

The API is really simple: to send a QBXML request, simply send the following request:
POST /ProcessRequest
Content-Type: application/xml

<QBXML>...</QBXML>
To check the qbxml versions supported by the QuickBooks you're talking to, send:
GET /QBXMLVersionsForSession
Really simple. Use it with any language you want to write in -- it's just plain ol' HTTP.

I plan to add basic authentication to this, and a little magical scheme that can validate passwords on the client end (without storing them, of course). I imagine it could save the password the first time you connect with authentication for a specific application.

Oh, and last thing -- the HTTPS versions are on their way. Definitely a must if you're communicating to your QuickBooks from the big open Internet.

Where is this wonderful little program, you ask? It's for a small sale of $25 at http://www.behindlogic.com, right along with the rubygem.

Wednesday, March 25, 2009

Ruby FTPS Implicit SSL

Today I worked for 5 hours to make ruby talk to an FTP server with Implicit SSL. This is known as FTPS, not to be confused with SFTP, and it basically means normal FTP over an SSL connection instead of a raw TCP connection. There are also a few FTP commands to add to the sequence, but it's not that bad. The problem is, Ruby doesn't have built-in support for it, and all the ruby libraries I found do Explicit TLS/SSL, but not Implicit.

So I spent a few hours tweaking and testing, and reading the RFC for FTP and FTP over TLS, and tweaking and testing some more. Finally I got it working, and I just HAVE to share it with others. I've seen questions about ruby and implicit FTPS all over the place but no correct answers -- so here you go!

Available from github: http://gist.github.com/85632

Use this exactly as you would use Net::FTP, except use Net::FTPS::Implicit instead.

Saturday, February 28, 2009

QuickBooks Open: Progress and Future

For those of you who are interested in the QuickBooks Rubygem, I have some new treats for you.

Recent changes to the gem:


  1. Parses the spec from XSD instead of DTD. Validations are more specific & detailed, and produce more readable errors.

  2. Generates classes on-the-fly instead of autoloading from ruby files. Much faster. Huge speed improvement.

  3. Supports whichever version you need. As of this version, you can only effectively use one qbxml-version at a time. Unless you're an avid Ruby guru. ;)

  4. New TCP adapter! Allows you to connect to your desktop QuickBooks over the network - or across the Internet!


In the works:

  • Jabber adapter - connect from anywhere to anywhere using XMPP.

  • A website where you can send HTTP POST requests that get routed to your users' desktop QuickBooks in realtime. An excellent solution for building a web app that integrates with QuickBooks Desktop!


* The TCP adapter, Jabber adapter, and Website to come will all be using shared-key encryption for security.

To buy, or for more info, head over to http://behindlogic.com.

Friday, January 30, 2009

QuickBooks Rubygem: Meta-Meta-Ruby

I've finished the major work on the Quickbooks gem, and the best part is that it was quite a fun feat in meta-programming. In fact, it's meta-programming writing itself to file with some extra salt. I like to call it meta-meta-programming, although that term is rather difficult to define. To explain the process briefly, I first 1) made a ruby script and supporting library to read and parse the DTD, then 2) Created ruby classes with properties, using them more as a smart data structure, then 3) told each class and module to write itself to file. Since there are so many classes, they are all set to autoload.

There are two reasons I decided to go about it this way:

1) It's the easiest way. The Quickbooks XML specifications (QBXML) in DTD form reveal that there are a huge number of object types in Quickbooks, and many different property and value types. There are 1000+ object classes. I could make a way to work with them without classes, but every single object type has its own property list and validations. To record real knowledge of how the API works for each object class, I have to record the property list the way the DTD defines it, which then includes the property order and how to validate the object type. Also, since there are so many classes, I really didn't want to write them all out by hand and have the likelihood of mistakes either.

2) It's the most comprehensive way. Because the QuickBooks API's xml DTD specification clearly defines precisely the way the API works, if I can read that into ruby, then I've got myself the real thing. The "real thing" needs to understand how the API works, not just be capable of working with it. For an illustration, instead of learning a few words of a language, we need the gem to actually learn the constructs and full vocabulary of the language. Example: validations. You can't have a good QuickBooks gem without good working validations. Because this gem has all the information from the DTD's baked in in some form or another, the gem will tell you if anything's askew in your data, because it understands what properties must be present in any object when it's created and when it's updated, and even if you have conflicting properties defined.

But now how to make it work smoothly and intuitively for a ruby programmer. With all those complexities, I determined that the most accurate way to write out the 1000+ object classes was to parse the DTD and generate them, then write them to file.


1) Parse the DTD


This isn't too hard, but it isn't easy either. There are primarily two parts to parsing a DTD: reading entities and elements into objects, and parsing the Parsing Expression Grammer (PEG) from their definitions. In the end of parsing, a DTD object holds a whole bunch of elements and macros and types. The next step is to iterate over those and create ruby classes and modules out of each of them.

(What I'm talking about is a PEG, which looks something like this: "(CompanyFilePath , HostInfo , (ListEvent | TxnEvent) , LastRestoreTime? , LastCondenseTime? , DataEventRecoveryTime?)" According to that expression, the CompanyFilePath and HostInfo are required, as well as either ListEvent or TxnEvent, and the rest are optional. The first step was to create a parser for those, and some of them are pretty complicated!)

2) Generate Ruby classes and modules from the DTD content


I made four "containers" for the different types of classes: Elements, Macros, Properties, and Types. Inside of each of these plural-named modules resides all of each type: 127 Macros, 14 Types, 435 Properties, and 850 Element classes, each with their own unique name. There are 3 for most of the element classes, for example: SalesOrderAddRq, SalesOrderModRq, and SalesOrderDelRq; so there are really only around 270 different object models. Each Element class simply sets the PEG Expression for that class, which specifies the class's elements and properties, as well as their validations, all in one go. When the class is instantiated, that expression is parsed, each element or property class is in turn instantiated, and any Macros are included and expanded into the expression string. So again, this PEG expression functions as both a property list and a validation specification. Properties such as addresses have embedded properties which must also validate (an address element/property has sub-elements like street, state, postal code). Many of the object types have even more complex validations. ListItems require either a ListID OR a FullName. In many cases you must have one of several properties, but only one. In other cases there are two possible groups of attributes, and you may have zero or more of the attributes in only one of those groups. Furthermore, you might be allowed either [both attributes A and B] or [one or more of another set of attributes]. Talk about complicated validations!

3) Write those classes and modules to file


After all of the DTD is translated into real classes and modules, I proceed to write them all to files. I've made a couple helpers that take care of simple things like creating the directory structure, determining the filename for each class/module, and wrapping the insides in the correct module and class structure. Some specific modules or parent classes get some static behavior added, which I write in a separate file and which gets included when the class is written to file. With all these classes written to file, each class, in a sense, knew "what" it was, but none of them knew what they could do or how to behave themselves. So I wrote in behavior in their super classes. Elements inherit from the Element class, Properties from the Property class, and Types from the Type class. Each type of object has its own behavior. I had to deduce rules from the structuring of the elements in the DTD that dictate how to classify each xml element as an Element, Property, or Type. Once each of these had behavior defined, I had basically created a class structure that brought life to the DTD's definitions. This is basically what the "QuickBooks Foundation Class (QBFC) Library API" provides.

4) Add behavior that bridges how you use QuickBooks to how you use Ruby


Up to this point, to continue the illustration of language, we have only the constructs and vocabulary of the language. The gem is usable, and you don't have to think at all about the QBXML, but you still need to know how the QuickBooks API works. Fortunately for you, that is no longer the case. I've added a layer of behavior on top of all of those elements, object classes, etc that allows you to work with the data the way you think about the data, instead of having to think about communicating about the data with QuickBooks. No other QuickBooks rubygem does this for you.

End Result


At the end I have a library of ruby classes and modules that work together exactly as the DTD dictates, and seasoned with some extra behavior such as to serialize the objects to xml and to connect with Quickbooks and operate the API communication. You don't need to know anything more about QuickBooks than you can pick up by simply using QuickBooks. It's actually quite fun to operate QuickBooks from the irb ruby console! After all the work I've done coding in an understanding of the API, 3 months later it still feels like magic!

The QuickBooks rubygem


Now it's time for a shameless plug. I've spent many an hour creating this QuickBooks rubygem, and it's now available for a fee. I ASSURE you it'll save countless hours of your own time trying to figure out QuickBooks, not only because there is a lot to the API, but because there is a LOT to the API and it is hard to comprehend! And because this gem brings the workings of QuickBooks into the "ruby way" of doing things.

Some Example Code



# Changing the name of a Customer.
# QB is a synonym for QuickBooks::Models.
# FullName is a collection attribute -- you can include several values, so we must use an array.
tom = QB::Customer.first(:FullName => ["Bombardi, Thomas"])
tom[:FirstName] = "Tom"
tom[:FullName] = "Tom Bombardi"
tom.save

# Creating a new SalesOrder.
so = QB::SalesOrder.new(:TxnDate => Date.today, :RefNumber => '12345678901') # QB is a shortcut for Quickbooks::Models, which contains all the object classes
so[:CustomerRef] = {:FullName => "Tom Bombardi"}
so[:CustomerRef] = tom.to_ref # same as above
so[:BillAddress] = Quickbooks::Elements::BillAddress.new(:Addr1 => '999 Some Rd', :City => 'Other City', :State => 'TX', :PostalCode => '88888')
so[:BillAddress] = {:Addr1 => '999 Some Rd', :City => 'Other City', :State => 'TX', :PostalCode => '88888'} # same as above
so[:ShipAddress] = {:Addr1 => '999 Some Rd', :City => 'Other City', :State => 'TX', :PostalCode => '88888'}
so[:PONumber] = '99999-111-ABCDE-00000'
so.attributes = {:ShipDate => Date.today, :Memo => 'This is a test SalesOrder Add request.', :IsToBePrinted => true} # just a shortcut for setting each one individually
so.attributes = {:IsToBeEmailed => false, :CustomerSalesTaxCodeRef => {:ListID => '3987235'}}
# SalesOrderLine is a collection attribute. You can either use = to set an array of items, or just use << to append to an initially empty collection.
so[:SalesOrderLine] << {:ItemRef => {:ListID => '8887778'}, :Desc => 'Some odd item', :Quantity => 1, :Rate => '25.00', :Amount => '25.00'} # notice the embedded ItemRef object with its own properties.
so[:SalesOrderLine] << {:ItemRef => {:ListID => '8887779'}, :Desc => 'Some other odd item', :Quantity => 2, :Rate => '21.00', :Amount => '42.00'} # here we add a second line-item
so.save


To obtain this gem


http://www.behindlogic.com/, or email me: gems [at] behindlogic.com