Articles

Doors Open Hamilton 2012

In Hamilton on May 1, 2012 by Matt Grande Tagged: , ,

Man, it’s been a long time since I’ve posted.  I’ve got other stuff that I could post, but I need to pretty it up for mass consumption yet.

Anyway, back to content.  I was surprised and dismayed that the Doors Open Hamilton website didn’t have a map of the featured sites on it.  So I created one. Check it out here.

Update: I’ve been mentioned on Raise The Hammer! Life Goal: Complete.

Advertisements

Articles

Thoughts on REST: Who gives a shit?

In .Net on August 9, 2010 by Matt Grande Tagged: , ,

I feel like I’ve come to a new understanding of REST.

I’ve long been an evangelical supporter of REST. I’ve felt that Controllers should have, at most, the Seven Actions (List, Show, Edit, Update, New, Create, Delete).

But no longer…

I’m currently working on a project that had a normal, everyday requirement. Purchase Orders can be edited, and they can also be closed. From the Pure-REST point-of-view, I have two options: A convoluted Update action that does two things or a creating a specific PurchaseOrderClose controller that does one highly-specific thing.

Instead, I opted to do something terrible and dangerous…

I added a Close method to my PurchaseOrder controller. I added a custom route (/PurchaseOrders/{id}/Close). The world didn’t explode, and the API is still easy to understand.

It’s a simple lesson, but one that’s often hard-learned: To every rule, there is always an exception. Always err on the side of cleaner code.

/// <summary>
/// This is it.  This is the one that will infect your soul, curve your spine,
/// and keep the country from winning the war. 
/// </summary>
public ActionResult Close(int id)
{
	var po = _poRepository.Close(id);
	return View(po);
}

Articles

Some Simple NUnit Code Snippets

In .Net on November 11, 2009 by Matt Grande Tagged: , , , ,

I decided to learn how to write code snippets and wrote a couple quick ones to help out my NUnit testing. You can grab them here.

What’s in these snippets?

Just a couple quick & easy Assert completers. Hopefully these will help you learn how to write your own (better) snippets.

  • ae – Assert.AreEqual(expected, actual);
  • ait – Assert.IsTrue(true);
  • aif – Assert.IsFalse(false);

How to install snippets

