Run. Bike. Code.

Living the active life while maintaining some nerdiness.

DataMapper DateTime Fields With Default

| Comments

Today’s post should be in the “doh-I’m-stupid” category, but I’ve put it into the Coding category nonetheless.

So, I’m happily hacking away on a new and really small Sinatra app that uses DataMapper as the ORM. The app receives POST requests of a certain form and creates entries in the database for each of these requests. Since I don’t want to have the user pass a timestamp for every entry, I’m making use of the :default key for the timestamp property.

1
2
3
4
5
6
class Entry
  include DataMapper::Resource
  property :id, Serial
  property :when, DateTime, :default => DateTime.now
  property :data, Text
end

So, did you spot the error already? Good on you, because it took me a while to figure out what was going on. See, entries where created alright, but somehow after a while weren’t displayed anymore, when filtered for “entries of the last 24 hours”. Even if you just created an entry, it wouldn’t show up on that page. Let’s take a look at the database, shall we?

db=> select id,"when" from entries order by id;
 id  |        when         
-----+---------------------
   1 | 2014-01-17 17:38:44
   2 | 2014-01-17 17:38:44
   3 | 2014-01-17 17:38:44
   4 | 2014-01-17 17:38:44
   5 | 2014-01-17 17:38:44
   6 | 2014-01-17 17:38:44
   7 | 2014-01-20 13:12:58
   8 | 2014-01-21 15:03:13
   9 | 2014-01-21 15:03:13
  10 | 2014-01-21 15:03:13
  11 | 2014-01-21 15:03:13
  12 | 2014-01-21 15:03:13
  13 | 2014-01-21 15:03:13
  14 | 2014-01-21 15:03:13
  15 | 2014-01-21 15:03:13
  16 | 2014-01-21 15:03:13
  17 | 2014-01-21 15:03:13
  18 | 2014-01-22 11:33:20
  19 | 2014-01-22 11:33:20
  20 | 2014-01-22 11:33:20
  21 | 2014-01-22 11:33:20
  22 | 2014-01-23 15:46:35
  23 | 2014-01-27 11:48:21
  24 | 2014-01-27 11:48:21
  25 | 2014-01-27 13:18:45
  26 | 2014-01-27 13:18:45
  27 | 2014-01-27 13:18:45
  28 | 2014-01-27 13:18:45
  29 | 2014-01-27 13:18:45
  30 | 2014-01-27 13:18:45
  31 | 2014-01-27 13:18:45
  32 | 2014-01-27 16:20:26
  33 | 2014-01-27 16:20:26
  34 | 2014-01-28 10:34:55
  35 | 2014-01-28 11:57:46
  36 | 2014-01-28 11:57:46
  37 | 2014-01-28 11:57:46
  38 | 2014-01-28 11:57:46
  39 | 2014-01-30 17:34:03
  40 | 2014-01-30 17:48:11

NB: Don’t name your database fields when. Just don’t.

All entries are created correctly, but somehow they end up with the same timestamp, even if created minutes and hours apart. And then, the timestamp sometimes changes and again groups a couple of entries to the same date. So after a bit of head-scratching I finally figured it all out: The timestamps correlated to the times when I deployed the code to production, which in turn calls DataMapper.finalize and DataMapper.auto_upgrade!. So whenever I deployed the code, the default value for the timestamp was evaluated (and only then), setting the timestamp to DateTime.now.

Here’s the fix, commit message first and then followed by the correct and updated code.

commit 5cfa94f0c080c9b1a2c80583ff42718446b6588b
Date:   Thu Jan 30 15:31:00 2014 +0100

Default for 'when' is now evaluated with a lambda

Otherwise all entries inherit the 'time of deploy'

To correctly default to the current time when creating an entry in the database, use a lambda for the default value, like so:

1
2
3
4
5
6
7
class Entry
  include DataMapper::Resource
  property :id, Serial
  property :when, DateTime, :default => lambda{ |p,s| DateTime.now}
  property :data, Text
  property :ticket, Integer, :required => true
end

With this fix deployed to production, the timestamps of entries with IDs greater than 39 all have their correct, up-to-date timestamp. Happy campers all around.

Isn’t that embarrassing?

Well, yes, I guess this is a real rookie mistake and I don’t want to blame anyone else than me. Then why did I share this embarrassing story, you ask?

Because Ben Orenstein said so. No, not directly to me, but he often mentions in the excellent Giant Robots smashing into other giant Robots podcast that his number one advice to new programmers is to start a blog and share their findings, no matter how small and irrelevant they seem. Because somewhere, some time, someone will have a similar problem, which you just solved, and by writing about it you share the knowledge.

