Sunday, January 01, 2012

Thinkering - A new meme for 2012

Thursday, December 22, 2011

Computing Power Like Water

Many SF stories are predicated on the idea that computing power is available like water. Simply make a request and a swarm (or cloud) of computers assemble as needed in order to answer your question. Web searches are great but they rely on pre-computed information and actually answer very limited questions and in very narrow ways. The Apache Whirr project allows the technically-savvy person to link tens of computers together for very little money. Each computer hour costs less than 5 cents. And when I say technically-savvy, the learning curve is quite gentle. A few keyboard commands gets them going without any need to understand the real complexity behind the scenes. This is an important step because people can focus on problem solving instead of plumbing. Imagine if every science project in the world could shave six months off their start-up time because they can get a computer network running inside of a day. No more need for expensive, hard-to-find computer network administrators. And if you've got the network topology wrong just tear it down and restart with just one day downtime and zero hardware replacement cost. If you thought that science was already moving too fast, you'll be shocked by the next ten years.

Friday, June 17, 2011

Detecting Unsorted Spring Beans

I like my Spring Beans definition files to be sorted. So I wrote the following code. Eventually I might turn it into a JUnit test for my continuous integration server.
package play;

import java.io.IOException;
import java.util.ListIterator;

import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

public class UnsortedSpringBeans {

 public static void checkSortOrder(final String filename) throws JDOMException, IOException {
        System.out.println(filename);
        System.out.println("-------------------------------------------------");                  
        String lastBean = null;
        SAXBuilder parser = new SAXBuilder();
        Document doc = parser.build(filename);
        Element root = doc.getRootElement();
        @SuppressWarnings("unchecked")
  ListIterator children = root.getChildren().listIterator();
        while (children.hasNext()) {
          Element child = children.next();
          Attribute id = child.getAttribute("id");
          if (id == null) {
              System.out.println("Skipping    : " + child.getName());                  
           continue;
          }
          if (lastBean != null) {
              int cmpValue = id.getValue().compareTo(lastBean);
              if (cmpValue < 0) {
                  System.out.println("Out Of Order: " + id.getValue());                  
              } else {
                  System.out.println("              " + id.getValue());                  
              }
          } else {
              System.out.println("              " + id.getValue());                  
          }
          lastBean = id.getValue();
        }
        System.out.println("");
    }
    
    /**
     * @param args
     * @throws IOException 
     * @throws JDOMException 
     */
    public static void main(String[] args) throws JDOMException, IOException {
        checkSortOrder("config/bean-definition.xml");
        checkSortOrder("config/database-beans.xml");
        checkSortOrder("config/hypersonicContext.xml");
        checkSortOrder("config/url-processor-beans.xml");
    }

}

Monday, May 23, 2011

Free-style Paper Roller-coaster at ReverseSpace.

Six kids had a great time.

Thursday, March 24, 2011

Human Logic Gates

Each data person gets candy Each logic person gets instruction. Then logic guys process the data guys. Good for Kids?

Monday, March 14, 2011

Monday, January 24, 2011

Running CEPH on 32bit Ubuntu kernal

DON'T DO IT! I spent several hours setting up three virtual servers - one master and two nodes - to run ceph. When it finally came time to run the cfuse command, I saw this message: WARNING: Ceph inode numbers are 64 bits wide, and FUSE on 32-but kernals does not cope well with that situation. Expect to crash shortly. Sigh.

Saturday, September 18, 2010

Active Relation Explained

Action Relation is an implementation of map-reduce. The predicate map the data. And the operations reduce it.

Thursday, September 16, 2010

Tracking RSPEC Test Execution So Debugging Statements Are Segmented

Throw the following into an initializer:

module Spec
  module Example
    module ExampleMethods
      def execute_with_print_logging(run_options, instance_variables)
        p "RSPEC TRACE: #{description} => #{@_proxy.location}"
        execute_without_print_logging(run_options, instance_variables)
      end
      alias_method_chain :execute, :print_logging
    end
 end
end

How Do I Expose the Current RSPEC File and Description

My goal with this monkey patch was to expose the rspec filename and description as global variables so that my exception handling code can know which rspec test caused the exception.

module Spec
  module Example
    module ExampleMethods
      alias :old_execute execute
      def execute(run_options, instance_variables)
        $rspec_location = @_proxy.location
        $rspec_description = description
        old_execute(run_options, instance_variables)
      end
    end
 end
end

Sunday, September 12, 2010

Compiling and Running Hadoop WordCount Example in NetBeans

