Friday, October 28, 2016

Chicken and Sausage Gumbo Recipe

Today I take a break from my usual tech blog posts to post a recipe. However, this is still tech-related as I am exploring the recipe schema to post this. If my code works, then the recipe should be formatted better for Pinterest, search engines, and recipe applications.

Chicken and Sausage Gumbo

Ingredients

  • 1/2 Cup Cooking Oil
  • 1/2 Cup Flour
  • 1 White Onion
  • 1 Bell Pepper
  • 4 Stalks Celery
  • 2 32-oz Cartons of Chicken Stock
  • Tony Chachere's Creole Seasoning (To taste)
  • 2 Bay Leaves
  • 1 Package Chicken Breasts
  • 1 Package Andouille Sausage*
  • Cooked Rice

Cook Time

Instructions

  1. Cut up chicken breasts into chunks and place into a bowl. Season with creole season, cover bowl, and put in refrigerator.
  2. Chop onion, bell pepper, and celery. Set aside.
  3. In a heavy 4-quart pot or Dutch oven, warm cooking oil over medium to medium-low heat.
  4. Add flour to oil and stir continuously until roux becomes a dark brown color. Do not burn. If black flecks appears, you will need to start over. It will take approximately 30 minutes to get a nice brown color.
  5. Add vegetables and cook in roux until onions begin to wilt.
  6. While stirring the mixture, slowy pour in chicken stock. Bring to a boil and then reduce to a simmer.
  7. Stir in seasoning and bay leaves. Adjust to taste.
  8. Carefully add meat to gumbo.
  9. Cut up sausage and add to gumbo
  10. Simmer gumbo for 1-2 hours or until chicken is tender
  11. Serve over cooked rice. Goes well with French bread and deviled eggs

* I prefer a real smoky sausage from a local smokehouse for the rich flavor but I usually do not have time to get that. So I like to buy Holmes Andouille sausage at the grocery store because it has a nice flavor and it is not greasy at all.

Thursday, October 6, 2016

Format JSON String in ColdFusion

I am sure this has probably already been done but I couldn't find it quickly with a Google search. So I wrote my own. This function takes a JSON string and indents it to make it more readable.
<cffunction name="indentJSON" hint="Indents JSON to make it more readable">
    <cfargument name="JSONString" default="" hint="JSON string to be formatted">
    <cfargument name="indentCharacters" default="#Chr(9)#" hint="Character(s) to use for indention">

    <cfset local.inQuotes = false>
    <cfset local.indent = 0>
    <cfset local.returnString = "">
    <cfset local.stringLength = Len(arguments.JSONString)>
    <cfloop index="i" from="1" to="#local.stringLength#">
        <cfset local.currChar = Mid(arguments.JSONString, i, 1)>
        <cfif i lt local.stringLength - 1>
            <cfset local.nextChar = Mid(arguments.JSONString, i + 1, 1)>
        <cfelse>
            <cfset local.nextChar = "">
        </cfif>
        <cfif local.currChar eq '"'>
            <cfset local.inQuotes = !local.inQuotes>
        </cfif>
        <cfif local.inQuotes>
            <cfset local.returnString = local.returnString & local.currChar>
        <cfelse>
            <cfswitch expression="#local.currChar#">
                <cfcase value="{">
                    <cfset local.indent = local.indent + 1>
                    <cfset local.returnString = local.returnString & "{" & Chr(10) & RepeatString(arguments.indentCharacters, local.indent)>
                </cfcase>
                <cfcase value="}">
                    <cfset local.indent = local.indent - 1>
                    <cfset local.returnString = local.returnString & Chr(10) & RepeatString(arguments.indentCharacters, local.indent) & "}">
                    <cfif local.nextChar neq ",">
                        <cfset local.returnString = local.returnString & Chr(10)>
                    </cfif>
                </cfcase>
                <cfcase value="," delimiters="Chr(0)">
                    <cfset local.returnString = local.returnString & "," & Chr(10) & RepeatString(arguments.indentCharacters, local.indent)>
                </cfcase>
                <cfcase value=":">
                    <cfif local.nextChar neq " ">
                        <cfset local.returnString = local.returnString & ": ">
                    </cfif>
                </cfcase>
                <cfdefaultcase>
                    <cfset local.returnString = local.returnString & local.currChar>
                </cfdefaultcase>
            </cfswitch>
        </cfif>
    </cfloop>

    <cfreturn trim(local.returnString)>
</cffunction>
And here's an example:
<cfset variables.testObject = {}>
<cfset variables.testObject.name.first = "Chad">
<cfset variables.testObject.name.last = "Armond">
<cfset variables.testObject.title = "Software Developer">

<cfset variables.testString = SerializeJSON(variables.testObject)>

<cfoutput>
    <h1>With Tabs (Default)</h1>
    <cfset variables.json1 = indentJSON(variables.testString)>
    <pre>#variables.json1#</pre>

    <h1>With Spaces</h1>
    <cfset variables.json2 = indentJSON(variables.testString, "    ")>
    <pre>#variables.json2#</pre>
</cfoutput>
And the results:

With Tabs (Default)

{
 "NAME": {
  "LAST": "Armond",
  "FIRST": "Chad"
 },
 "TITLE": "Software Developer"
}

With Spaces

{
    "NAME": {
        "LAST": "Armond",
        "FIRST": "Chad"
    },
    "TITLE": "Software Developer"
}

Wednesday, October 5, 2016

Converting Perl Arguments from Named Arguments to Positional Arguments While Maintaining Legacy Code

I think that's the longest blog title I've ever written. In case it's not clear, here is what is happening.

I used to use only positional arguments in all of my Perl functions simply because I didn't know any better. There are problems with that approach as this article points out. With any new development, I am solely using named arguments but what about legacy code? I wondered if I could change a method to accept named arguments but still use the same positional arguments so that I wouldn't have to update my legacy code base. Here's what I came up with:
if (ref(@_[0]) eq "HASH") {
    my %args = %{@_[0]};
    foreach my $arg (keys %args) {
        eval("\$$arg = \$args{\$arg}");
    }
}
What this code snippet does is look at the first argument in the list to determine its type. If it's a HASH, then we know the arguments are being passed as named arguments. So we convert them using the eval function to look just like the old positional arguments.

So let's say we have this legacy Perl function:
sub test {
    my ($arg1, $arg2, $arg3) = @_;
    
    print "\$arg1 = $arg1\n";
    print "\$arg2 = $arg2\n";
    print "\$arg3 = $arg3\n";
}
To convert it, we just add the new code snippet in. Here's a test script to see it in action.
#!/usr/bin/perl

use strict;

&test("abc", "123", "xyz");

&test({
    arg1 => 'abc',
    arg2 => '123',
    arg3 => 'xyz'
});

sub test {
    my ($arg1, $arg2, $arg3) = @_;
    
    if (ref(@_[0]) eq "HASH") {
        my %args = %{@_[0]};
        foreach my $arg (keys %args) {
            eval("\$$arg = \$args{\$arg}");
        }
    }
    
    print "\$arg1 = $arg1\n";
    print "\$arg2 = $arg2\n";
    print "\$arg3 = $arg3\n";
}
 
Blogger Templates