So, if you wonder why your DataMapper timestamps are all the same, I solved it for you the hard way.

An idiot is someone who doesn’t know something you just learned yesterday.

Adding Static IPs to the Asus RT-N66U Running TomatoUSB

| Comments

… or the tail of how I spent the better part of a day scratching my head.

tl;dr

Don’t assign static IP addresses via ifconfig on the machines in your LAN. Let them use DHCP and then assign static IP addresses to the machines (via their MAC addresses) on the router interface.

When it rains

On Monday this week, our home DSL behaved very flaky. Really slow with a lot of packet loss. Since I’m usually very patient, I didn’t immediately call the provider to open a ticket, instead I waited to see if the problem would go away. It didn’t. On Tuesday I opened a ticket with the Telco, and at the same time tried to figure out what was going on. Reset all devices (splitter, modem, router), tried various settings to make the connection more stable, all to no avail.

Now, after the provider assured to me that the line was ok, I was a bit desperate and figured I’d replace the good old Linksys WRT54GL (running DD-WRT) with the new ASUS RT-N66U which I had bought a while ago and never gotten around to install.

It pours

Shortly after buying the new router I had already replaced the stock firmware with TomatoUSB, specifically the Shibby mod1. This gave me a head start for setting things up on the new router. I configured PPPoE, DHCP, WLAN in that order. Connected with the laptop via wireless and was able to use the internet2.

After that I began to reconnect all other devices, most notably the FreeBSD fileserver. Once connected, I couldn’t reach the WAN (internet) from any other machine. 80% packet loss on the line, whereas the internal LAN worked fine. Strange. Disconnect fileserver, WAN accessible again. After a morning of fruitless debugging, connecting and disconnecting devices and playing around with settings I decided to let it rest and go for a run, as one does3.

After a day in the office with enough distraction (and some googling) I went back to the problem at hand in the evening and tried to see the difference between those devices that could be connected to the LAN ports and worked (like the printer, or the Windows netbook), and those that screwed the network when connected to the LAN port (like the fileserver). After a while it dawned to me that DHCP might be the culprit.

Sunshine

Traditionally the FreeBSD server had its own, static IP assigned via /etc/rc.conf. Apparently, if you do this and at the same time assign (the same) static IP to the server’s MAC via the TomatoUSB UI, it doesn’t work.

The solution for me was to switch the server to use DHCP as well by specifying ifconfig_em0="dhcp" in /etc/rc.conf and then assign the static IP on the router’s interface4:

I still don’t know what caused my connection to be bad at the beginning of the week, but here I am reconnected to the world and at the same time having been forced to finally set up the new ASUS router. I like it a lot and I’m looking forward to setting up more features like a guest WLAN, QoS and OpenVPN. But first I need a break from IT (net-)work.

  1. As an aside, the TomatoUSB firmware is really well done and offers a lot of features that the stock firmware doesn’t offer.

  2. At this point, I think the old Linksys router just crapped out and reached end of life. I certainly won’t debug what the actual problem was but give it its well earned rest in the electronics graveyard.

  3. 17km commute to work.

  4. See the naming scheme? Yep, I’m a Chargers fan.

How to Fix Garmin HR Spikes

| Comments

This is another post that has been sitting in the Trello backlog for a while. With the start of the ‘cold-and-dry-air’ season a.k.a. winter I thought I had it all figured out … how to avoid those dreaded spikes from your heart-rate readings with the Garmin HR strap. And then two things happened.

The Problem

But first, let’s back up a little, in case you don’t know what I’m talking about. In winter times, when there is very little humidity in the air and the outside temperatures are such that you are not easily sweating, then you might end up getting crazy high or low or both (fluctuating) readings from your heart-rate monitor until there is enough moisture built up so that the problem goes away. The result often looks something like this:

Three different runsThree different runs

Mind you, I definitely don’t start my runs with 180+ BPM. And as you can see, the situation takes about 5-15 minutes to settle, and usually all is well thereafter.

Others have written about the problem as well, and I thought I could confirm the proposed solution (ultrasound gel. Yep, sounds as messy as it is). Turns out I can’t. But I have found something that works for me. More on that later. So, what happened that made my glorious ‘Heureka!’ posting obsolete?

4x7 Review

| Comments

I stumble over quite a lot of interesting articles and some are worth sharing on this site. I plan to do this every 4 weeks (thus “4x7 Review”) and I will include my own posts, some training highlights and some of my nutrition. Enjoy!

