development

The Rails community released Rails 5.0.0.beta1 just before christmas. I’ve added this release to route_downcaser’s test-suite for version 1.1.5, and I’m happy to say, that everything works out of the box. So unless something substantially changes in Rails (which ought not happen), then there will be no problems with upgrading to Rails 5.0 – at least with regards to route_downcaser.

At work I’m usually working on up to 5 issues at a time – sometimes an issue is waiting for input from somebody temporarily away. Sometimes I need to prioritise a new issue above others. So I need to be able to quickly switch between issues – and still make sure to track how long I’ve totally worked on each issue.

So if you’re interested, take it for a spin, and let me know if you have any suggestions for improving it.

I use RVM all the time when I develop Ruby (and Rails) applications. It’s great for isolating Ruby environments and gem packages for a specific project. I also use git extensively – especially branching when developing new features for an app.

Sometimes a branch works with new gems, that I do not want to pollute my main project-specific gemset with. So I create a new RVM gemset for this particularly branch. This has had its own problems because a “git checkout” now also needed to be followed by a “rvm use” statement. Also having a .ruby-gemset file in the project root led to RVM resetting the current gemset as soon as I changed directory.

One solution could be to check-in the .ruby-version/.ruby-gemset files in each branch, but I don’t want to annoy fellow developers with my RVM files. So I came up with the solution below instead.

First for this example, I assume that you have a git repository containing a master branch and another branch. If not, here’s a quickstart to make this happen:

Okay with that squared away, let’s get on with the actual steps. You need to create a RVM gemset for each branch (master and somebranch) with the appropiate .ruby-version/.ruby-gemset files. The principle is, that you rename them, so they have a postfix named after the branch.

And make sure, that the file is executable, since it is just a script:

chmod +x .git/hooks/post-checkout

After you have done this, everytime you checkout a branch, this script will be called. If you checkout somebranch, it will look for a .ruby-version-somebranch and .ruby-gemset-somebranch and copy them to .ruby-version and .ruby-gemset respectively. If you create a new branch but do not make a specific gemset for this branch, the script will instead copy .ruby-version-master/.ruby-gemset-master. So always as a minimum create these.

You might think that now you a all done. However if you try to checkout a “somebranch” now, things will seem strange. The .ruby-gemset file will be an exact copy of .ruby-gemset-somebranch, but if you call “rvm current”, you will still be on the master gemset. Why is this so?

The thing is: .ruby-gemset is now placed correctly, but will not be read by RVM until you change into the actual directory. Try this:

But this is still an extra manual step, that complicates things. You WILL forget this at some point, so let's get rid of it.

You need to edit your $HOME/.bashrc file and add this line:

$HOME/.bashrc

git () { /usr/bin/git "$@"; cd .; }

This changes the git command to a function, which calls the executable git in /usr/bin with all arguments, and afterwards does the otherwise harmless "cd ." which will then make RVM reload the .ruby-version/.ruby-gemset files.

Exit the shell and open a new to reload .bashrc, and you're good to go.

Please let me know, if you have any trouble with the above. Everything has been tested, but evil typos may have creeped into the text.

I’m very anal when it comes to boot time. When I power up my laptop, I want it to be available for me ASAP. As a developer this sometimes conflicts with the need of having a lot of daemons running: PostgreSQL, MySQL, Apache, Memcache, Redis, Solr, etc etc. Services that are needed when i work on different projects. All these daemons takes time to start up, and since I don’t always program, I don’t always need them. But still they start up, and still I have to wait.

So I solved this by disabling the services in the /etc/rc.* folders. And instead I made this little script, which I put into $HOME/bin (which of course is already in your $PATH, right?)

Some people have asked me, why I try to do things in C# that are clearly Ruby-ideoms. The short answer is: Because I can. The longer answer involves thoughts about that you should never stop learning. For a programmer, this involves pushing your tools to their boundaries and beyond. Seeking new insights other places and apply them to your environment. Stuff like that.

Catch-all property (like Ruby’s method_missing)

One of the powerful features of Ruby is method_missing. With this seemingly innocent construct you are able to make a class respond to things that are not statically defined beforehand.

Typical uses are for ORMs like ActiveRecord, that enables you to map class properties to database table-fields without explicitly defining the fieldnames in your class.

The way ActiveRecord does this is, that the model base-class contains a Hash (Dictionary) called attr. When a table-record is loaded, all fields are loaded into this hash. And method_missing are then used to map property-names directly to keys in the hash.

user = User.find(13)
puts user.email

This can also be done in C# using DynamicObject. http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.aspx

DynamicObject is a rather bold introduction into a strong-typed language like C#, since it expose members such as properties and methods at run time, instead of at compile time.

using System;
using System.Collections.Generic;
using System.Dynamic;
public class MyFakeORM : DynamicObject {
// For a clearer example, I don't go into the stuff about loading data from the database into this model
// Dictionary to hold all fields from the loaded record
Dictionary _attr = new Dictionary();
// Catch-all methods for getting and setting a "missing" property
public override bool TrySetMember(SetMemberBinder binder, object value) {
_attr[binder.Name] = value;
return true;
}
public override bool TryGetMember(GetMemberBinder binder, out object result) {
return _attr.TryGetValue(binder.Name, out result);
}
}

Note: For this to work, you also need to define your instance-variable as a dynamic instead of MyFakeORM:

The same thing can be made in .NET by using a combination of the dictionary TempData” and C#’s extension methods. And we can formalize it a bit more by using an enum to control how many different message types, that we will accept.

What I am doing here is, that I extend the base MVC controller with a new method called “Flash()”. You call this in your controller to set a new message, supplying the type of message and the message-string itself.

The same goes for extending the Html helper. I define a method, that will print out all added messages, each of them wrapped into their own DIV tag with classes set appropiate of the message type.

Ruby is a very dynamic language, and you are able to do a lot of stuff with class extensions, meta programming, lambda functions and so forth. When I first experienced Ruby back in 2006 I was very impressed with some of the stuff possible – things that IMHO made C# look stale and static.

Not so any more. The recent updates to C# in 2008 (with .NET 3.5) and lately with .NET 4.0 has added functionality, that enables a more dynamic approach to C# programming, while still keeping the safety net of a strongly typed compiled language.

This is the first part of a small series, where I will take some of the goodies from Ruby and explain how to do it in C#.

Extending classes without subclassing

Most people a first exposed to Ruby through the web framework Ruby on Rails (Rails for short). Rails does a number of cool tricks. One of them is in the ActiveSupport part where the Integer class is extended with some extra methods called days(), weeks(), months(), and years(). This enables some “wow” effects when first looking at Rails code. You are able to do stuff like this: