Hardscrabble 🍫

By Max Jacobson

See also: the archives and an RSS feed

devblog

March 19, 2013

Note: When I was first learning Ruby in late 2012, I made a small web app called “beefsteak” to act as my blog. I wrote several posts on that blog while I was exploring and adding features. I’ve since migrated my personal blog away from beefsteak and to Octopress, and then Jekyll. I decided to collapse those posts into one post because I think they’re kind of confusing now that they’re on a Jekyll site. I’m writing this note on July 10th, 2016. By the time you’re reading this, who knows what the blog is running on…

testing this little devblog thing

Originally posted December 1, 2012

So it’s like 6am and I guess I just made my first mini markdown blog engine.

I’m almost certainly too quick to congratulate myself. It has approximately zero features but it’s succeeding at putting HTML on the screen and I call that a win.

This is pretty much the whole app:

require 'sinatra'
require 'kramdown'

get '/' do
  @title = "devblog - max jacobson"
  the_html = String.new
  the_html << "<h1>#{@title}</h1>\n\n<hr />"
  posts = Dir.entries("posts")
  posts.each do |filename|
    if filename =~ /.md/
      the_text = File.read("posts/" + filename)
      the_html << Kramdown::Document.new(the_text).to_html + "<hr />"
    end
  end
  erb the_html
end

get '/css/style.css' do
  scss :style
end

It just checks all the files in a directory called “posts”, checks all of the ones with the .md file extension, and then renders them all one after the other. That’s it!

I wrote this in just a minute or two so I’ll be sure to add more blog-like features to this. Maybe design it up a bit. That mention of sass is more or less for show.

I feel smart right now so I’m comfortable admitting that I’d love to use Jekyll but just can’t figure out how the hell it works.

This is not one of those smartly static sites. It generates each page as you load it. Probably pretty fast, but still, not smart-smart.

Already with the updates

Originally posted December 1, 2012

There are already updates wow I am good.

Things I’ve added in the last small amount of time:

Here’s what the tree of my project directory looks like right now:

[~/Dropbox/Sites/devblog] [maxjacobson] [07:41 AM]
ϡ tree
.
├── Gemfile
├── Gemfile.lock
├── Procfile
├── config.rb
├── posts
│   ├── 2012-12-01-already-updates.md
│   ├── 2012-12-01-gem-anxiety.md
│   └── 2012-12-01-the-first-post.md
├── views
│   ├── layout.erb
│   └── style.scss
└── web.rb

2 directories, 10 files

Off topic, but: I learned how to customize my bash prompt earlier today and that’s what it looks like.

added sorting

Originally posted December 1, 2012

I have added sorting and so I believe the posts on the homepage will be in the proper order. Kewl.

did i just implement search in like 5 minutes?

Originally posted December 1, 2012

I’m not sure but I think I just implemented search like it was no big deal.

It works well and fast but only because there are so few posts, I assume. I’m not searching the whole internet here or anything, but I do kinda feel like I Am Google or something.

That’s a theme for this system: it will get worse the more I use it. I’m kinda excited to ruin it.

man, sorting is hard when you use the twelve hour clock

Originally posted December 1, 2012

I have a TextExpander snippet for quickly inserting the current time. I write ttime and it inserts, say, 10:43 PM. In that format. If it were an hour earlier, it would say 9:43 PM. No leading zero.

This is what was screwing up my sorting method.

I want posts to be sorted based on both date and time, so if there are multiple posts in a day they’ll show up in the right order instead of just alphabetically.

I could have just written those leading zeros manually or I could’ve just used a twenty-four hour clock, but I like my snippet how it is and want my code to come to me rather than the other way around.

So I’ll share my method because I’m sure in as little as a month I’ll find it embarrassing and that’s very fun for me, being embarrassed.

The argument for this method, to_sort, is an array of hashes that stores all of the posts.

Each hash looks like this:

