Merging Nested Hashes in Ruby

RubyA typical use for Hash#merge is merging user supplied options with the default options for a particular action. Just now while doing this, I realized that the built-in merge method doesn’t merge nested hashes. First, let’s look at a trivial example use-case where you might need this.

Continue reading

ImageMagick Tips and Tricks

TerminalI’ve been using ImageMagick in one of my projects and I’ve had to do quite a bit of Googling. Below are some tips and tricks I’ve collected that might be useful to others.

Trim Whitespace From Your Image

$ convert -trim img.png

Create A New Image From Text

Note: You can combine this with the ‘trim’ tip above by passing the -trim argument.

$ convert -background white -fill black -pointsize 72 label:"Sean Fox" output.png

Output:
ImageMagick Converted Text

List Fonts ImageMagick Can Use

$ identify -list font

Building Ruby Gems Cheat Sheet

RubyHere are some quick commands for building and installing ruby gems locally. This is just for reference; I’ve been meaning to make more of these kinds of posts.

Bump the Gem Version

To bump to version 1.0:

echo "1.0" > VERSION

Generate the Gemspec

rake gemspec

Build the Gem

gem build ./hello_world.gemspec

Install the Gem

gem install ./hello_world.gem

NHibernate AutoMapping Persister Error

Microsoft .NETIf you’ve configured FluentNHibernate with automapping, it’s easy to run into a persister error like the one below.

NHibernate.MappingException: No persister for:
XYZ.ProductName.Model.Customer

But this was working last time I compiled and I haven’t been writing database code. What could I have done?

The Problem

NHibernate cannot find your model. Did you move it? Maybe you were just doing some refactoring and you moved the models to a different namespace?

Check Your FluentConfiguration

First you should check your FluentConfiguration and make sure you’ve actually wired up the model that’s missing.

var automappingConfiguration = new MyAutomappingConfiguration();
Fluently.Configure()
                    .Database(SQLiteConfiguration.Standard.ConnectionString(connectionString).ShowSql())
                    .Mappings
                    (
                        m => m.AutoMappings.Add(AutoMap.AssemblyOf<Customer>(automappingConfiguration))
                    )
                    .BuildConfiguration();

Yep, there’s our Customer. So why can’t NHibernate find it?

Check Your AutomappingConfiguration

Next you should check your AutomappingConfiguration and make sure it’s pointing to the correct namespace.

public class MyAutomappingConfiguration : DefaultAutomappingConfiguration
{
	public override bool ShouldMap(Type type)
	{
		return type.Namespace == "XYZ.ProductName.SomeOtherProject.Models";
	}
}

Doh! I moved those models to a new namespace during some refactoring with Resharper. I better update the namespace in my AutomappingConfiguration.

Hopefully you’ve managed to help NHibernate find your models now.

Have fun coding!

Configuring FluentNHibernate with SQLite in .NET 4

Microsoft .NETConfiguring FluentNHibernate with SQLite can be a bit painful, particularly because the SQLite assemblies are built separately for x86 and x64. On top of that, because NHibernate is loading the SQLite DLL at runtime, the DLL needs to be in a location that NHibernate can find it. When trying to set this up myself, I ran into the following error:

An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection,
and InnerException for more details.

And the inner exception looked like this:

Could not create the driver from NHibernate.Driver.SQLite20Driver, NHibernate, Version=3.3.1.4000, Culture=neutral,
PublicKeyToken=aa95f207798dfdb4.

The Problem

Typically this error just means NHibernate cannot locate and load the SQLite DLL. This could be because you’re trying to load the 64-bit DLL under a 32-bit project or vice-versa. I noticed a lot of people were simply configuring their Visual Studio projects for x86 and referencing only the x86 SQLite DLL to solve this problem, but this is unnecessary. Below I’ll explain how to set this up properly.

The Solution

Basically the System.Data.SQLite DLL needs to be in the same directory as the NHibernate DLL. Typically, whichever Visual Studio project is set as the startup project (your main application interface) should have a reference to System.Data.SQLite. So just add the NuGet package to that project, as well as any test projects that may need access to the database as well.

The Long-winded Solution

Or if the above wasn’t clear enough…

Install FluentNHibernate

Firstly, you need to have FluentNHibernate installed and referenced in your project. For this, I would recommend installing NuGet.

After NuGet is installed, just grab the package using the GUI or run the Install-Package command from the NuGet prompt:

PM> Install-Package FluentNHibernate

You’ll reference FluentNHibernate from any project that uses it in the code, just like normal.

Configure FluentNHibernate

Make sure you’re building a valid NHibernate configuration in your code using Fluently.Configure() and that you’re using FluentNHibernate.Cfg.Db.SQLiteConfiguration.

Install SQLite

Using NuGet, grab the package using the GUI or run the Install-Package command from the NuGet prompt:

