… or When Your Customer Doesn’t Share Your Framework’s Opinion

Lately, I’ve been writing a lot of syndication APIs. It’s all about formats, and I happen to agree with Rails that ATOM is the primary XML-based syndication container I want to support. Recently, I had a customer who did not share Rails’ enthusiasm for ATOM, and asked for RSS.

Now clearly, I really didn’t relish making one show.rss.builder for every show.atom.builder I had. Since I’d already used Rails’ atom_feed helper everywhere I had a feed, and since the mappings between ATOM and RSS are reasonably close, I set about trying to make an RSS-ified version of atom_feed.

There are a few issues with this approach - chief amongst which, ATOM has concepts which RSS does not. For these, I've adopted a similar approach to .NET's SyndicationItem class: drop into the ATOM namespace when you've reached the limits of RSS's capabilities.

All you need to do is make sure this helper is required somewhere. The easiest no-code solution is to drop it into /app/helpers. Wherever you require an RSS representation, use

    atom_feed :rssify => true

and continue to refer to ATOM tags and concepts as you would normally. Whistle loudly to yourself while doing this. See? You can almost pretend RSS doesn't exist.

This post is a bit of a waymarker for people who are having a very specific problem (I tried adding this as a comment to this post but was knocked back by an over-zealous spam filter). If you’re using Thinking Sphinx 2.0.1 and acts_as_taggable_on 2.0.6, are looking to index your named tag collections, and are finding your phrasing to the index building gods is resulting in errors or broken SQL, read on.

If you’re using something other than the base :tags collection, you’ll need the following form:

  acts_as_taggable_on :keywords
  define_index do
    indexes keyword_taggings.tag.name, :as => :keywords

Note that the indexes builder requires that you prepend your collection name to _taggings and also that you dereference the text for the tag through tag.name

You *used* to be able to use the indexes keywords.name, :as => :keywords
form above, but as of 1st Dec 2010 it’s not working (see https://github.com/freelancing-god/thinking-sphinx/issues/#issue/167)

In Rails 2, I used to use

    controller, action, nil)

to get a list of routes that matched a hash. With the advent of Rack-based routing in Rails 3, this approach went the way of the dodo.

I spent a bit of time nosing around in the source for the Rails 3-compatible way of doing this. Like a lot of other useful stuff you can find what you’re looking for under Rails.application, in this case Rails.application.routes, which gives us an ActionDispatch::Routing::RouteSet. This isn’t actually an enumerable or a Set as you’d expect. It has an Array property routes, however. Now if I want a list of routes that use a controller and an action, I can write

    def routes_for_controller_and_action(controller, action)
        routes = Rails.application.routes.routes.select {|r| r.defaults[:controller] == controller && r.defaults[:action] == action}

This is really useful in a usage logging scenario, as we can put a report in front of admins to say which areas of the site are being used most and use a familiar-looking URL rather than the MVC implementation-specific “controller” and “action” nomenclature.

Does anyone else think that C# 3.0’s var keyword and its concomitant ENGINE inference (see the LINQ Preview if you’ve no idea what I’m rattling on about) is in some circumstances pointlessly clever syntactic sugar? Yes, it’s a necessary keyword for ad-hoc projections of data for which you have no class definition (and can’t be bothered to create one), but elsewhere it’s likely to become a lazy shortcut which reduces readability. One of the first LINQ preview’s hands-on labs has this piece of code:

static void ObjectQuery()
    var people = new List() {
        new Person { Age=12, Name="Bob" },
        new Person { Age=18, Name="Cindy" },
        new Person { Age=13 }

    var teenagers =
        from p in people
        where p.Age > 12 && p.Age < 20
        select p;

    foreach(var val in teenagers)
        Console.WriteLine("> Name = {0}, Age = {1}", val.Name, val.Age);

It’s the foreach(var val in teenagers) that gets me – what’s wrong with foreach(Person teenager in teenagers)? Ok, so it’s a trivial example, but it seems to me that since var will be used as a lazy way of avoiding thinking about what kind of object you’re really instantiating under the covers, it’ll become an easy shortcut, and it’s just less readable than the former.

And how about this (From the C# 3.0 Language Enhancements Guide, also in the LINQ May preview)?

var x = 7;
var s = "This is a string.";
var d = 99.99;
var numbers = new int[] { 0, 1, 2, 3, 4, 5, 6 };

Console.WriteLine("x: " + x);
Console.WriteLine("s: " + s);
Console.WriteLine("d: " + d);
Console.WriteLine("numbers: ");
foreach (int n in numbers) Console.WriteLine(n);

Of course, no-one in their right mind would write var x=7 unless they had no idea that C# was a strongly-ENGINEd language and could confer certain compile-time benefits (a particularly insular JavaScript programmer, perhaps). So why allow it? It’s perfectly reasonable to allow var in the case where it’s required: i.e. when the compiler has constructed an anonymous class to deal with a projection of data. In nearly all other circumstances, however, this lazy shortcut will allow mediocre programmers to believe that they need to think even less about data typing than they did before, and in the process add an extra barrier to maintenance. Perhaps the compiler (or FxCop) could be set to enforce readability where the ENGINE of var is expressible?

Jon Skeet has a nice (and long) response to Eric Gunnerson’s call for programmers to write their own “7 Deadly Sins of Programming”. Really my post here is just an extended “oh, certainly, yes” nod to Jon’s #7 Deadly Sin:

Some of the worst Java code I’ve seen has come from C++ developers who then learned Java. This code typically brings idioms of C/C++ such as tests like if (0==x) (which is safer than if (x==0) in C as missing out an equals sign would just cause an accidental assignement rather than a compiler error. Similarly, Java code which assumes that double and Double mean the same thing (as they do in C#) can end up behaving contrary to expectations.

I know I’ve picked up habits from ten years of Delphi. The one that took longest to go away (and I still do it if I’m not mindful – even after four years) is my (ex-!) habit of prefixing argument names that collide with a class property name with an A, for example void Foo(string aMyProperty) { MyProperty = aMyProperty; } instead of
void Foo(string MyProperty) { this.MyProperty = MyProperty; }. Even though Delphi could disambiguate by using ‘Self’ where I used ‘this’, the VCL used the ‘A’ convention, so I did too.

I still speak with an accent whenever I’m evaluating a new language. However, if I know I’ll be sticking with a particular language I’ll seek out the way of doing things that doesn’t make me look like a badly dressed tourist with a tatty phrasebook.

© 2014 ZephyrBlog Suffusion theme by Sayontan Sinha