Programatically Selecting a Restaurant?

Posted by jcnnghm Tue, 13 Jan 2009 00:28:00 GMT

I’ve been working quite a bit on the BarsAnnapolis.com site lately.  We’ve been getting ready to launch a new website, similiar to that site, featuring Annapolis-area restaurants.  I finally completed the actual site-work today, it’s all set and ready to go.  Instead of displaying bar speacials, the site will attempt to infer and display the optimal place and the optimal dish to have right now.

Of particular interest was the algorithm to accomplish this.  I ended up weighing a whole host of things, including current weather conditions, temperature, time of day, and season, to come up with reasonable weights for each venue.  The results are interesting, and seem to be pretty accurate so far.


Slow Runt 3

Posted by jcnnghm Tue, 03 Jun 2008 12:52:00 GMT

While unit testing some code that I’ve been working on that uses the excellent runt library, I ran into a bit of code that was quite slow. When calling the include? method of the Runt::DIMonth class with a negative value for the week of the month argument (i.e. DIMonth.new(-1,6).include?(date)) it took over 120 seconds to execute my unit tests.

I replaced the method max_day_of_month (Runt::TExprUtils), as listed below:

def max_day_of_month(date)
  result = 1
  next_month = nil
  if(date.mon==12)
    next_month = Date.new(date.year+1,1,1)
  else
    next_month = Date.new(date.year,date.mon+1,1)
  end
  date.step(next_month,1){ |d| result=d.day unless d.day < result }
  result
end

with the following code:

def max_day_of_month(date)
  month = date.month
  year = date.year
  if month == 2
    !year.nil? && (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)) ?  29 : 28
  elsif month <= 7
    month % 2 == 0 ? 30 : 31
  else
     month % 2 == 0 ? 31 : 30
  end
end

The same unit tests can now be performed in under two seconds. I didn’t write the algorithm, it’s taken verbatim from the Rails ActiveSupport::CoreExtensions::Time::Calculations::ClassMethods module daysinmonth method. That method appears to be the cause of the issue.

Can't Ping From/To Windows XP

Posted by jcnnghm Fri, 09 May 2008 11:41:00 GMT

I ran into a strange problem recently, I couldn’t ping from or to a Windows XP box on my network. After some unsuccessful experimentation, I thought that the problem may be caused by the NVidia chipset, so in the NVIDIA control panel, I disabled TCP/IP Acceleration, this fixed the problem immediately.

It appears that there is some kind of bug that severely affects ICMP packets in the NVIDIA TCP/IP Hardware Acceleration, so I would recommend disabling it. This isn’t the first I’ve heard of the NVidia network configuration settings causing all sorts of strange issues.

Testing Authorize.net with ActiveMerchant 6

Posted by jcnnghm Sun, 27 Apr 2008 18:55:00 GMT

I had some trouble testing Authorize.net with the excellent rails credit card processing gem ActiveMerchant. The documentation calls for the code ActiveMerchant::Billing::Base.mode = :test, however, this resulted in the following error: The merchant login ID or password is invalid or the account is inactive.

To solve the problem, a key test with the String value true can be added to the gateway initialization hash, as follows:

if ENV['RAILS_ENV'] != 'production'
  gateway = ActiveMerchant::Billing::Base.gateway(:authorize_net).new(
    :login => "login",
    :password => "transkey", :test => 'true')
else
  gateway = ActiveMerchant::Billing::Base.gateway(:authorize_net).new(
    :login => "login",
    :password => "transkey")
end

Using this code, the account is placed into test mode when not run in production mode.

Virtualization and Me

Posted by jcnnghm Sat, 26 Apr 2008 18:51:00 GMT

I’ve had all of our servers running beneath the Xen hypervisor for a little over two years now, and all in all, I’ve got to say I don’t think I’d ever consider going back to the old way. Xen makes it easy to add new VM’s, and moving servers between physical hardware nodes isn’t too difficult either. Being able to boot a virtual server from the SAN means that you can boot that server on any node that can get to the SAN. This has enormous benefits from a management perspective.

Of course, virtualization isn’t all rosy. The configuration process is much more complex, system failure is harder to detect and troubleshoot, and performance is slightly lower than it would be on actual hardware. In my mind, these are all reasonable trade-offs once you consider the vastly increased flexibility you’ll achieve with a virtualized operating environment.

With virtualization finally taking off, and the relative familiarity with it in the industry, perhaps it’s time to take another look at the world of thin clients.

Multi Bit Shift Launch

Posted by jcnnghm Mon, 25 Feb 2008 12:54:00 GMT

I was finally able to launch my new product, Multi Bit Shift, a Flex multiple file upload applet complete with a Rails plugin to ease the integration. I learned a lot from this project, since this is the first that I have made use of project management software, in particular FogBugz, which I would highly recommend.

In particular, I learned that I grossly underestimated the amount of time required to produce proper documentation, the MBS website, and the product screencasts. Proper documentation is really what separates real, professional products from amateur contributions, so it is absolutely vital to dedicate whatever time is necessary to make sure everything is both well and thoroughly documented.

The website, and to a lesser extent the screencasts were also quite time consuming. I had my company, Compucated Solutions produce the design and integrate it with software that I wrote to manage the site. I am very pleased with the design and presentation at this point, but I must admit that I did spend considerable time writing and formatting content, as well as coding up the necessary software bits. I look at this kind of as an investment though, because when I go to release software in the future I have a very flexible engine that I can now quickly roll products out on.

The screencasts were also quite time consuming. I ultimately settled on the TechSmith’s Camtasia Studio product, as recommended by Jeff Atwood to produce the video. I am quite pleased by the results although I would like to be able to set the background color of the video files, and perhaps tweak the appearance a bit. While the software was a little pricey at $299 considering there are lots of competitors and viable alternatives, I ultimately settled on this particular product because it does what it does so very well. If you need to produce screencasts, seriously consider Camtasia, it is worth the premium. If you don’t need to produce screencasts, I suggest that you reconsider because they are a really excellent way to quickly convey complex information.

Besides just creating the screencasts, I also decided to make use of Amazon’s Simple Storage Service to host them. While I probably have ample bandwidth to host the screencasts on my equipment, I ultimately came to the conclusion that the users would have a better user experience if they were hosted by someone else. I have to say that, at this point, I am extremely impressed by the Amazon S3 service. It’s fast, reliable, flexible, easy to use, and inexpensive. I’m currently using the Firefox S3Fox plugin to manage the storage space. It really doesn’t get much easier.

All said and done, I believe I spent just as much, or even more time, documenting and launching this software than I actually did on the design and coding. In the future, I believe I’ll have to give much more thought in the product planning stages to the actual launch requirements (like a website, screencasts, docs, etc…) and the time required for their production.

Posting Delay

Posted by jcnnghm Sun, 24 Feb 2008 01:38:00 GMT

Unfortunately, over the course of the past couple of weeks I’ve been quite sick with the flu. I am about caught up now, so I should be able to start writing again tomorrow.

Rails Boolean Field Helper

Posted by jcnnghm Thu, 07 Feb 2008 22:10:00 GMT

I wrote this some time ago and I thought it was worth reposting here, primarily so it would be easier for me to find. This details the handling of binary fields from front to back in Ruby on Rails.

Creation:

Active Record migrations are quite good at creating tables. The below migration will add table “table” to the db with a boolean field a_boolean when rake db:migrate is run.

class CreateTable < ActiveRecord::Migration
  def self.up
    create_table :table do |t|
      t.column :a_boolean, :boolean
    end
  end

  def self.down
      drop_table :table
  end
end

Boolean Form Field Select Helper:

The following line creates a select box with true and false represented by Yes and No. The currently selected value (while editing) is automatically selected.

<%= select('table', 'a_boolean', [["Yes",true],["No",false]]) %>

Validation:

This validation will confirm that the field is either true or false.

validates_each :a_boolean do |record, attr, value|
  record.errors.add attr, 'is invalid.' if value != true && value != false
end

Complexity and Troubleshooting

Posted by jcnnghm Wed, 06 Feb 2008 15:13:00 GMT

Over the past day or so, I’ve been working on the absolute worst kind of tech problem, intermittent. Basically, some time ago I deployed another web server, and recently my monitoring service started notifying me that about once an hour it would be inaccessible from the internet for a few minutes. The strange part was, I couldn’t detect any problem accessing the site locally, and most of the time it was accessible from outside the network.

I initially suspected that the culprit was my Mongrel installation, so I got to work troubleshooting that. I spent over an hour working on mongrel before I realized that Mongrel probably wasn’t the problem. Indeed it wasn’t, my first mistake was not attacking the problem at the beginning. This server is deployed behind a Linux bridging firewall, and is physically a Sun Microsystems box running Xen. This particular server is virtualized on that box along with several other systems, and runs an Apache load balancer for the mongrel cluster. In other words, there are many layers where something could go wrong. The correct approach would have been to verify network connectivity internally and externally during an outage period with a tool like ping. After I realized that Mongrel was running just fine, that’s what I did.

After I enabled ICMP packets to the host in the firewalls, I was able to determine that nothing was getting to that host intermittently. I inspected the routing table of the router, and was able to get packets to flow again whenever a disruption started. Obviously I couldn’t manually reset the routing whenever the connection was lost, so I set out to find the real problem.

After examining my xen configuration files, I started to look into the mac addresses that the bridge was seeing. I quickly discovered that my servers mac address wasn’t listed because after periods of inactivity it would effectively time out. Upon closer inspection of the servers network configuration files, I was finally able to determine that while the server had static public IP addresses and a gateway set, it was also pulling a private IP and a gateway from the DHCP server. This interface was acting as the primary interface, which was causing the communications errors. Once I disabled DHCP and configured a static private IP address, I no longer experienced issues.

When dealing with complex environments and intermittent problems like this, it is important to isolate the problem and address it from a bottom up manner. If I had started at the base of the problem and checked the network connectivity to begin with instead of assuming Mongrel was at fault, I would have saved quite a bit of time. Additionally, when dealing with intermittent problems it is important to track down the source and either fix it outright, or force it to fail totally so that the issue can actually be addressed. Once I realized the issue was a routing problem somewhere along the chain, and was able to make it fail predictably, isolating the cause of the issue was much easier, because I no longer had to second guess if my actions were only making the problem worse.

If you follow these two rules when dealing with complex and intermittent issues, you’ll save yourself a great deal of time and trouble and ultimately come up with an exact solution. In other words, handle bugs in complex environments as orderly as possible, otherwise your actions may exacerbate the situation.

state_select and Rails 2.0.2 1

Posted by jcnnghm Tue, 05 Feb 2008 09:23:00 GMT

Because of a change in the workings of Rails 2.0.2, the excellent state_select plugin doesn’t work properly. Fortunately, the fix is really easy. After line 35, enter the following code, value = value(object).

This should give you a new to_state_select_tag, like this:

def to_state_select_tag(country, options, html_options)
  html_options = html_options.stringify_keys
  add_default_name_and_id(html_options)
  value = value(object)
  selected_value = options.has_key?(:selected) ? options[:selected] : value
  content_tag("select", add_options(state_options_for_select(selected_value, country), options, value), html_options)
end

That change got the state_select plugin to work for me under Rails 2.

Update: This has been fixed in the latest version. If you are experiencing this issue, update to the latest version.