{
  :text=>"the body of the post (in markdown) would go here, but it would be long so I'm leaving it out",
  :title=>"Introducing myself to the command line",
  :date=>"2012-02-26",
  :time=>"12:00 PM",
  :category=>"coding",
  :tags_array=>["command-line", "learning"],
  :filename=>"2012-02-26-introducing-myself-to-the-command-line"
}

And the method takes the info, specifically the date and time, and adds an additional parameter, :sorter, and then sorts the array based on that value of each hash, and returns the sorted array.

def sort_posts (to_sort)
  to_sort.each do |post|
    the_date = post[:date]
    the_time = post[:time]
    if the_time =~ /AM|am/
      if the_time =~ /^[0-9]:/ # aka ONE digit before the colon
        sorter = the_date.gsub(/-/,'') + ("0" + the_time).gsub(/:| |AM|am/,'')
      else
        sorter = the_date.gsub(/-/,'') + the_time.gsub(/:| |AM|am/,'')
      end
    end
    if the_time =~ /PM|pm/
      if the_time =~ /12:/
        sorter = the_date.gsub(/-/,'') + ((the_time.gsub(/:| |PM|pm/,'')).to_i).to_s
      else
        if the_time =~ /^[0-9]:/ # aka ONE digit before the colon
          sorter = the_date.gsub(/-/,'') + ((("0" + the_time).gsub(/:| |PM|pm/,'')).to_i + 1200).to_s
        else
          sorter = the_date.gsub(/-/,'') + ((the_time.gsub(/:| |PM|pm/,'')).to_i + 1200).to_s
        end
      end
    end
    post[:sorter] = sorter.to_i
  end
  to_sort.sort! { |a,b| b[:sorter] <=> a[:sorter]}
  return to_sort
end

So that’s that.

Edit (2012-12-02, 10:58 AM): There’s a bug in there! posts at 12:15am would sort newer than posts at 1:15am becuase twelve is a higher number than one. So I added some conditioanls to treat 12 like zero. Updated code below:

def sort_posts (to_sort)
  to_sort.each do |post|
    the_date = post[:date]
    the_time = post[:time]
    if the_time =~ /AM|am/
      if the_time =~ /^[0-9]:/ # aka ONE digit before the colon
        sorter = the_date.gsub(/-/,'') + ("0" + the_time).gsub(/:| |AM|am/,'')
      elsif the_time =~ /^12:/
        sorter = the_date.gsub(/-/,'') + ("00" + the_time).gsub(/:| |AM|am|12/,'')
      else
        sorter = the_date.gsub(/-/,'') + the_time.gsub(/:| |AM|am/,'')
      end
    end
    if the_time =~ /PM|pm/
      if the_time =~ /12:/
        sorter = the_date.gsub(/-/,'') + ((the_time.gsub(/:| |PM|pm/,'')).to_i).to_s
      else
        if the_time =~ /^[0-9]:/ # aka ONE digit before the colon
          sorter = the_date.gsub(/-/,'') + ((("0" + the_time).gsub(/:| |PM|pm/,'')).to_i + 1200).to_s
        else
          sorter = the_date.gsub(/-/,'') + ((the_time.gsub(/:| |PM|pm/,'')).to_i + 1200).to_s
        end
      end
    end
    post[:sorter] = sorter.to_i
  end

  to_sort.sort! { |a,b| b[:sorter] <=> a[:sorter]}
end

SEE?? Embarrassing. I love it. I’m sure there’s an easier way to do this. But it’s interesting, I think, that an idea (“hmm, i want to sort by both date and time, so why don’t I make a :sorter variable that takes those two strings and combines them into one an integer that represents when it was posted”) morphs and grows into this 28 line mess. I guess it’s time to refactor.

categories and tags

Originally posted December 1, 2012

I added some functionality for categories and tags. The difference between categories and tags, in my implementation, is that there can only be one category, but there can be a bunch of tags.

So be generous with your tags.

You can use spaces in your categories and tags and they’ll be converted to hyphens. They’re comma-delimited.