As seen on runbikeco.de

Notable past training

Looking back at the month of January I have to say I’m pretty proud of my training. I was able to complete four weeks of solid running:

  • (overlapping with the last review): 40km in Week 1, longest 15km.
  • Week 2: 41.95km, longest 15.3km.
  • Week 3: 40.86km, longest 15.0km.
  • Week 4: 40.91km, longest 15.1km.

This is all with four runs per week, completing the month of January with 167.36km in 17 runs (compared to December: 159.95 km in 21 runs).

Additionally, I did two spinning sessions in the gym for crosstraining as well as a couple of strength training sessions (need to be more consistent in doing those).

This current week is a rest week for me, resulting in only 25km of running.

Upcoming training

The next four weeks will focus on aerobic tempo work and increasing the distance for the long run (15/16/18/19km). The overall mileage will be similar to January, maybe slightly more per week (42+km) and if it all works out I should complete the month of February with 174km!

Food consumed

I won’t bore you with everything I ate during the past four weeks, but there is always a meal or two that was special.

Well. With the holidays being over, there was certainly less big cooking going on in our house. But fear not, Super Bowl is coming up on Sunday and I’m sure I’ll fire up the grill. Hopefully I’ll remember to take pictures for the blog!

Found elsewhere

Lastly, a more or less uncommented link-dump of the past 28 days.

With that, have a great four weeks ahead. And remember, you can subscribe to this blog via Atom as well as Feedburner. And if you prefer email over RSS, subscribe to my newsletter, where you can get all new articles (and certainly no spam) delivered right to your inbox. Thanks for reading!

My Plans for the Year 2014

| Comments

This post was sitting way too long in the drafts folder, but by now you all should have well recovered from the various start-of-the-year resolutions postings and therefor can enjoy this again. And I definitely want to get this out before January is over

Note that I specifically didn’t name this “Goals for 2014”, because it’s really more about what I’ve planned to do this year. Of course, I have one or the other goal in mind, especially for the running races, but those will be told when they are due. So, let’s get started in the order of this blog’s name.

Why, Yes, I Am a Chargers Fan

| Comments

If you follow me on Twitter, you might have seen a bit of a smack talk about last weekend’s NFL playoffs, more specifically the SD@DEN game. I wrote the following text a few years ago on my old blog and figured it would be a good opportunity to repost here, with slight adaption regarding times.

I will be back with my regular postings about running, biking and coding right after this one.

This is my 13th season of watching American Football, more specifically, the NFL. For most Americans – who grow up with American Sports – that’s probably nothing spectacular, but I am from Germany, where people think of football as something you play with your feet (11 players on one team) – it’s called soccer in the rest of the world.

I also have a team I root for: the San Diego Chargers. During the past 13 years, a lot of people asked me for why I root for them. I like telling that story, so let’s see if I can write it up properly.

September 2001

I travel to San Diego for a trade show, where my company exhibits. My job is it to set up equipment for the show, which (back then) usually takes forever. My colleague (and later good friend) Paul comes up and says “Henrik, there is a football game in town which I want to see, make sure to be done by noon so that we can watch it together.”. The game in question is CIN@SD. Naturally (since it takes forever to set up the systems), we don’t make it to the game.

4x7 Review

| Comments

I stumble over quite a lot of interesting articles and some are worth sharing on this site. I plan to do this every 4 weeks (thus “4x7 Review”) and I will include my own posts, some training highlights and some of my nutrition. Enjoy!

As seen on runbikeco.de

Notable past training

I got some solid running in over the last four weeks with about 135km in 19 sessions, averaging 7km, with the longest distance back to 14.5km.

I also managed to visit the gym for a couple of strength training sessions as well as one spinning session on the bike.

Upcoming training

For the next four weeks I’ll keep the weekly mileage at around 40km and will not increase the long run to beyond 15km. I’ll add some tempo elements and continue to work on form and strength.

Food consumed

I won’t bore you with everything I ate during the past four weeks, but there is always a meal or two that was special.

This time there is one item of note and it could have ended up as a blog post on its own. We had guests over at the 4th Sunday of Advent for some winter BBQ. With about 12 folks at the house, I decided to try a beef brisket (7kg, no less) for the first time ever.

