Half-Penny For Your Thoughts

rounded down to the nearest cent



Categories


Recent Articles




Computing

QBFC and Ruby

I discovered how to use QBFC with Ruby. QBFC is part of the Quickbooks SDK and is a fairly basic wrapper around QBXML. To me, it’s not the simplest interface, but it’s a nice not to bother with the XML, as I’ve been doing. Whereas when using QBXML, you would call WIN32OLE.new(“QBXMLRP2.RequestProcessor”), use WIN32OLE.new(“QBFC6.QBSessionManager”) instead.

Here’s quick example:

require 'win32ole'

qb = WIN32OLE.new("QBFC6.QBSessionManager")

qb.OpenConnection2 "", "Ruby Test", 1 # 1 is ctLocalQBD
qb.BeginSession("", 2) # 2 is omDontCare

request_set = qb.CreateMsgSetRequest("US", 6, 0)
customer_query = request_set.AppendCustomerQueryRq

response = qb.DoRequests(request_set)
customer_set = response.ResponseList.GetAt(0)
first_customer = customer_set.Detail.GetAt(0)
puts first_customer.FullName.GetValue

qb.EndSession
qb.CloseConnection
qb = nil

Now, I like to wrap all that opening and closing connection stuff in a block, so here’s a version I like a bit better:

require 'win32ole'

OPEN_MODES = {
  :single => 0,
  :multi  => 1,
  :either => 2
}

def session(app_name, options = {})
  com_obj = WIN32OLE.new("QBFC6.QBSessionManager")
  com_obj.OpenConnection2(options[:app_id].to_s, app_name, 1) # 1 is ctLocalQBD

      open_mode = OPEN_MODES[options[:open_mode].to_s] || 2 # :either is default
  com_obj.BeginSession(options[:filename].to_s, open_mode)

  begin
    yield(com_obj)
  ensure
    com_obj.EndSession
    com_obj.CloseConnection
    com_obj = nil
  end
end

session("Test Application") do | qb |
  request_set = qb.CreateMsgSetRequest("US", 6, 0)
  customer_query = request_set.AppendCustomerQueryRq

  response = qb.DoRequests(request_set)
  customer_set = response.ResponseList.GetAt(0)
  first_customer = customer_set.Detail.GetAt(0)
  puts first_customer.FullName.GetValue
end

And, finally, a bit of playing with WIN32OLE (risky, most likely):

require 'win32ole'

unless Object.const_defined?(:ActiveSupport)
  gem 'activesupport'
  require 'active_support'
end

class WIN32OLE

  alias_method :old_array_selector, :[]

  def [](idx)
    if idx.kind_of? Integer
      self.GetAt(idx)
    else
      old_array_selector(idx)
    end
  end

  alias_method :old_method_missing, :method_missing

  def method_missing(symbol, *params)
    if (('a'..'z') === symbol.to_s[0].chr)
      obj = old_method_missing(symbol.to_s.camelize.to_sym, *params)

      if obj.ole_methods.detect{|m| m.to_s == 'GetValue'}
        obj.GetValue
      end
    else
      old_method_missing(symbol, *params)
    end
  end
end

The new definition of [] checks if an integer was passed. If so, and if self responds to “GetAt”, go ahead and send the integer value to self#GetAt . This allows me to use response.ResponseList[0] instead response.ResponseList.GetAt(0).

The method_missing stuff allows does a similar shortcut for GetValue . Instead of first_customer.FullName.GetValue, I can call first_customer.full_name.

This is not at all tested, so I can’t say what these changes might mess up.


Computing

Building a Builder, Part 1

Rails has a lot of useful view helpers. If you’re writing your views in rhtml files, Rails can take care of a lot of the nitty-gritty html details, especially with forms. But, if you’re like me, you find yourself writing the same bloody tags over and over, especially for administrative views. It would (I think) be silly for Rails to include much more in the way of helpers than it already has, lest it blossom into 15,000 different “my favorite view setup is”… So, I really like what Rails offers, especially because it’s so easy to extend.

I noticed that for a lot of sites, I was using basically the same layout over and over, including a basic setup for the views, especially for resource controllers that needed a standard group of views: index, show, edit and new. I use tables for displaying the data, because, hey, that’s what tables are for. Yes, they are. No, do not use 30 thousand floated divs to display a table of information. That’s just wrong.

</rant>

So, I decided to build some helpers to make my life easier. And, rather than do everything from scratch, I started by extending Rails’ FormBuilder. Over the next 4 weeks or so, I’m going to go through some of the steps I used, for your reading pleasure. Yay! So, without further ado: NodeBuilder.

