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:
- a
config.rb
file for helper methods that get the blog title and subtitle- so nothing in the main app file,
web.rb
is hardcoded and theoretically someone else could use this
- so nothing in the main app file,
- permalinks based on the file name
- option to see the markdown source of any page with a little link at the bottom. (alternately just add the
.md
to any page) - some small amount of style, mainly to do with displaying codeblocks
- incidentally, I’m treating markdown source as “code”
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:
- syntax highlighting for code blocks, using my fav colorscheme, cobalt
- switched from erb to haml – now writing far less HTML by hand
- appending
.md
to posts or pages takes you to a text file instead of embedding within a page, which displayed poorly (missing underscores for some reason) - some (goofy?) animations on page loads. It picks randomly from a list
- oh, and when you click to see a footnote, the right one will wiggle. see? 2
- much better config file; in case anyone besides me uses this system, it should be relatively easy for them to plug in their info and start blogging