<br/>Top: as delivered, seasoned for the night, early morning on the grill.<br/> Bottom: 6 hours in, adding some brats, ready to eat (8 hours in)‘ title=’<br/>Top: as delivered, seasoned for the night, early morning on the grill.<br/> Bottom: 6 hours in, adding some brats, ready to eat (8 hours in)‘><span class=
Top: as delivered, seasoned for the night, early morning on the grill.
Bottom: 6 hours in, adding some brats, ready to eat (8 hours in)

In true nerd nature, since this was going to be a long BBQ session, I wanted to throw together an Arduino-based temperature logger to monitor meat and grill heat. Not all parts arrived in time though, so no temperature logger was built this time. Now that I have all parts I’m sure I’ll blog about the project in the future. I just need to invite enough people for that huge amount of beef again.

Oh, for the record, the brisket turned out really tasty!

Found elsewhere

Lastly, a more or less uncommented link-dump of the past 28 days. With the holidays and such, this list is surprisingly short this time. I guess I haven’t been surfing the web a lot over Christmas and NYE.

With that, have a great four weeks ahead. And remember, you can subscribe to this blog via Atom as well as Feedburner. And if you prefer email over RSS, subscribe to my newsletter. Thanks for reading!

Year in Review: A Look Back on 2013

| Comments

The year 2013 is past us by now and so it’s the appropriate thing to do to have a look back and recap what happened.

By the numbers

Well, doh, I’m a nerd, so let’s start with the numbers. On December 11th, I tweeted:

I’m happy to say that I managed to get those missing 2.5km (and then some) of running in! All in all I cycled 1562.94km (29mi short of 1000 miles) in 2013, whereas I ran 1565.83km. For someone having a love-hate relationship with running, this is pretty huge!

If you head over to Strava, you can see my running heatmap and the cycling heatmap. The latter is pretty boring, as I don’t take my bike with me very often abroad, so all the heat is local. But if you zoom out on the running heatmap, you can find at least some remote areas (hint: Baltimore, MD and Miami, FL).

Integrating Trello and Octopress

| Comments

In my last post I wrote about how I use Trello and Beeminder to keep a semi-regular flow of new content appearing in this blog. Today I want to fill you in on the automation that is involved.

From Trello to Vim

I’m lazy. That’s why I automate things instead of doing them manually over and over again. As mentioned in the previous post, I draft most of the blog content in Trello. However, Octopress needs the content in a file so that it can generate a static HTML page out of it. Instead of copying my draft content out of Trello and into an editor, I wrote a short Rake task to do the same thing:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
desc "Pull card from Trello and generate post from it"
task :new_trello_post do
  b = Trello::Board.find(ENV["TRELLO_BOARD"])
  content_cards = []
  b.cards.select {|c| c.list_id == ENV["TRELLO_LIST"] }.each do |card|
    card.labels.each do |label|
      if label.name == "CONTENT"
        content_cards << card
      end
    end
  end
  content_cards.each do |c|
    puts "Id: #{c.id} ('#{c.name}')"
  end
  c_id = ask("Which card? ",nil)
  card = Trello::Card.find(c_id)
  if not card.nil?
    Rake::Task["new_post"].invoke(card.name)
    new_post_file = ENV['NEW_POST']
    open(new_post_file, 'a') do |post|
      post.puts card.description
    end
  end
  `git commit -m 'Adds draft for #{card.name}. Start #{card.short_id}' #{new_post_file}`
end

Let’s walk quickly through it, shall we? I have the ID of my Trello board as well as the ID of the “Draft” list in my environment (lines 3 and 5). With those IDs, using the ruby-trello gem, I fetch all the cards of the “Draft” list that are labeled with “CONTENT” and present (myself) a list with these cards (lines 6-14). I can then choose one by ID and generate a new Octopress post by re-using the appropriate Rake task (line 18). I’ve modified this task to return the filename of the new post via the environment, so that I can automatically add the draft content (as pulled from Trello) into the file and submit the first draft to git (lines 19-24). With a magic commit message (see below), the card gets moved from the “Draft” list to my “Doing” list.

From Git to Trello

Now that I had the ability to feed my editor with the draft content from a Trello card, I wanted to be able to update the original Trello card. Not necessarily with the changes to the content, but more with a log of activity and especially the possibility to notify Trello once the card was done (i.e. the blog post was published). Turns out, Jason Fox had the same desire and wrote a detailed instruction on how to use a small app on Heroku to update Trello from Github. My setup is more or less a verbatim copy, obviously using the right board-id and list-ids.

As you can see above, I will automatically move a draft card by specifying the card.short_id in the commit message.

From Trello to Beeminder