Step 1 - Creating a Builder based on FormBuilder

The Rails API docs discuss this (as does the Agile Development with Rails and probably many other blogs, but here’s the gist:

lib/node_builder.rb

class NodeBuilder < ActionView::Helpers::FormBuilder
  def text_field
    super + "<br />That was a text field"
  end
end

lib/node_builder_helper.rb

def node_for(name, object, options, &proc)
  form_for(name, object, options.merge(:builder => NodeBuilder), &proc)
end

Yay! That was worthless. But that’s the basics. The rest is just having fun.

Step 2 - I don’t want no sticking <%= … %> ‘s

Since one of my goals is to write as little html as possible, I decided I’d rather just have NodeBuilder take one big pure-ruby block. That is, instead of:

<% form_for :person, @person, :url => { :action => "update" } do |f| %>
  First name: <%= f.text_field :first_name %>
  ...
<% end %>

I wanted:

<% node_for :person, @person, :url => { :action => "update" } do |f|
  f.text_field "First name", :first_name
  ...
end %>

This means two important things:

  1. NodeBuilder needs to produce all the needed html. Yes, I can throw occasional html in as a string, but I want to avoid that.
  2. My node_for helper needs to push a string containing the full text it produces back to the view.

I’m going to look at #1 in detail in my next entry. So, what this entry is really about, is how do we do #2? Actually, I’m not really sure, but I got it working. Here’s how:

def node_form(object_name, collection, &block)
  raise ArgumentError, "Missing block" unless block_given?
  collection = [collection] unless collection.kind_of?(Array)
  builder = NodeBuilder.new(collection, object_name, self, {:list_type => :col}, block)
  collection.each do |object|
    yield builder.row, object
  end
  concat(builder.to_s, block.binding)
end
  1. The first line is just a sanity check that there’s actually a block in the calling code. Otherwise, there’s not much point here.
  2. The second line is something particular to NodeBuilder: all my helpers expect an Array of model objects, whereas Rails’ FormBuilder expects a single object. I’ll eventually get back to that point, but the helper can accept a single object and create an Array consisting of just that single object.
  3. Now I create a NodeBuilder instance. The arguments to the NodeBuilder is again something I hold until a later entry.
  4. Iterate through the collection and yield the NodeBuilder instance (builder.row updates which row we’re on and returns the instance) and the current object in the collection to the block in rhtml. I could, without the collection, do something like
    yield builder
    .
  5. Now, the magic that lets me push a string containing the full text. Instead of the different methods in NodeBuilder returning text, they add information to instance variables. The NodeBuilder.to_s method uses the variables to create the full html. The last line of this method concats that html to the block.binding. And, no, I don’t know what exactly that means, but it does seem to work. And the last line is the key to making #2 happen.

More to come.


Computing

Whois Resources

Yay for whois! Isn’t it cool. No. Wouldn’t it be nice if whois queries returned YAML results? Yes. Actually, maybe I’ll do that… Anyway, that’s not the point.

I’m looking into writing a Ruby library for whois lookups. Yup, there’s two out there, neither of which really fit my “needs”. So, as is my want, I’m using a blog entry as a place to store some resources information, both for my future use and also in hopes that it may prove useful to someone else.

First, the two existing Ruby libraries:

  1. Michael Neumann’s whois module: This is what I’m currently using. It’s quite simple (in a good way), but currently only checks nine TLDs (most importantly to me, not including several I use, such as .us). That being said, I think adding others would be trivial, i.e. just defining the server to check. The bigger downside, to me, is that it doesn’t give “easy-to-use” methods. It returns more or less raw data in an array. What I’m considering is a more “abstracted” approach. That being said, if you’re looking for a Whois library in Ruby, this is an excellent start.
  2. Whois Ruby: This library looks promising, but, as far as I can tell, only gets whois information on IP addresses. Since I just want domain name whois details, this does not seem to be what I’m looking for. If you are looking for IP information, though, this is worth a look.

If I do work on this library, these will both be useful. My other question (beyond what currently exists) is where to find the whois servers for various TLDs, and (probably through trying them), how are the information and formats compare?

  • Wikipedia has what will probably be a useful list of TLDs
  • The IANA has a less-pretty list of the same. Valuably, after selecting a list, and then a TLD, you arrive at a page with details. At the bottom of that page is the whois server. Yay! So that will be a main resource.
  • The IANA’s IP Address Services page would probably be a good place to start looking for whois servers on IP address, or the aforementioned Whois Ruby library.

Computing

Webmail

So, I’m writing a webmail app. I know, everybody is writing a webmail app. My 90-some-odd-year-old grandfather is probably writing a webmail app. In COBOL. Even Google has a webmail app. At least I’m not writing a shopping cart. Shudder.

There is a Ruby on Rails webmail that’s pretty good, mailr. I use it. So why am I writing a webmail app? Because I’m an “S”. If you don’t know what that means, read Robert Kiyosaki’s Cash Flow Quadrant. Now, being an “S” is not where I want to be. I’m working on that. But, still, I’m writing a webmail app.

There is some good news here.

The impetus for my writing such software is a desire to have an email client that works, well, how I want it. Besides layout and particular functionality issues, I would like for my email to be stored in a database, on one of my servers, while still downloading and/or displaying email using IMAP or POP, or even, say, in Thunderbird or OE folders. Having grown accustomed to MVC design, thanks to Rails, I concluded, naturally, that the UI would be logically separate from the interaction with the various email libraries, database, etc. Regarding the abstraction of interacting with the various email storage options, I particularly am inspired by Johan Sørensen’s CSCM library.

All that is to say, here is the general approach I am planning (for the moment) on using: Creating two projects with different, but complementary purposes, being:

  1. A library that abstracts interacting with email storage mechanisms, including, but not limited to:

- Database storage, utilizing ActiveRecord - IMAP - POP3 - Thunderbird Email Folders - A YAML-based storage system, purely for testing - Also, would include abstraction of sending emails, including via SMTP and IMAP. - Additional adapters could be added via a mechanism such as GemPlugins

  1. A front-end that utilizes the library above. Actually, probably a couple of front-ends. One for my particular use, the other as a simple sample for using the library.

So, ultimately, my idea is to create a project that simplifies writing an email client in Ruby, by providing a library abstracting the interaction with mail servers and other storage mechanisms, and a simple starter application. My theory here is that a custom webmail application would be useful to many organizations, but only to the extent that it could be simply and easily setup.

The point, then, of this article is a) to clarify my own thoughts, and b) request comments from anyone who wanders by and has thoughts on this.