In order to compile and run the Hadoop WordCount example in NetBeans, I followed these steps:

  1. Create a new Java project called hadoop.
  2. Copy the src/examples/org/apache/hadoop/WordCount.java to src/hadoop.
  3. Select Run>Set Project Configuration>Customize and change the Main class entry to hadoop.WordCount. Also set the arguments entry to 'input output".
  4. Add the following jar files as libraries: hadoop-0.20.2-core.jar, commons-cli-1.2.jar, commons-logging-1.0.4.jar, commons-httpclient-3.0.1.jar
  5. Add the following method to the WordCount class:
    static public boolean deleteDirectory(File path) {
            if (path.exists()) {
                File[] files = path.listFiles();
                for (int i = 0; i < files.length; i++) {
                    if (files[i].isDirectory()) {
                        deleteDirectory(files[i]);
                    } else {
                        files[i].delete();
                    }
                }
            }
            return (path.delete());
        }
  6. Add the following lines of code just before the "new Job" line:
      // delete the output directory.
       WordCount.deleteDirectory(new File(otherArgs[1]));
  7. Create the input directory.
  8. Copy a text file into the input directory.
  9. Press F6 to run the program.
  10. Read the files in the output directory.

Thursday, August 12, 2010

MonoDevelop Rocks!

MonoDevelop - I am doing pro-bono work for a local non-profit (Hope and a Home) that has a GoDaddy Windows-based account. I, of course, only have Ubuntu running at home. A short web search found MonoDevelop. Ten minutes later, I had written by first ASP application. Easy to install and easy to use - highly recommended!

Monday, July 26, 2010

Sunday, July 25, 2010

Suggestion for Community Service Hours - Curating a Community Calendar

http://elmcity.cloudapp.net/ - This is an interesting website which allows you to provide calendar events in several different formats. A great community project would be to aggregate school events in a locality.

Sunday, July 11, 2010

Using ImageMagick To Create Horizontally Repeating Background Image

  1. Find an image that you want to slice vertically, which I'll refer to as the base image. This slice is what will be repeated across the background of the web page.
  2. Use the identify home_page.jpg command to find out some details about the base image. The result of this command looks like this: home_page.jpg JPEG 1300x1380 1300x1380+0+0 8-bit DirectClass 736KiB 0.240u 0:00.240
  3. For our purposes, the first set of numbers is sufficient. They hold the width and height.
  4. The next step involves extracting a vertical slice (top to bottom) from the base image. Use this command: convert -extract 10x1380+0+0 home_page.jpg body_background.png. Notice that you can vary the width of the slice using the first number. In this case, I use 10 but some other number is probably more appropriate for you.
  5. If you want to test various widths, you can 'tail' the background image using display -update 1 body_background.png which redisplays the image every second.
  6. Once you've got the vertical slice, you need to integrate it with your web page.
  7. Use CSS similar to this:
    body {
      background-image: url('body_background.png');
      background-repeat: repeat-x;
    }

Thursday, July 01, 2010

Using module_eval to Define Instance Methods in a Ruby Gem to Enable Per-Model Configuration

In the last post, I mentioned that I wrote a small gem to post changes to ActiveRecord models to Twitter. In that version, the configuration was handled by a YAML file. I wanted to evolve the gem so that developers could switch Twitter accounts for each model.

Basically, I wanted to able to the use the following:

class Place < ActiveRecord::Base
  alastrina :twitter => { :username => 'alastrina_gem', :password => 'QQQQQQ' }
end

After a bit of tinkering and searching, I decided to use the following code in my gem.

ALASTRINA_CONFIGURATION_FILE = 'config/alastrina.yml'

module Alastrina
  def self.included(base)
    base.extend(ClassMethods)
  end
  
  module ClassMethods
    def alastrina hash
      module_eval do
        def configuration
          throw "Missing #{ALASTRINA_CONFIGURATION_FILE}" unless File.exists? ALASTRINA_CONFIGURATION_FILE 
          @config ||= YAML::load(File.read(ALASTRINA_CONFIGURATION_FILE))
        end
        if hash[:twitter]
          def send_to_twitter?
            true
          end
          eval"def twitter_username\n\"#{hash[:twitter][:username]}\"\nend\n"
          eval "def twitter_password\n\"#{hash[:twitter][:password]}\"\nend\n"
        else
          def send_to_twitter?
            @twitter_flag ||= !configuration['twitter'].blank?
          end
          def twitter_username
            @twitter_username ||= configuration['twitter']['username'] if send_to_twitter?
          end
          def twitter_password
            @twitter_password ||= configuration['twitter']['password'] if send_to_twitter?
          end
        end
      end
    end
  end

  def after_save
    if send_to_twitter?
      require 'twitter' 
      throw "Missing Twitter userid" if twitter_username.blank? 
      throw "Missing Twitter password" if twitter_password.blank?
      send_via_twitter
    end
  end

