How I Learned to Love Monitor Arms

Posted by jcnnghm Sun, 07 Feb 2010 22:08:00 GMT

IMG_0183

My Desk

IMG_0197

Moved out of the way

IMG_0196

Pushed Away from the side

IMG_0198

The Arm Structure

IMG_0189

Sleek Appearance

IMG_0191

Beefy MX Arm

IMG_0173

All the stuff that's not on my desk anymore

screen

Windows Monitor Settings

I recently added a 30" LG Monitor to my 3-monitor setup. Originally, I had intended to replace my 24" Viewsonic widescreen, but when I started considering it seriously, I began to see the utility in having a forth monitor, instead of just a larger third.

I was initially unsure of how I would accomplish this, but I had seen a 3M Monitor Arm in Office Depot, so I thought I'd buy it and try it out. Unfortunately, the 3M arm didn't have the lift that I really wanted, so I returned that arm and started searching online for other options. I came across the Ergotron Single Desk Mount Arm and the Ergotron Dual LX Monitor Arm. My thought was that I'd be able to purchase a dual arm, and mount both monitors on the left side of my desk on the arms, one above the other.

Once the dual arm arrived, I was able to get it setup in about 30 minutes. I was somewhat surprised at the ease of the setup. I had to unmount the other monitors from their stands, attach the monitor arms, secure the base to my desk with the desk clamp, and route the wires through the arms. The hardest part was removing the stands from the existing arms, and that wasn't very difficult. I did have to adjust the tension of each arm because of the weight of the monitors. All in all, I was very impressed with the ease of the setup process.

After a day of using the arms, I was so impressed that I ordered a second set for the monitor on the right side of my desk, and the Mx Desk Mount LCD Arm for the center 30" panel. The setup of the 30" monitor was a little more difficult than the smaller panels, but that's largely a function of the size and weight of the display. The desk clamp for the MX arm is larger than the other, and seemed very secure to me. The MX Arm is very solidly constructed, and has no problems whatsoever keeping the large display in place. I wouldn't attempt to use it with a smaller display, it really is designed for heavy displays, and the smaller arms do a fine job.

The cable management system of the arms is very well designed, and actually seems to work. I upgraded all of my DVI cables and power cables during this process to either 10 or 15ft so that the monitors positions could be easily adjusted, so the cables are rather large and inflexible, yet the cable management system still worked fine.

While I originally wanted the arms only to allow the two displays to be elevated, as soon as I got them installed I realized that I had needed these arms for some time, I just didn't know I needed them. For starters, they make dusting my desk significantly easier, as the monitors can be easily repositioned out of the way. Additionally, the appearance of my desk is cleaner than it was before, with the arms really improving the visual aesthetics of my work area; it looks much cooler and more high-tech now, and that counts for something. The arms have also made it easier to reconfigure the display configuration for specific situations. I'll occasionally shift one of the monitors to landscape view, and the arms allow any of the monitors, even the 30" display, to be transitioned.

From a productivity standpoint, I've got 4,096,000 reasons to be happy with this upgrade. The 2560x1600 resolution of the large display allows me to display either 2 or 4 files, plus the filesystem tree, in my IDE simultaneously. This has greatly enhanced my coding productivity. WIth the other three display, two 1600x1200, and a 1680x1050 display, I have a total of 9.7 million pixels to work with. In the upper left I usually keep my email, iTunes, and my project management software open. On the right hand side I usually have a web browser open with the stuff I'm working on. In the lower left I usually have a bunch of SSH windows open, tailing files, running irb, cucumber and autospec. In the center I'll keep my IDE or anything I'm actively working on. This allows me to keep everything I'm currently working on open and on top, so that I can reference things without having to move or change any windows. In particular, it's nice having autospec always running on my project so I can glance over and see any regressions.

All in all, I'm extremely happy with the monitor arms. I estimate the upgrade cost about $600, and my only regret is that I didn't make the investment sooner.

Three Years of Liberty

Posted by jcnnghm Sun, 07 Feb 2010 04:21:00 GMT

Chair

Liberty Chair
Chair

Worn Out Seat
Chair

At My Desk

About three years ago I purchased a Liberty Chair by Humanscale. The chair hasn't held up as well as I would like. With the Vellum cover and the Gel seat, the seat cover has started to tear. This chair was very expensive, about $1,000, and I would not have expected the seat cover to deteriorate.

All in all, I still think it's a comfortable chair, and it's definitely allowed me to log lots of hours in relative comfort. If you're in the market for one of these chairs, you may want to get this chair with leather instead of vellum, since that will hold up better. It's probably also worth considering another brand.