PM> Install-Package System.Data.SQLite

Make sure you’re installing System.Data.SQLite and NOT installing System.Data.SQLite.x86 or System.Data.SQLite.x64. The System.Data.SQLite package contains both the x86 and x64 versions of the DLL, which is what I would recommend if you want to compile your application for both 32-bit and 64-bit machines.

Reference SQLite

Add to reference to System.Data.SQLite to your primary application project (e.g. the startup project, the GUI, etc.). Also add a reference to any test projects that use the database, such as your NUnit tests.

You’re Done?

Does it work? If so, congrats! Happy coding!

It Didn’t Work

Ok, so if it didn’t work, you can try telling .NET which assembly to load.

Update Your App.config or Web.config

In your App.config or Web.config for your main application or any other projects that access the database, add the following:

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <qualifyAssembly partialName="System.Data.SQLite"
          fullName="System.Data.SQLite, Version=1.0.84.0,
          Culture=neutral, PublicKeyToken=db937bc2d44ff139"/>
    </assemblyBinding>
  </runtime>

The qualifyAssembly element specifies the full name of the assembly that should be dynamically loaded when a partial name is used; this should ensure the correct version is loaded at runtime.

Also, if you’re wondering how I got the PublicKeyToken for the DLL, check out my article on finding the public key token for a .NET DLL or assembly.

Finish Line

You’re all done! Now you can use FluentNHibernate and SQLite in both x86 and x64 mode. The correct DLL should be loaded based on your project/compiler settings.

Happy hacking!

How to find the public key token for a .NET DLL or assembly

Microsoft .NETWhen using .NET, sometimes you need the public key token for a strongly named assembly. Below I’ll explain how to glean that information using sn or gacutil.

Where are these utilities?

The two utilities you can use to get public key tokens are sn and gacutil. You can find either of them in the Visual Studio Command Prompt or the .NET Framework directory.

Visual Studio Command Prompt

To get to the Visual Studio Command Prompt, just hit the Start menu and type Visual Studio Command Prompt into the finder. If you have Visual Studio installed, you should be able to find this tool.

.NET Framework Directory

Alternatively, you can also run these tools from the .NET Framework directory. For .NET 4.0 or 4.5, you’ll find the tools here: C:\Windows\Microsoft.NET\Framework\v4.0.30319

Just navigate to that directory in cmd.exe or PowerShell.

Public Key Tokens with sn

Just run sn -T followed by your DLL or assembly. Here’s an example:

PS > sn -T "C:\dev\project_name\packages\System.Data.SQLite.1.0.84.0\lib\net45\System.Data.SQLite.dll"

Microsoft (R) .NET Framework Strong Name Utility  Version 3.5.30729.1
Copyright (c) Microsoft Corporation.  All rights reserved.

Public key token is db937bc2d44ff139

Public Key Tokens with gacutil

If the DLL is in the GAC, you can do the same thing with gacutil:

PS > gacutil -l System.Data.SQLite
Microsoft (R) .NET Global Assembly Cache Utility. Version 4.0.30319.1
Copyright (c) Microsoft Corporation. All rights reserved.

The Global Assembly Cache contains the following assemblies:
System.Data.SQLite, Version=1.0.84.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=AMD64

Number of items = 1

Now go get that token you were after!

Fixing .NET Framework 4 Client Profile Dependency Issues

Microsoft .NETIf you’ve worked with .NET 4, you might have run into this before. You’re casually typing and clicking along and then you go to add a reference to your project; but suddenly your application won’t build any more. The error complains about your targeted framework and a Microsoft library dependency. This library is included in .NET, but it won’t add to my project! What gives?

The referenced assembly "StructureMap" could not be resolved because it has a dependency on
"System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" which is not in the
currently targeted framework ".NETFramework,Version=v4.0,Profile=Client". Please remove references
to assemblies not in the targeted framework or consider retargeting your project.

The Problem

If you take a closer look at the error, you’ll notice the targeted framework includes the text Profile=Client.

The .NET Framework 4 Client Profile is a subset of the .NET Framework 4 that is optimized for client applications; it restricts the set of referenced assemblies to only those that are interesting to a client application. For example, it won’t make System.Web available by default because it is not typically valuable to client apps.

So if you started building a Forms app (or WCF or WPF), Visual Studio might have defaulted you to target the .NET Framework 4 Client Profile instead of just .NET Framework 4. And now, it’s complaining because you want to add libraries that a client application doesn’t typically have any use for.

The Solution

Right-click the project that needs the reference added, click properties, and update the project to target .NET Framework 4 instead of the Client Profile.

Visual Studio Project Properties - .NET Framework 4

Now get back to work!

How To Fix DataGridView Rows Showing Up Without Data