private

  def send_via_twitter
    if changes.size > 0
      httpauth = Twitter::HTTPAuth.new(twitter_username, twitter_password)
      client = Twitter::Base.new(httpauth)
      begin
        client.update(changes.to_yaml)
      rescue
        RAILS_DEFAULT_LOGGER.error "alastrina.send_via_twitter; Unable to send change. Message[#{$!}] Change[#{changes.to_yaml}]"
      end
    end
  end
  
end

ActiveRecord::Base.class_eval { include Alastrina }

The key insight to this code is how the hash passed on the alastrina of the Model is passed down into the instance. The code is fairly straightforward once you see what the eval is doing.

Monday, June 28, 2010

Alastrina - a gem to push model changes to twitter

http://github.com/medined/alastrina - the gem

http://github.com/medined/alastrina_demo - a demo application

http://twitter.com/Alastrina_gem - the result

I was doodling in code this weekend and the result is a small gem that hooks into the after_save callback to send model changes to a Twitter account.

Make sure you install the Twitter gem. Then in the demo app, update the config/alastrina.yml file with your Twitter credentials. Open a console and do:

a = Place.new
a.name = "GGG"
a.save

And, presto, the model changes should be posted to your Twitter feed.

Monday, June 21, 2010

Connecting acts_as_solr and cucumber (resolving the whiny_nil error)

When I installed cucumber into my application and ran 'cucumber' I got an error that said "undefined method 'symbolize_keys' for nil:nilclass". This message happened because acts_as_solr tried to load a 'cucumber' environment from config/solr.yml and was unable to find it.

Monday, March 22, 2010

Ubuntu and RocketFish RF-FLBTAD bluetooth dongle

I bought the RocketFish RF-FLBTAD bluetooth dongle today. When it was plugged into the front USB ports of my computer, the dongle would not be recognized as an HCI device. However, when I plugged it into one of the USB ports in the back of my computer, it registered just fine. Lots of good messages in /var/log/syslog. Update: The dongle disappeared when I rebooted. However, it came back when I manually ran: sudo /etc/init.d/bluetooth restart

Tuesday, February 09, 2010

Heroku Tip; Use a Ping or Uptime Service As a Cron Job.