Once I’m happy with the content and ready to publish I’ll commit the final version to git, using the magic word Finish #11 (the draft for this post happens to be card 11, quite a long time candidate to write about). After pushing to the Github repository, the web-hook will update the Trello card one final time, moving it to the “Done” list. And that’s where Beeminder will pick it up and count it towards my “Keep Blogging” goal.

After this short excursion into the technical details of this blog (remember, it’s not only Run and Bike, but also Code!), I will see to get some running content up next. After all, I’ll start my last race of 2013 tomorrow: A 10km New Year’s Eve run.

My Blogging Workflow With Beeminder and Trello

| Comments

As noted in my last post I had planned to write about my blogging work-flow, and today, almost 6 months after starting this blog, shall be the day.

Before I started this very blog, I had a Tumblr, where I posted a couple of entries and then stopped. I still wanted to blog, but writing blog posts never was my priority, and I also wasn’t too happy with the Tumblr platform. In the meantime, I tried to set up a Drupal based blog, but quickly noticed that just maintaining the setup drained more energy than I was willing to invest.

Enters the new kid on the block, Octopress, a simple “blogging platform” based of the static site generator Jekyll. I like the fact that I can edit blog posts in my favourite editor and store them all in Git for revision control. Furthermore, since Octopress is open source, I can customize, modify and add functionality at will.

Now, Octopress is great, except when it isn’t. Since it doesn’t come with an online editor to draft blog posts, and since I don’t always have access to my development box that has the git repository1, I needed something that enabled me to quickly jot down blog ideas. I usually even need to work on the draft some time before I can actually sit down and fill the details.

Trello to the Rescue

Luckily, there is an awesome web-based tool called Trello. From their help:

Trello is a collaboration tool that organizes your projects into boards.
In one glance, Trello tells you what's being worked on, who's working on
what, and where something is in a process.

Besides the super-easy-to-use Web application, Trello has a mobile app, which works really great on my phone as well as on my tablet. That way, I can work on my blog content from any computer or even on the go. So here’s how I use Trello for blogging:

Since I use Trello for other stuff as well, I created a Board called ‘Blog’, which holds these four lists:

  • Ideas
  • Draft
  • Doing
  • Done

That’s really all there is to it. If I have an idea for a blog post, I’ll just add a card to the “Ideas” list, giving it a preliminary title and label it with the “Content” label2.

Keep Going

One problem of my old blog was that, while I really wanted to have a blog because I had all kinds of posts in my mind, nothing forced me to write a post. Now, I use the term “force” in a positive sense here. I sometimes need some external pressure to make things happen. When I decided to start Run. Bike. Code. I really wanted to stick with it this time. Beeminder is the perfect tool for people like me.

You commit to a goal, get reminded on a regular basis, and if you fall off the waggon, you have to pay out of your own pocket for it (that’s the simplified version, for details on why and how Beeminder works for “us”, please head over to their website and check out all goodness there).

Turns out, Beeminder integrates with Trello. I have a Beeminder goal to move one Trello card to the “Done” list3 per week. So the complete work-flow works like this:

  1. Create a card in “Ideas”.
  2. Move the card to “Drafts” when I know more details of what to actually write.
  3. Do the necessary steps to add meat to the card, i.e. research, collect pictures, or just plain writing.
  4. Once the card seems ripe and I have some free time at hand, move the card to “Doing”. Start the blog post within my git repository, using the material collected so far.
  5. When I’m happy with the post, I’ll publish it and move the card to the “Done” list.
  6. Beeminder will pick it up from there and update the goal.

Now, if you do the math, starting from my first post to today, there should be 40 blog posts published, having derailed from the goal only once. If you actually go through the archive, you’ll find only 34 posts. That’s because I had (and still have) a couple of non-content cards that I completed, especially in the early phase of this blog. I use Trello for those as well, justified by the fact the by working on those I actually work on the blog, thereby keeping it alive.

Now, being the lazy nerd, I don’t manually move cards around on the Trello board, there is some automation for that, which I shall explain in a future post (yes, it has a Trello card already).

Also, should I really run out of ideas, Beeminder lets me easily adjust the goal rate, or, if I know I won’t be able to blog (e.g. during vacation) I can schedule a break without violating the contract. Works out really nice.

With that, thanks for reading, especially to my new readers! You can expect weekly posts for quite some time. And remember, Beemind all the things!

  1. Nor can I write blog posts from idea to published article on one go.

  2. I also have a label for technical, or behind-the-scenes, stuff that I want to change or implement for the blog.

  3. Technically, “archived” cards count as well, helping me to keep the “Done” list clean.