Microsoft .NETThe DataGridView is incredibly helpful for binding data sources to a grid, but sometimes working with it is a bit tricky. If you use the DataGridView control sparingly (or you’re just plain forgetful), you might run into an issue where you can see rows in the grid, but all the cells are empty!

DataGridView Empty Rows

The Problem

Not to worry! If you’re seeing the correct number of rows, you probably just have some visibility problems with the class being used.

In my case, I was trying to bind a list of proxies (List) like this:

private void BindProxyGrid(IList proxies)
{
    var proxiesBindingList = new BindingList(proxies);
    dgvProxies.DataSource = proxiesBindingList;
}

And my proxy class looked something like this:

public class Proxy
{
    public string Ip;
    public int Port;
}

The Solution

So why didn’t it work? Because the DataGridView requires properties and I was using public fields. Updating the class to use properties fixed the problem!

public class Proxy
{
    public string Ip { get; set; }
    public int Port { get; set; }
}

It works!

DataGridView Filled Rows

The Lesson Learned

If you’re using a BindingList with your DataGridView, you may need to adjust the visibility for any class members you want to display in the grid; for example, the DataGridView can’t access public fields or properties marked internal.

Happy coding!

Normalizing Line Endings Across Multiple Files

Terminal Recently I’ve been noticing some of my C# files have inconsistent line endings.

Visual Studio: Inconsistent Line Endings

The Problem

The line endings in the following file are not consistent. Do you want to normalize the line endings?

This probably means some of the developers have been editing our source code using a text-editor (instead of Visual Studio) and they had their line endings set to “Unix” or “Mac” instead of “Dos/Windows”. This isn’t a big deal, though it is annoying.

Vim: Convert All Files to Dos/Windows Line Endings

Since I don’t know which files have this problem, I decided to just normalize all the line endings. There are various ways to do this, but I chose to use vim since the documentation on this topic is excellent.

To convert from any mixture of CRLF endings and LF-only endings, to CRLF endings:

:set ffs=dos
:args **\*.cs
:argdo w

We’re basically asking vim to assume Dos/Windows line endings, having it open all *.cs files (C# code files), then having it write the line-ending changes.

Downsides

This does change every single file that was found, regardless of the original line endings. It’s best to do this as one commit in source control to avoid any confusion.

Alternatives

You can also use unix2dos to do this conversion or any scripting language (python, perl, powershell).

Some people also let their source control handle their line endings. Git can enforce these line endings by updating them for you if you prefer. However, at my office, we choose not to let our source control alter our code in any way; we prefer to do that ourselves. :)

Now get back to coding!

Setting a Default Upstream Branch in Git

Terminal So you’re working in a branch in your Git repository, and you’ve just made some changes. You just ran git commit and now you want to merge any changes from upstream. So you issue a git pull and BAM!, you see this error:

# git pull
You asked me to pull without telling me which branch you
want to merge with, and 'branch.xyzbranch.merge' in
your configuration file does not tell me, either. Please
specify which branch you want to use on the command line and
try again (e.g. 'git pull  ').
See git-pull(1) for details.

If you often merge with the same branch, you may want to
use something like the following in your configuration file:
    [branch "xyzbranch"]
    remote = 
    merge = 

    [remote ""]
    url = 
    fetch = 

See git-config(1) for details.

So what gives? Why doesn’t git know what you’re trying to do?

Where is My Upstream Branch?

The problem is git has no idea which branch you want to pull from or push to. Chances are you made this branch like this:

# git branch xyzbranch

That creates a new branch in your git repository, but it’s not set up to track any remote (upstream) branches. You can use git remote show origin to see where your branches are pushing and pulling if you’d like to verify that.

# git remote show origin
* remote origin
  Fetch URL: git@hostname:repository.git
  Push  URL: git@hostname:repository.git
  HEAD branch: master
  Remote branches:
    another_branch    tracked
    master            tracked
    some_other_branch tracked
  Local branches configured for 'git pull':
    another_branch    merges with remote another_branch
    some_other_branch merges with remote some_other_branch
  Local refs configured for 'git push':
    another_branch    pushes to another_branch (fast-forwardable)
    master            pushes to master (up to date)
    some_other_branch pushes to some_other_branch (up to date)

So there is no upstream branch set for xyzbranch! That’s not really a problem, it just means you have to tell git where to pull changes from and where to push them to every time you use git pull and git push. But that’s annoying, so how do we fix it and set a default remote branch?

Setting Your Upstream Branch

If you’re on a branch called xyzbranch and you want to track the master branch, you could use git branch –set-upstream to do that like this:

# git fetch origin
# git branch --set-upstream xyzbranch origin/master
Branch xyzbranch set up to track remote branch master from origin.

And suddenly, voila!

# git pull
Already up-to-date.

No more complaining from git!

For more tips and tricks on Git, check out GitReady.com.

Git it done!