This is a pass-along tip from Toby Hede (http://stackoverflow.com/users/14971/toby-hede) on StackOverflow. Just give the Ping service the URL of the controller doing the work instead of your root page.

Rails Tip - How Do I See Params From My Forms?

I like to document what my forms are sending to my action methods. So most of the time, I create a method in my controller like this:
def to_export
  render :text => params.inspect
end
Then I use copy and paste to put the result into my code as a comment.
# {
#   "commit"=>"Upload File", 
#   "authenticity_token"=>"17FvBH+Z4Meni6WvsCdPByrrk751BV9mNklzKDAo2Vc=", 
#   "action"=>"do_import", 
#   "import_criteria"=>{
#     "primary_language_name"=>"Creole", 
#     "secondary_language_name"=>"English"
#   }, 
#   "form"=>{
#     "file"=>"traveling_haiti.txt"
#   }, 
#   "controller"=>"import"
# }

Monday, February 08, 2010

Another Fix for EMAIL not authorized to access APP

I wanted to change the primary email associated with my Heroku account. So I removed the email from the authorization list. The next time I pulled from git, I got the following error:

heroku@david-medinets.otherinbox.com not authorized to access crisiscamp-translation
The email address is pulled from your public/private keys which can be recreated using the following command:
ssh-keygen -t rsa -C EMAIL

Sunday, February 07, 2010

Using Formtastic Without ActiveRecord

Let's start with a model:
class PrimaryLanguage
  attr_accessor :name
  def initialize(name)
    @name = name
  end
end
Then create an object in a controller:
class AbcController < ActionController::Base
  def aaa
    @primary_language = PrimaryLanguage.new('English')
  end
end
Design a form:
<% semantic_form_for @primary_language, :url => select_primary_language_path, :html => { :id => 'primary_language'} do |form| %>
  <%= form.input :name, :as => :select, :collection => @languages, :required => false, :label => "Primary Language:<br/>", :include_blank => false %>
<% end %>
And finally handle the user's input;
class XyzController < ActionController::Base
  def bbb
    primary_language_name = params[:primary_language][:name]
    # do something
  end
end

Saturday, January 09, 2010

When Coloring Hover Always Using Anchor CSS.

I just found out that you need to specify both a and a:hover in order to color text when the mouse hovers over a link. Using the a:hover does not work in isolation.

Monday, November 30, 2009

Plug A Security Hole in RubyGems By Mailing Ruby Install Dir ReadOnly!

When creating a Ruby gem, developers can specify a list of executable files. These executives are copied into the same directory where the Ruby binary is located. While very convenient, it opens a huge security hole.

It would be fairly easy for someone to provide an alternate version of the Ruby executable.

If possible, write-protect your ruby install directory to prevent this avenue of attack. If you run Windows and are paranoid, backup the Ruby install directory so you have something for future comparison.

Sunday, November 22, 2009

How to Resolve Heroku's 'not authorized to access newname' Git error.

When you see the 'not authorized to access newname' error, it probably. means that your Git configuration is incorrect. For example, my .git/config file had the following:
[core]
 repositoryformatversion = 0
 filemode = true
 bare = false
 logallrefupdates = true
[remote "heroku"]
 url = git@heroku.com:newname.git
 fetch = +refs/heads/*:refs/remotes/heroku/*
Notice the highlighted words. Just change newname to the actual project name and you should be fixed.

Saturday, November 21, 2009

Scripting the Heroku Push

This tip falls under the KISS principle. I recently started using the Heroku service to run some Rails websites. After making changes and committing them to your local Git repository, those changes are pushed to Heroku using the command git push heroku master. Since I'm likely to forget and since it's four words I created a file called script/push with that command. Here are the steps.

  1. Create a file called script/push with one line: git push heroku master.
  2. Run chmod +x script/push
  3. Run git add script/push.
  4. Run git commit -m "scripting the Heroku push".
  5. Run script/push.

That's it. Just script/push whenever you need to deploy.

Sunday, October 25, 2009

Most Efficient Food in Cafe World

2009-Nov-23 Updated with new foods. Changed net income to reflect the 15 coin charge for cleaning the stove.

2009-Oct-31 Updated with crab bisque, halibut and peking duck.

My kids like this game. I needed a way to make it more interesting. Here is the list of food they can make, in order of efficiency.
food                     cost   income  net  hours   minute secosnds  net/seconds
bacon cheeseburger         15   52      22              5       300        0.07
overstuffed peppers      1300 4300    2985    12              43200        0.07
kung pao stir fry         600 1600     985     4              14400        0.07
king crab bisque         1300 6685    5370    24              86400        0.06
chips and guacamole        10   36      11              3       180        0.06
super chunk fruit salad    35  100      50             15       900        0.06
atomic buffalo wings      350  960     595     3              10800        0.06
buttermilk pancakes       250  400     135             45      2700        0.05
tony's classic pizza      400 1300     885     5              18000        0.05
chicken gyro and fries     45   88      28             10       600        0.05                               
voodoo chicken salad      700 2675    1960    12              43200        0.05
herbed halibut            700 4500    3785    24              86400        0.04
crackling peking duck     900 3600    2685    18              64800        0.04
jumbo shrimp cocktail      65  148      68             30      1800        0.04
savory stuffed turkey     700 3600    2885    22              79200        0.04
tikka masala kabobs       215  360     130     1               3600        0.04
spagetti and meatballs    450 1375     910     8              28800        0.03
spitfire roasted chicken  600 3200    2585    24              86400        0.03
french onion soup         175  615     425     4              14400        0.03
triple berry cheesecake   400 1650    1235    12              43200        0.03
caramel apples             90  300     195     2               7200        0.03
homestyle pot roast      1800 5750    3935    48             172800        0.02
staked steak              300 2010    1695    24              86400        0.02
pumpkin pie               200 1060     845    12              43200        0.02

Friday, October 23, 2009

Forest Options of ps Command

Some computer system that I use have a ptree (or process tree) command. It is very nice to see processes and their children. In fact, I am disappointed when working on systems without ptree. And then I learned about the forrest option of the ps command.

ps faux

Wonderful. Makes me happy. RTFM!

Wednesday, October 21, 2009

United States' Official Repository of Foreign Place-names (more entity extraction fun)

https://www1.nga.mil/ProductsServices/GeographicNames/Pages/default.aspx - This is a fantastic resource if you need a list of place names. You can download a file containing names covering the whole world.

Friday, October 16, 2009

Names in Non-English Languages (continuing a theme)

The title is horrible but clear, at least to me. I only have one link so far, but it's a good one.
  • http://blog.jclark.com/2007/12/thai-personal-names.html - There's an election coming up in Thailand on December 23rd and the streets are lined with election posters. As a bit of an i18n geek, I find it interesting that the posters almost all make the candidates' first names at least twice as big as their last names. If you're also an i18n geek, your reaction might well be: "it must be because Thais write their family name first, followed by their given name". But you would be wrong. Thais have a given name and a family name; the given name is written first, and the family name last.

Monday, October 12, 2009

Entity Extraction Links (also Named entity recognition)

  • Websites
  • Software
    • Ruby
    • http://github.com/hypomodern/flex-attributes/ - Originally by Eric Anderson, some of that code still remains. If you’re not into this version, check his out at rubyforge.org/projects/flex-attributes/ See Hypomodern::FlexAttributes for usage information.
  • http://www.opencalais.com/ - Calais is a rapidly growing toolkit of capabilities that allow you to readily incorporate state-of-the-art semantic functionality within your blog, content management system, website or application.
  • http://www.aktors.org/technologies/annie/ - Open Source Information Extraction from The University of Sheffield; ANNIE is an open-source, robust Information Extraction (IE) system which relies on finite state algorithms. ANNIE consists of the following main language processing tools: tokeniser, sentence splitter, POS tagger, named entity recogniser.
  • http://www.searchenginecaffe.com/2007/03/java-open-source-text-mining-and.html - Jeff Dalton's List of Java Open Source NLP and Text Mining tools
  • http://gate.ac.uk/ - GATE as an architecture suggests that the elements of software systems that process natural language can usefully be broken down into various types of component, known as resources
  • http://www.casos.cs.cmu.edu/projects/automap/ - AutoMap is a text mining tool that enables the extraction of network data from texts. AutoMap can extract three types of information: content analytic (words and frequencies), semantic networks, and meta-networks.
  • http://www.sra.com/netowl/ - SRA developed NetOwl®, a suite of rich text mining tools, to discover and extract the knowledge found in free-form text documents and turn it into actionable information. NetOwl has been refined over more than a decade of research and development. Our team of researchers and engineers continue to expand NetOwl’s capabilities to keep pace with evolving information needs.
  • http://www.inxightfedsys.com/products/sdks/tf/default.asp - Out of the box, Inxight ThingFinder automatically identifies and extracts more than 35 key entities - such as people, dates, places, companies or other things - from any text data source, in multiple languages. This ability to automatically identify and classify relevant entities makes ThingFinder one of the most powerful text analysis and extraction tools on the market. Using Inxight ThingFinder, developers can maximize and extend the value of their applications by enabling end-users to quickly find the most important pieces of information within large volumes of documents.
  • http://incubator.apache.org/uima/ - UIMA enables applications to be decomposed into components, for example "language identification" => "language specific segmentation" => "sentence boundary detection" => "entity detection (person/place names etc.)". Each component implements interfaces defined by the framework and provides self-describing metadata via XML descriptor files. The framework manages these components and the data flow between them. Components are written in Java or C++; the data that flows between components is designed for efficient mapping between these languages.
Articles
  • http://en.wikipedia.org/wiki/Named_entity_recognition - Named entity recognition (NER) (also known as entity identification and entity extraction) is a subtask of information extraction that seeks to locate and classify atomic elements in text into predefined categories such as the names of persons, organizations, locations, expressions of times, quantities, monetary values, percentages, etc.
  • http://www.semanticuniverse.com/articles-entity-extraction-and-semantic-web.html - Entity Extraction is the process of automatically extracting document metadata from unstructured text documents. Extracting key entities such as person names, locations, dates, specialized terms and product terminology from free-form text can empower organizations to not only improve keyword search but also open the door to semantic search, faceted search and document repurposing. This article defines the field of entity extraction, shows some of the technical challenges involved, and shows how RDF can be used to store document annotations. It then shows how new tools such as Apache UIMA are poised to make entity extraction much more cost effective to an organization.
  • http://broadcast.oreilly.com/2009/02/how-entity-extraction-is-fueli.html - How Entity Extraction is Fueling the Semantic Web Fire; short commentary on Apache UIMA and a few other tools.

Thursday, April 02, 2009

Installing Ruby and RubyGems On Ubuntu 8.10

     # ruby
    cd ~/rn
    wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p0.tar.gz
    tar -xzvf ruby-1.9.1-p0.tar.gz
    cd ~/rn/ruby-1.9.1-p0
    ./configure
    make
    make test
    sudo make install
    # zlib
    cd ~/rn/ruby-1.9.1-p0/ext/zlib
    sudo apt-get install zlib1g-dev
    ruby extconf.rb --with-zlib-include=/usr/include --with-zlib-lib=/usr/lib
    make
    sudo make install
    # gem
    cd ~/rn
    wget http://rubyforge.org/frs/download.php/45905/rubygems-1.3.1.tgz
    tar -xzvf rubygems-1.3.1.tgz
    cd rubygems-1.3.1
    sudo ruby setup.rb
    # fix ruby executable
    cd ~/rn/ruby-1.9.1-p0
    sudo make install

Saturday, March 14, 2009

Using Rails Gem to Generate a New Project on Ubuntu

Using the rails installed by apt-get was a bit confusing because the rails project being generated was not the rails version that I expected. I had installed the rails gem v2.2.2 but the config/environment.rb file showed rails v2.1.

I fixed this issue by removing the default rails.

sudo apt-get remove rails

And then using an alias:

export GEMDIR=`gem environment gemdir`
export RAILS_VERSION=`gem list rails | grep "rails " | cut -b8- | awk '{sub(/\)/, "");print}'`
alias rails='ruby $GEMDIR/gems/rails-$RAILS_VERSION/bin/rails'

Now when I do

rails dool

The project uses the right version of rails!

Monday, January 05, 2009

The --include-activation and --aasm parameters of the Restful Authentication Rails Plugin are mutually exclusive

I was following the installation instructions for the Restful Authentication Rails plugin. So I executed:

script/generate authenticated user sessions --include-activation -—aasm --rspec

This resulted in:

premature end of regular expression: /\A

After digging into the source code, I found that the parse! method in /usr/lib/ruby/gems/1.8/gems/rails-2.2.2/lib/rails_generator/options.rb swallowed exceptions. Here is the original code.

def parse!(args, runtime_options = {})
  self.options = {}
  @option_parser = OptionParser.new do |opt|
    opt.banner = banner
    add_options!(opt)
    add_general_options!(opt)
    opt.parse!(args)
  end

  return args

  ensure
    self.options = full_options(runtime_options)
end

The OptionParser initialization may cause exceptions which are not properly handled. I don't know what should be down but added the following code immediately before the ensure line at least will show the exception.

    rescue => e
    puts("I caught a #{e.class.to_s} with message #{e.to_s}")

Now that the exception is displayed, I saw one of my underlying problems:

I caught a OptionParser::InvalidOption with message invalid option: --include-activation

So I learned that when the --aasm parameter is used, then the --include-activation must not be specified.

Sunday, January 04, 2009

Using the Visualize Models plugin

This is a good plugin. It works with GraphViz to generate diagrams of your object model. After installation, I ran into a problem that Visualize::Inflector was not found. This was easily resolved by using ActiveSupport::Inflector in visualize_models.rb.

The Myth of the Hero Programmer

Fortunately, I have met few self-appointed heroic programmers over the years. However, late last year I was saddened to met another. People on truly agile teams might never have met this dying breed of programmer so let me present the archetype by borrowing from the Highlights magazine:

Goofus: Writes complex hard-to-understand code to prove superiority.
Gallant: Writes clear easy-to-understand code to enhance team dynamics.
Goofus: Writes code with side-effects to show his mastery of arcana.
Gallant: Writes simple code that is easy to maintain and debug.
Goofus: Disdains and deletes comments.
Gallant: Describes code context to aid maintenance and provide road maps for new team members.
Goofus: Speaks in imperative words and derisive tones.
Gallant: Speaks with humility and guides people to solutions.

The Ruby community should guard against any tendency towards heroic programmers to avoid some of the complaints made against the Perl community. Too many 'perlers' loved complexity for its own sake which lead to unmaintainable code and a bad reputation for the language in general.

Let's focus on the agile concepts of teamwork, shared code ownership, and collaboration. They are much healthier for the community.

What Goofus/Gallant experiences have you had?

Thursday, January 01, 2009

Avoiding the undefined method `use_transactional_fixtures=' error.

After adding rspec to my project and generating a model with rspec_model, I tried to run the generated spec test:
$ spec -cfprofile spec/
.../toshi/spec/spec_helper.rb:12: undefined method `use_transactional_fixtures=' for # (NoMethodError)
 from /usr/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner.rb:184:in `configure'
 from /home/medined/Workspaces/toshi/spec/spec_helper.rb:8
 from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
 from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
 from /home/medined/Workspaces/toshi/spec/models/book_spec.rb:1
After a fruitless internet search, I tried using a rake task:
$ rake spec
.
Finished in 0.061996 seconds
1 example, 0 failures

Adding RSPEC to a Rails Project

$ rails toshi
$ script/generate rspec
Couldn't find 'rspec' generator
$ cd toshi/vendor/plugins
$ git clone git://github.com/dchelimsky/rspec.git
$ git clone git://github.com/dchelimsky/rspec-rails.git
$ cd ../../
$ script/generate rspec
      create  lib/tasks/rspec.rake
      create  script/autospec
      create  script/spec
      create  script/spec_server
      create  spec
      create  spec/rcov.opts
      create  spec/spec.opts
      create  spec/spec_helper.rb

Thursday, October 16, 2008

How is a Use Case Different From a User Story?

http://alistair.cockburn.us/Elephant+carpaccio - Alistair provides a way to think about Use Cases and User Stories. In essence, he says that Use Cases provide the overall shape of the application while User Stories provide the details.

Wednesday, October 08, 2008

How do I restore and change gedit key assignments?

Use the vi editor to modify the .gnome2/accelsgedit. Editing the file with gedit does not work; the changes are not saved. I had reassigned my ^s key away from File>Save. I order to get the key assignment back, I re-commented the following line:

(gtk_accel_path "<Actions>/GeditWindowActions/FileSave" "<Control>s")

Sunday, October 05, 2008

RCOV - Covering unit, integration, and functional testing in one analysis.

Add the following code into a file called lib/tasks/rcov.rake. Notice that I used the find to gather the relevant tests then the xargs to form them into a nice line which can be added to the rcov command.

namespace :test do

  desc 'Tracks test coverage with rcov'
  task :coverage => :environment do
    rm_f "coverage"
    rm_f "coverage.data"

    rcov = "rcov --sort coverage --rails --aggregate coverage.data --text-summary -Ilib -Itest -T -x gem/*,rcov*"

    files = `find . -name *_test.rb | xargs`

    rcov = "#{rcov} " + files
    puts rcov
    system rcov

    system("firefox coverage/index.html")
  end
  
end

The new rake command can be executed using rake test:coverage

Monday, September 29, 2008

Advanced Rails Recipes - Chapter Two - The missing copy method.

I am reading through the Advanced Rails Recipes book. In chapter two, it refers to an Event.copy method which is not shown in the book. Shown below is the missing method from app/models/event.rb.

class Event < ActiveRecord::Base

  def self.copy(other)
    self.new(other.attributes.merge(:name => "Copy of #{other.name}"))
  end

end

Sunday, July 20, 2008

JBoss Drools CLASSPATH Error; The Eclipse JDT Core jar is not in the classpath

JBoss Rules v4.0.7 is compatible with Eclipse v3.3 or higher. However there is a simple workaround. Run the following commands:

export ECLIPSE_PLUGINS=/home/medined/Desktop/eclipse-3.4/plugins
ln -s 
  $ECLIPSE_PLUGINS/org.eclipse.jdt.core_3.4.0.v_874.jar 
  $ECLIPSE_PLUGINS/org.drools.eclipse_4.0.7/lib

Sunday, July 13, 2008

Getting "Client.InvalidKeyPair.NotFound" Error With Selenium Grid

When running the cap grid:boot command, I received the following error:

Client.InvalidKeyPair.NotFound: The key pair '/home/medined/.ec2/affy.pem' does not exist
It turned out that the EC2_KEYPAIR_NAME system variable was set incorrectly. You can find the correct value using the ec2-describe-keypairs command. Here is an example of its use:

$ ec2-describe-keypairs
KEYPAIR affy c3:e7:5f:09:50:66:f5:2b:3d:2b:ac:1d:09:52:9d:34:29:85:1b:76

So the correct value for me is affy, not the filename.

Saturday, July 12, 2008

Using Capistrano to Bundle Amazon EC2 Images

I've found the following bit of Capistrano script to be useful when tinkering with EC2 images. I can make a change and then bundle the image with just one command: cap admin:bundle

The most difficult part of this script was finding out how to upload files to the remote instance using scp. The rest is fairly straightforward. I am only posting this script because I haven't seen this functionality posted anywhere else.

# capfile for Amazon EC2 Bundling. Normally, a yaml file would be
# hold configuration parameters. I am using environment 
# variables because they are also used by the EC2
# programs - why have the information in two places?

# This script assumes that you are only bundling one
# instance at a time.

# EC2 Instance Hostname to be bundled.
ec2_hostname = ENV['BUNDLE_EC2_HOSTNAME']

# S3 Bucket Name (where the bundle is uploaded)
s3_bucket_name = ENV['BUNDLE_S3_BUCKET_NAME']

# If you are using ElasticFox (and if not, why not?) that
# you created in the KeyPairs tab. Specify the full
# path to the file.
ssh_keypair_file = ENV['BUNDLE_SSH_PRIVATE_KEY_FILESPEC']

# Amazon Web Services Info
amazon_account_id    = ENV['AMAZON_ACCOUNT_ID']
amazon_access_key_id   = ENV['AMAZON_ACCESS_KEY_ID']
amazon_secret_access_key = ENV['AMAZON_SECRET_ACCESS_KEY']

# Amazon EC2 Info
cert_filespec     = ENV['EC2_CERT']
private_key_filespec   = ENV['EC2_PRIVATE_KEY']

# We are only dealing with one EC2 instance.
role :libs, "#{ec2_hostname}"

# I like working with ElasticFox which seems to only
# support using the root user.
set :user, "root"

ssh_options[:keys] = ssh_keypair_file

namespace :admin do

 task :bundle do

  # Copy the certificate and private key to the remote computer.
  upload("#{private_key_filespec}", "/mnt", :via => :scp) 
  upload("#{cert_filespec}", "/mnt", :via => :scp)

  # Extract just the filename from the filespec.
  private_key_filename_start = private_key_filespec.rindex('/') + 1
  private_key_filename_end = private_key_filespec.length
  private_key_filename = private_key_filespec[private_key_filename_start, private_key_filename_end]

  # Extract just the filename from the filespec.
  cert_filename_start = cert_filespec.rindex('/') + 1
  cert_filename_end = cert_filespec.length
  cert_filename = cert_filespec[cert_filename_start, cert_filename_end]

  # Remove any old image.
  run "rm --force /mnt/image /mnt/image.*"

  # Create the EC2 Bundle
  #run "ec2-bundle-vol -d /mnt -c /mnt/#{cert_filename} -k /mnt/#{private_key_filename} -u #{amazon_account_id} -r i386"

  # Upload the EC2 Bundle to S3
  run "ec2-upload-bundle -b #{s3_bucket_name} -m /mnt/image.manifest.xml -a #{amazon_access_key_id} -s #{amazon_secret_access_key}"

  exec "ec2-register #{s3_bucket_name}/image.manifest.xml"

 end

 task :update do
  run "apt-get update"
  run "apt-get upgrade -y"
 end

end
Zemanta Pixie

Thursday, July 10, 2008

Using SCP with Capistrano

It took me several hours to find out how to send a file to my remote computer via scp using Capistrano. It's actually quite easy. There is a method called upload which has a via option. Here is an example of its use:

upload("products.txt", "/home/medined", :via => :scp)

If you need to change the files name, you can also specify it in the second parameter. For example,

upload("products.txt", "/home/medined/products_new.txt", :via => :scp)
Zemanta Pixie

Wednesday, July 09, 2008

Capistrano, ElasticFox & EC2

What a nice combination of tools! I just installed Capistrano and created a capfile. From then on, I could run commands across all my virtual istances in one shot. This setup took just minutes. The only change that I made to my existing instances was to add a capistrano userid. My capfile looks like this:

role :files, 
  "capistrano@ec2-75-101-225-105.compute-1.amazonaws.com", 
  "capistrano@ec2-67-202-59-118.compute-1.amazonaws.com"

namespace :files do
  desc "Show free disk space"
  task :show_free_space, :roles => :files do
    run "df -h /"
  end
end

The best thing of all? No XML configuration!

Monday, July 07, 2008

ElasticFox: How to SSH to Amazon EC2 Image Without Entering a Password

1. Download and install the ElasticFox plugin.
2. Enter your credentials.
3. Enter your account information.
4. Select the KeyPairs tab.
5. Click Create a New Pair.
6. Save to a file; for example ~/.ec2/affy.pem.
7. Select the AMIs and Instances tab.
8. Click Launch Instance(s).
9. In the dialog box, select the keypair that you created in step 5.
10. When the AMI is running, you should be able to connect to it without a password prompt.

Sunday, July 06, 2008

Captain Kirk Teaches SCRUM and Agile Development

Episode One: Change the Playing Field

"The odds are against us and the situation is grim." - Star Trek: Generations

STARDATE 11234.2

Students, Starfleet has asked to me say a few words about SCRUM while I'm visiting your base. Fortunately, my meeting with the Ambassadors isn't until 0930 so I have just enough time to talk and then answer a few questions.

Some years ago, I was in a situation that by most accounts (especially Bones') would be considered bleak. Our software team was handed a Klingon application to calculate the expansion rate of exploding warheads. Our Quality Assurance staff was located in the beta quadrant. While my Klingon interpreter and product owner (Kveld of house K'mpok) was in the brig for attempting to kill Scottie. I needed to act, and fast! But what were my options?

Yes, I could have outsourced the work to the Romulons. But they are the enemy! Let's get serious. Other suggestions?

Ok, that's another approach. We could bring everyone together onto a single starbase to form a co-located team. That suggestion is a classic. And workable except for the inter-species issues. My product owner, the klingon in the brig, is also responsible for other projects. He can't be co-located for all of them, can he? Additionally, co-location means additional costs in the form of housing, food, time away from family. In this situation, co-location is not possible.

Hmm. Good idea. Use the holodeck as a virtual meeting room. I like that and that is the approach that we took. Along with some others as well.

Since the team is so dispersed the issue of time was quite important. The team agreed to a daily standup (a scrum, some like to say) but at what time? The meeting time changed every three months. Thus, no one location was impacted more than another - all were inconvenienced equally.

Scottie agreed to import a case of Ra'taj for Kveld and to refrain from further mentioning his mother's similarity to a Gagh.

The approach that I take to every situation is:

What is the operant set of relationships and rules? And how can they be changed to resolve the issue?
Once you know how the forces arrayed against you are deployed, you can find the levers needed to tip the scale in your direction.

Any questions?


Thank you.

Dup dor a'az Mubster (live long and prosper)