Computing

Simple Ruby DNS Server

Update 2009-09-10: If you’re interested in a DNS server written in Ruby, check out RubyDNS. Thanks to Samuel for his comment below announcing its release.

A few weeks ago, I started playing with Ruby’s Resolv library, which abstracts the DNS protocol. I’m playing with creating a DNS server in Ruby. It turns out to be pretty easy to get a very basic DNS server going in Ruby, And, for the curious, here it is.

require 'socket'
require 'resolv'

hosts = [
  {:name => "example.com", :type => "A", :data => "192.168.0.1"}
]

# Bind to UDP port 53 to receive requests
$port = 53
server = UDPSocket.open
server.bind(nil, $port)

while true
  # Receive and parse query
  data = server.recvfrom(10000)
  query = Resolv::DNS::Message::decode(data[0])

  # Setup answer
  answer = Resolv::DNS::Message::new(query.id)
  answer.qr = 1                 # 0 = Query, 1 = Response
  answer.opcode = query.opcode  # Type of Query; copy from query
  answer.aa = 1                 # Is this an authoritative response: 0 = No, 1 = Yes
  answer.rd = query.rd          # Is Recursion Desired, copied from query
  answer.ra = 0                 # Does name server support recursion: 0 = No, 1 = Yes
  answer.rcode = 0              # Response code: 0 = No errors

  query.each_question do |question, typeclass|    # There may be multiple questions per query
    name = question.to_s                          # The domain name looked for in the query.
    record_type = typeclass.name.split("::").last # For example "A", "MX"
    ttl = 16000
    record = hosts.find{|host| host[:name] == name &amp;&amp; host[:type] == record_type }
    unless record.nil?
      # Setup answer to this question
      answer.add_answer(name + ".",ttl,typeclass.new(record[:data]))
      answer.encode
    end
  end

  # Send the response
  server.send(answer.encode, 0, data[1][2], data[1][1])
end

To try this out, run the above script (may require sudo, since it binds to port 53; I haven’t figured out a way to test this at a different port) and then, in irb:

require 'resolv'
d = Resolv::DNS::new(:nameserver => "localhost")
puts d.getaddress("example.com")

This would only respond to A record requests for example.com, and the array of hashes is not particularly scalable. One could, for example, use ActiveRecord to access the records from a database, which is something I’m currently working on.