You can see the tags at the bottom of this post and you’ll see some hyphens. but if you look at the markdown source, you’ll see some spaces.

(You can see the markdown source by clicking the link at the bottom of each post or by simply replacing the / with .md at the end of a post url)

RSS is hard to implement and I’m not sure I’m doing it right

Originally posted December 1, 2012

I’m pretty sure I’m not doing this right but I’ve added an RSS feed so that’s fun, enjoy.

It’s available at /feed and ever time that “file” is queried, the sinatra app will generate an up-to-the-minute accurate feed, including all of the posts.

I don’t necessarily recommend subscribing because I might change where it’s located soon. Right now the blog is online at http://devblog.maxjacobson.net but I may move it to blog. or beef. or beefsteak. or something else entirely.

going open source

Originally posted December 2, 2012

Just for fun I’m sharing the source code for this blog in full on github. I don’t know if anyone else will or should use this but maybe they’ll want to and I won’t stop them.

It’s surprisingly easy having two remote destinations for this code (heroku, where my blog is hosted, and now github where the source code is hosted). I make changes, commit them, push to one, then push to the other. Easy peasy.

If someone else wants to use it, they’ll have to delete my stuff and replace it with their stuff. I’m not giving them a blank slate. Because I’m not sure how to maintain two separate versions like that. But they’ll figure it out, I think.

I guess I’ve been planning to do this, because I’ve refrained from hardcoding my information (name, blog title, etc) into the code. Instead it’s in a separate config.rb file (which you can see on github).

I’m cold on this balcony in San Diego. I am proud that I made this in like two days. I will keep working on it. A small part of me just got a tingling urge to hurl my laptop down into the parking lot like it’s my punk rock guitar.

I’m worried that it will be a whole hassle if I ever want to change the address of this blog. I already kinda feel limited by “devblog”.

Right now my Top Level website, http://maxjacobson.net is mostly just a front for my Pinboard public links. maybe I’ll merge that idea into this one and put the whole thing at that address. I glanced over the Pinboard gem and I could probably whip something up myself instead of using the linkroll widget. That would give me some more flexibility to display multimedia stuff, Layabout-style and do some more color-coding without having to use jquery like I’m currently doing to emphasize posts with the max_jacobson tag.

I’m just daydreaming here.

some new features here

Originally posted December 13, 2012

Things I’ve added to beefsteak tonight:

more feeds

Like, for individual categories, tags, and search queries. Try clicking on a tag/cat or searching something, and you’ll see a link to the feed at the bottom.

A fun one might be: http://devblog.maxjacobson.net/tag/gush/feed or http://devblog.maxjacobson.net/search/confess/feed if you like me at my gushiest or most confessional.

pages

My about page is now at http://devblog.maxjacobson.net/~about. I made another one mostly to test what it looked like with two. It doesn’t look great.

You can view the markdown source of pages the same as posts. Just add the .md suffix or click the link at the bottom. I don’t know why I offer this. It doesn’t work amazingly. In some posts with code, I see underscores disappear. It’s weird.

favicon and apple touch icon

I just threw in some all-black-errything squares for now. I figure if anyone else uses this they can replace with something they like.


Here’s what the tree for this site looks like right now:

(notice the new pages directory, mostly)

[~/Dropbox/Sites/devblog] [max] [08:23 PM]
 ϡ tree
.
├── config.rb
├── Gemfile
├── Gemfile.lock
├── helpers.rb
├── pages
│   ├── about.md
│   └── projects.md
├── posts
│   ├── 2011-03-12-un-americano.md
│   ├── 2012-02-26-introducing-myself-to-the-command-line.md
│   ├── 2012-08-26-favblogging.md
│   ├── 2012-12-01-added-sorting.md
│   ├── 2012-12-01-already-updates.md
│   ├── 2012-12-01-categories-and-tags.md
│   ├── 2012-12-01-gem-anxiety.md
│   ├── 2012-12-01-sleep.md
│   ├── 2012-12-01-sorting.md
│   ├── 2012-12-01-the-first-post.md
│   ├── 2012-12-02-erb-and-indendation.md
│   ├── 2012-12-02-on-an-airplane.md
│   ├── 2012-12-02-open-source.md
│   ├── 2012-12-02-RSS-is-hard.md
│   ├── 2012-12-02-search.md
│   ├── 2012-12-04-seal-attack.md
│   └── 2012-12-13-meetups.md
├── Procfile
├── public
│   └── img