Copy and paste the XML from the link above and save it in a file with the extension .snippet. I’d recommend saving it in the default code snippets folder (C:\Users\lskywalker\Documents\Visual Studio 2008\Code Snippets\Visual C#\My Code Snippets). Then, in Visual Studio, go to Tools -> Code Snippets Manager…, and click Add. Navigate to the file you saved, and you’re done!

Neat! Where can I learn more?

Everything I learned, I learned from the MSDN articles about code snippets.

Good luck, and happy coding.

Articles

Pluralization Helper for C#

In .Net, Rails on October 28, 2009 by Matt Grande Tagged: , , ,

UPDATE – This code is now available on GitHub.  Click here for the repo.

I recently wanted a pluralization inflector in a C# project, one similar to the one in Ruby on Rails. Unable to find a satisfactory one, I whipped up my own. Here’s what I’ve got.

namespace MyNamespace
{
    public class Formatting
    {
        private static readonly IList<string> Unpluralizables = new List<string>
        { "equipment", "information", "rice", "money", "species", "series", "fish", "sheep", "deer" };
        private static readonly IDictionary<string, string> Pluralizations = new Dictionary<string, string>
        {
            // Start with the rarest cases, and move to the most common
            { "person", "people" },
            { "ox", "oxen" },
            { "child", "children" },
            { "foot", "feet" },
            { "tooth", "teeth" },
            { "goose", "geese" },
            // And now the more standard rules.
            { "(.*)fe?", "$1ves" },         // ie, wolf, wife
            { "(.*)man$", "$1men" },
            { "(.+[aeiou]y)$", "$1s" },
            { "(.+[^aeiou])y$", "$1ies" },
            { "(.+z)$", "$1zes" },
            { "([m|l])ouse$", "$1ice" },
            { "(.+)(e|i)x$", @"$1ices"},    // ie, Matrix, Index
            { "(octop|vir)us$", "$1i"},
            { "(.+(s|x|sh|ch))$", @"$1es"},
            { "(.+)", @"$1s" }
        };

        public static string Pluralize(int count, string singular)
        {
            if (count == 1)
                return singular;

            if (Unpluralizables.Contains(singular))
                return singular;

            var plural = "";

            foreach (var pluralization in Pluralizations)
            {
                if (Regex.IsMatch(singular, pluralization.Key))
                {
                    plural = Regex.Replace(singular, pluralization.Key, pluralization.Value);
                    break;
                }
            }

            return plural;
        }
    }
}

And of course, some NUnit tests.

namespace AutomatedTests
{
    [TestFixture]
    public class FormattingTests
    {
        [Test]
        public void StandardPluralizationTests()
        {
            var dictionary = new Dictionary<string, string>();
            dictionary.Add("sausage", "sausages");  // Most words - Just add an 's'
            dictionary.Add("status", "statuses");   // Words that end in 's' - Add 'es'
            dictionary.Add("ax", "axes");           // Words that end in 'x' - Add 'es'
            dictionary.Add("octopus", "octopi");    // Some Words that end in 'us' - Replace 'us' with 'i'
            dictionary.Add("virus", "viri");        // Some Words that end in 'us' - Replace 'us' with 'i'
            dictionary.Add("crush", "crushes");     // Words that end in 'sh' - Add 'es'
            dictionary.Add("crutch", "crutches");   // Words that end in 'ch' - Add 'es'
            dictionary.Add("matrix", "matrices");   // Words that end in 'ix' - Replace with 'ices'
            dictionary.Add("index", "indices");     // Words that end in 'ex' - Replace with 'ices'
            dictionary.Add("mouse", "mice");        // Some Words that end in 'ouse' - Replace with 'ice'
            dictionary.Add("quiz", "quizzes");      // Words that end in 'z' - Add 'zes'
            dictionary.Add("mailman", "mailmen");   // Words that end in 'man' - Replace with 'men'
            dictionary.Add("man", "men");           // Words that end in 'man' - Replace with 'men'
            dictionary.Add("wolf", "wolves");       // Words that end in 'f' - Replace with 'ves'
            dictionary.Add("wife", "wives");        // Words that end in 'fe' - Replace with 'ves'
            dictionary.Add("day", "days");          // Words that end in '[vowel]y' - Replace with 'ys'
            dictionary.Add("sky", "skies");         // Words that end in '[consonant]y' - Replace with 'ies'

            foreach (var singular in dictionary.Keys)
            {
                var plural = dictionary[singular];

                Assert.AreEqual(plural, Formatting.Pluralize(2, singular));
                Assert.AreEqual(singular, Formatting.Pluralize(1, singular));
            }
        }

        [Test]
        public void IrregularPluralizationTests()
        {
            var dictionary = new Dictionary<string, string>();
            dictionary.Add("person", "people");
            dictionary.Add("child", "children");
            dictionary.Add("ox", "oxen");

            foreach (var singular in dictionary.Keys)
            {
                var plural = dictionary[singular];

                Assert.AreEqual(plural, Formatting.Pluralize(2, singular));
                Assert.AreEqual(singular, Formatting.Pluralize(1, singular));
            }
        }

        [Test]
        public void NonPluralizingPluralizationTests()
        {
            var nonPluralizingWords = new List<string> { "equipment", "information", "rice", "money", "species", "series", "fish", "sheep", "deer" };

            foreach (var word in nonPluralizingWords)
            {
                Assert.AreEqual(word, Formatting.Pluralize(2, word));
                Assert.AreEqual(word, Formatting.Pluralize(1, word));
            }
        }
    }
}

And finally, usage.

var output = Formatting.Pluralization(2, "item");
// Produces "items"
output = Formatting.Pluralization(5, "sheep");
// Produces "sheep"
output = Formatting.Pluralization(100, "sausage");
// Produces "sausages"
output = Formatting.Pluralization(1, "sausage");
// Produces "sausage"

Now, I’m sure that I’m missing some cases in there. For example, I haven’t found a good way to pluralize “proof.” If any of you wonderful people find another missing case, or if you want to add one, let me know in the comments.

Articles

Google Maps Street View in Hamilton!

In Uncategorized on October 8, 2009 by Matt Grande

A couple days back, Google Maps Street View was finally added to Hamilton. Here’s some of my favourite images:

Actually, that’s all the neat stuff I’ve seen around Hamilton so far… Not that much, come to think of it.

In other news, I start a new job in just over a week. Things will be hectic for the next while, so I won’t be posting as much. And I don’t really post all that much to begin with so… Things will be really bad.

Articles

Love vs. Hate

In lovestuffhatestuff.info, Rails on October 1, 2009 by Matt Grande

So, I created a website. Maybe you’d like to visit it? It’s just a quick little thing. You can see it here: lovestuffhatestuff.info

Articles

Delaying File Processing & Uploading with DelayedJob and PaperClip

In delayedjob, paperclip, Rails, Ruby, s3 on August 11, 2009 by Matt Grande

I’m going to say it right now. I love DelayedJob. I’ve been working on a project that involves uploading assets, mostly images, to S3 and resizing the images to three sizes. With the addition of DelayedJob, this can happen much faster.

Before I go on, I should mention that I wouldn’t have been able to delay paperclip without this post, and I wouldn’t have been able to delay S3 uploads without this post. Thanks go out to both bloggers!

The original DelayedJob was done by tobi. I’ll be using the version created by collectiveidea, which has a few extra nice features.

So the first step is to install it. I had to install both the plugin and the gem. The plugin was unable to generate the database migration, and the gem was unable to run the rake task. Hopefully, it was either a mistake on my part, or they’ll fix it soon.

script/plugin install git://github.com/collectiveidea/delayed_job.git
sudo gem install collectiveidea-delayed_job

Collectiveidea’s delayed_job has a nice generation script which will make your delayed_jobs table for you.

script/generate delayed_job
rake db:migrate

You’ll also want to add a processing column to your asset table.

class AddProcessingToAsset < ActiveRecord::Migration
  def self.up
    add_column :assets, :processing, :boolean, :default => true
  end

  def self.down
    remove_column :assets, :processing
  end
end

Your next step is to move into the code. To prevent the S3 upload, we subclass our Asset model with TempAsset, and just save locally.

class TempAsset < Asset
  has_attached_file :media, :path => ":rails_root/tmp/uploads/:id/:basename.:extension"
end

In your controller, save your TempAsset instead of Asset, and call a method that will queue up the processing.

class AssetsController < ApplicationController
  def create
    @asset = TempAsset.new(params&#91;:asset&#93;)
    @asset.save
    @asset.queue_move_to_s3
    redirect_to @asset
  end
end
&#91;/sourcecode&#93;

From there, we want to make our <code>queue_move_to_s3</code> method.  I'm using <code>send_later</code> in this example, but <code>enqueue</code> works just as well.  While we're at it, we'll write the method that will perform the saving.


# In temp_asset.rb
def queue_move_to_s3
  self.send_later(:perform)
end

def perform
  asset = Asset.find(self.id) # This is the same db record as self
  asset.media = self.media.to_file
  asset.processing = false
  asset.save!  # This will re-upload & re-size your image as per your has_attached_file method in Asset

  path = self.media.path
  self.media.to_file.close
  File.delete(path)
end

One last thing you may want to do is have a “We’re Still Processing This File” image. Thanks to the processing column we added earlier, it’s a piece of cake.

# In asset.rb
def url(style=:thumb)
  if processing
    still_processing_image_path
  else
    self.media.url(style)
  end
end

There are unfortunately a few hoops to jump through to get this working, but in the end you have a much faster response time which leads to a much better user experience. Hope this helps!