I think the Aeron chairs are probably just as comfortable, and more durable.

Headless Selenium Screenshots with Cucumber

Posted by jcnnghm Wed, 30 Dec 2009 16:24:00 GMT

 I was finally able to get Selenium integrated with Webrat and Cucumber on my Linux development server.  I followed this excellent guide to setting up the selenium server to run headless.  This enables me to run my tests without actually seeing the Firefox window.  This does, unfortunately, make debugging a bit more difficult.

Because of that, I created a Cucumber step to save a screenshot of the webpage in the tmp/screenshots folder.  This includes the entire page, not just the viewable portion.  Not only does this simplify debugging, but it also makes it trivially difficult to capture a large number of screenshots from the testing framework to compile visual reports.  I believe that making sure everything looks right is as much a part of testing as making sure it actually works.

 

Then /^I save a screenshot with filename "([^\"]*)"$/ do |filename|
  selenium.capture_entire_page_screenshot(File.expand_path("tmp/screenshots/#{filename}.png"), "")
end

Set Restriction Info with Facebooker

Posted by jcnnghm Tue, 22 Sep 2009 15:03:00 GMT

I’ve been working on a Facebook App and I was trying find out exactly how to go about setting content restrictions with Facebooker. While the documentation for the Admin.setRestricitionInfo API call is pretty clear, the Facebooker documentation is less clear.  It looked to me at first glance that the Facebooker::Admin.set_restriction_info method would have to be called with every request.  This seemed terribly innefecient to me, so I tried some other methods out until I found something that worked. In config/initializers, I created a facebook_permissions.rb file, and inserted the following code:

Facebooker::Admin.new(Facebooker::Session.create).set_restriction_info(‘type’ => ‘alcohol’)

This code will run every time your server starts, updating your application restriction settings.  Run the following command from script/console to double-check that the restrictions are being set correctly:

Facebooker::Admin.new(Facebooker::Session.create).get_restriction_info(‘type’)

Select Random Rows Using Ruby On Rails

Posted by jcnnghm Fri, 07 Aug 2009 04:59:00 GMT

Today I was looking for a way to randomly select rows from a database using Rails. I implemented the following message, which will randomly select a specified number of random rows, or as many rows as are available if the requested number is greater than the available number.

def find_random(random_count, options = {})
  if random_count > count(options)
    find_every(options).sort_by{rand}
  else
    find_every(options.merge({:offset => rand(count(options) - random_count + 1), :limit => random_count})).sort_by{rand}
  end
end

The code first attempts to determine if there are enough records to randomize. After that, it randomly selects an offset and returns the specified number of rows at that offset, after randomly sorting them. The benefit that this has over the other methods, is that it should scale well with very large data sets. The downside is, of course, that the are sequential from the given offset. In my situation, this works fine. Depending on what the data is used for, this may not work well for you. If that is the case, the approach I would take is to randomly generate a number of offsets, and select individual records at each offset. This should perform reasonably quickly as long as only a random items are selected.

Rails Forum Plugins 2

Posted by jcnnghm Thu, 06 Aug 2009 04:09:00 GMT

 I’ve been looking into adding some forum functionality into my Baltimore and Annapolis bars website.  While I was researching different forum implementations to find out what kind of forum I’d like to have on the site, I came across a couple of rails plugins that will take care of all the heavy lifting.

First is Savage Beast, the second version of a plugin designed specifically to add forums to Rails sites.  While Savage Beast is functional, it doesn’t appear to be actively updated.  It was forked a few months ago to bring it in compliance with Rails 2.3.  Unfortunately, as of this writing, that hasn’t been completed yet.  Savage beast is definitely worth watching, but at this time I think it would take too much work to get it production ready.

On the other hand, we have Community Engine,  Community Engine uses the Engines plugin, now integrated into rails, to add all kinds of social networking features into your rails project.  In addition to forums, the plugin brings user profiles, blogs, photos, and a messaging system.  The plugin has a ton of github activity, forks, and followers, and is definitely under active development.  Even better, the plugin is already Rails 2.3 compliant.  The only apparent problem with Community Engine is how many features it really has.  I have a feeling it could be quite difficult to integrate the software into an already-developed website.

I intend to begin integrating it over the next few days, and I’ll keep this up to date with how it’s going.

Programatically Selecting a Restaurant?

Posted by jcnnghm Tue, 13 Jan 2009 05: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 16: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 days_in_month 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 15: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 3

Posted by jcnnghm Sun, 27 Apr 2008 22: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.