│       ├── 2012-12-04-seal-1.jpg
│       ├── 2012-12-04-seal-2.jpg
│       ├── 2012-12-04-seal-3.jpg
│       ├── apple-touch-icon.png
│       └── favicon.ico
├── README.md
├── views
│   ├── 404.erb
│   ├── 500.erb
│   ├── layout.erb
│   └── style.scss
└── web.rb

5 directories, 35 files

fuzzy search

Originally posted December 14, 2012

I just made the search a little smarter on this blog. I think. I made it so that when you search a multi-word query, it’ll include posts that match any of the words, not just posts that match all of the words. They’re sorted chronologically, not based on relevance.

And you can put a query in quotes if you want it to match all of the words, in that order.

Here’s how I did that (with some stuff paraphrased):

if query =~ /^".+"$/
  query_array = [query.gsub!(/"/,'')]
else
  query_array = query.split(' ')
end
# ... each post |the_text|
query_array.each do |q|
  if the_text =~ Regexp.new(q, true)
    # then include the post
    break
  end
end

So, first I check if the query is in quotes (I’m coming to really love using regular expressions), and if so I remove the quotes and put that whole string thru. If it’s not in quotes, I split the string into an array of strings, using a space as the delimeter. Then I go through each post and check it against each item in the array. If the query was in quotes, the array only has one item in it. Once there’s a match, I push it thru. The break makes it so once a post matches the query, we move on to the next post rather than keep checking other words in the query against it.

I wonder if I should allow single quotes too. Note to self, allow single quotes.

I wonder what new bugs I just introduced.

heave ho

Originally posted December 22, 2012

So I am happy enough with beefsteak that I am moving this to my proper homepage, http://www.maxjacobson.net.

That space was mainly occupied by my pinboard public links, and I’ve integrated those into beefsteak now.

I considered integrating a pinboard gem but for now I’m sticking with the same old linkroll widget I’ve been using. It’s not super flexible but it has an important feature the main pinboard gem lacks: a distinction between private and public links. It’s not that I have such private stuff in there, it’s just that I have so much stuff in there. As previously described I use IFTTT to send all kinds of stuff automatically, and then I occasionally make a small minority of those links public. And maybe there’s some private stuff in there.

Who is sleepier than I? No one is.

The project is still mostly useable by other people, I think. The only thing is the small jquery script that modifies the DOM so that links with the tag max_jacobson are made red. I tweaked it so it lets you specify what that tag will be, but it’s not working. I’m going to fix that later, maybe.

I create links just to kill them at this point. Old feeds and links have a short shelf life.

beefsteak v2

Originally posted March 19, 2013

This version of beefsteak is brought to you by Justin Timberlake.

I put his new album on repeat eleven or twelve hours ago and starting working.

I realized people might be looking at my GitHub and realized I was embarrassed of the way this blog worked. In the few months from the last update, I learned a lot. I hope I’ll be embarrassed of this in a few months.

Heck I already kind of am.1

The first several posts I wrote for this blog were, naturally, about this blog and the process of building it and excitement of discovery. A lot of it is really dumb but I’m leaving it.

So here’s what’s new:

  1. or will be in the morning, anyway 

  2. and now I’ve just made it so the return button makes the source from within the blog wiggle, too. I want to learn to write my own CSS3 animations. Right now I’m leaning heavily on Dan Eden

Note: I don't have comments or analytics on this website, so it's hard to tell if people are reading or enjoying it. Please feel free to share any feedback or thoughts by shooting me an email or tagging me in a post on Mastodon @maxjacobson@mastodon.online.