Programming Articles
At the beginning of April 2013, MWRC ensued in Salt Lake City, Utah. I rolled the dice and submitted a talk, not thinking that they'd pick it. Announcements started rolling out on the twitter, and boom, there it was. Speaking at MWRC 2013: @darkhelmetlive on "Ruby Batteries Included". mtnwestrubyconf.org/2013/ruby-sess…— MtnWest RubyConf (@mwrc) January 24, 2013 Well, the conference came and went, and I had a great time. Lots of great speakers, …
Yesterday I did a talk at Mountain West Ruby Conf 2013 all about the Ruby Standard Library. The basic premise is you should be looking to the standard library first, before running to RubyGems.org and GitHub for new code. If all you need is a hammer, you don't need to buy the hardware store. Where are the docs? The problem is that sometimes, the standard library doesn't have the documentation you might want. Maybe it's not that great of an examp…
Mutation testing isn't about testing your code, but about improving your tests. What happens is the testing tool looks through your source code for instances of some known thing. This usually something easily tweaked, like ==. For each instance, it changes it to some opposite value that makes sense. In the case of ==, we can change it to !=. For each single change it makes, it runs the tests. The idea is that the tests should fail. If they don't…
Oh look, a post on ruby concurrency. LOLZ THREADS. Anyway, let's get past the lolz about ruby and threads and just run this on JRuby okay? Celluloid Celluloid is a ruby library to make concurrency easy. It gives you a nice object oriented interface to the concurrent patterns it provides. We're going to look at two specific interfaces: Actors and Futures. Before we begin, let me say I love Celluloid. I'm just doing this to see how much basic func…
I had this conversation on Twitter yesterday. That's fine. 37Signals is known for saying no to things in the interest of a better product. A migrator for BCX isn't exactly something that would add enough value to the product to warrant spending their time on it. It's cool. Don't worry, I got this I built one. It only took a couple hours to throw together and clean up. It's super basic, but it did the job for me. It handles todolists with their t…
I gave a lightning talk at RubyConf 2012 in Denver. Man was I nervous. Apparently I did an okay job though, and I'd like to thank all the people who were and took time out of their day to listen to me. Thanks! If you want to view the original talk, the video is here. Scroll to 10:15 to find me, but I recommend watching them all. A few people had more questions (I talked really fast since it was a lightning talk after all) and this was originally…
Last week I wrapped up the chapter on the crypto package in Go, The Standard Library Within the crypto package we have the crypto/subtle package. This package contains functions for doing constant time operations which are an important part of cryptography. Constant time functions help prevent timing attacks which are caused when operations take different amounts of time to complete a task based on some input. When the time something takes leaks…
I was working on my twitterstream package the other day and got thinking. When do you make a new type? When don't you make a new type? Type System Basics If you use a programming without a strong static type system, you probably don't have much to worry about. In ruby and python for example, it doesn't really care about what you pass a method or function, as long as it has whatever methods you expect it to have. This is called duck typing The Go…
I scratched my own itch. I made twitterstream I was working on a little script to pull some images from Twitter, and wasn't happy with what was out there. The ruby gems available were throwing random exceptions or just pulled the JSON down into a hash. I'm all about the Go programming language lately, so I started working in Go instead. There were two libraries available, both named twitterstream, but neither worked the way I liked. Both use oat…
Go 1.0.2 was released late last night. It's a bunch of bug fixes, including some nasty ones with hashes. It's completely backwards compatible with go1.0.1 and go1, so there's no reason not to update: cd $GOROOT hg pull hg update -r go1.0.2 cd src ./all.bash And you're done! You'll probably have to update some packages along the way. It will complain about how it was expecting a package for go1 or go1.0.1, which just means you need to recompile. …
Maybe Heroku changed something, or maybe it's the new Cedar stack, but using private gems from Github is pretty easy. It apparently didn't work before. The important part is in your ~/.ssh/config Host heroku.com ForwardAgent yes After that it's no big deal. Just use an ssh URL to Github (or wherever, the Github part doesn't really matter) in your Gemfile and off you go! source :rubygems ruby '1.9.3' gem 'sinatra', :git => 'git@github.com:darkhel…
Ruby 1.9 has 4 different ways to deal with closures. Cue music Proc Procs are the weird ones of the bunch. Technically, all of these things I'm going to describe are Procs. By that I mean, if you check the class, it's a Proc. A Proc is made by using Proc.new and passing a block, Proc.new { |x| x }, or by using the proc keyword, proc { |x| x }. A return from inside exits completely out of the method enclosing the Proc. A Proc doesn't care about t…
I was bored last night, so I hacked this up. My original thought was since riak has an HTTP interface, I could just proxy GET requests to it when a short URL was used, but either I was doing it wrong or you can't set the Location header when you POST documents. Oh well. Anyway, this uses riak just to store the URL, and the riak key as the short URL key. There is no error checking, UI, or anything fancy. It's pretty much the simplest thing that c…
I've been doing a lot of Go programming lately, and it's good stuff. Go is a fairly new programming language coming out of Google from the minds of some really smart people, like Rob Pike and Russ Cox (among others). It's a C family language, so it has curly braces, has simple yet advanced concurrency features, and garbage collection. It's both high and low level, and was originally billed as a systems programming language. Now though, it seems …
Here's something I cooked up this evening. Nothing too epic, but it's a neat illustration of metaprogramming with ruby. Ruby allows you to reopen classes and add methods to them. You can also make a Module and include that in a class to add methods. I've added four methods to the Symbol class and overridden one method in the Array class (using alias to keep the old method around since super doesn't quite work). Now we can pipe arrays like bash u…
Your software has bugs. Deal with it. To fix these bugs, I prefer the rubber duck debugging technique. Well, maybe prefer is too strong a word, but it’s definitely the first stop. Rubber duck debugging is when you have a bug, and can’t yet see what the problem is. You get a rubber duck, put it next to your monitor, and explain the problem you’re having. In the process of explaining the bug, you realize the root problem and are able to fix it. It…
Kindlebility is now Tinderizer TL;DR Kindlebility sends articles on the web to your Kindle. It needs your Kindle email address (@free.kindle.com addresses are fine). I don’t store your Kindle address or use it for anything else. Use Kindlebility to make a bookmarklet. Add kindle@darkhelmetlive.com to your Kindle Approved Email List. Click the bookmarklet on a page to send the article to your Kindle. Moving on I’ve been meaning to write some more…
I was doing some optimizing the other day on a Rails 2.3.x application with a metal controller. I didn't feel like writing a straight rack application, so I used sinatra. A pretty good explanation of how this works can be seen in Adam Wiggins' slides: Rails Metal, Rack, and Sinatra from Adam Wiggins In Rails 3, they still have metal controllers, in that the ActionController::Metal class is essentially a really thin controller, and you can use it…
I don’t know if you know this, but everybody and their dog is writing node.js applications. It’s more popular than Kanye memes. It’s a contagious bug, and I caught it too. I had a one specific use case that it was perfect for, since a Javascript library already existed to do it. Another idea came later, and that’s the one that started it for me. So let’s get on with that. shortestpaper This was the one I started on. The basic problem was that mo…
It's 10 minutes past 6 on Sunday evening, and we just wrapped up our Rails Rumble 2010 project. Check it out at http://gemrage.com/. Check out our team here too. This. Shit. Was. Real. We had a rough start with lack of internet for 3 hours, had a few depressing times thinking we'd never finish, but we rocked our socks off with Windows and Internet Explorer, MacBooks, Twitter and Campfire, and produced a pretty cool application. Please go check o…
Embedly is a great service for generic embedding of content. Have you seen posterous? How they can just accept any link to a video on youtube, a picture on flickr, whatever, and it gets properly embedded? I imagine they could use Embedly to accomplish that. Anyway. They have a jQuery script to do embedding, but in the middle of if is this behemoth of a code smell: Oh noes a global variable! The implication of this is that you can only run one ca…
So you missed Twitter for a day? Have a long list of updates along the lines of "OMG this ice cream is fantastic!" to sort through? Fear no more, for I have the solution. Well. If you're using Chrome. I made a little Chrome extension that filters out tweets that have no actual links in them. Actual links are 'web' links, not links to user profiles or hashtags. Tweets are interesting and all, and if you are keeping up with them, a few about rando…
It's been a while, but we're continuing the Top 25 Most Dangerous Software Errors with numbers 10-6. 10. Missing Encryption of Sensitive Data Have you ever signed up for some website or service, only to receive an email 30 seconds later WITH YOUR PASSWORD IN IT! Doesn't it just fucking kill you? Have you ever used a 'Forgot your password' page only to be blindly given your password? Fantastic. I highly doubt they are doing any encryption with yo…
Let's get some background information out of the way. I'm working on a new application, and am using crazy new things that I haven't had a chance to really use before. Rails 3, MongoDB, Redis and Resque, HTML5, etc. 1 With all these things, I figured I'll just use EngineYard since I can pretty much do whatever I want with the server, and they have a lot of the "stuff" taken care of. But they don't support MongoDB out of the box, and you have to …
A copy merge is basically where you take all of their changes. Say you're in branch A and want to merge in branch B. Their might be conflicts, but you don't care, as you want whatever is in branch B. Almost as if you are copying from B to A. Since you are in branch A, it is referred to as ours. Branch B is referred to as theirs. In git land, you can do this, assuming you are in branch A: git merge -s recursive --strategy-option theirs B This wil…
It's been a while, but I've been busy pwning n00bs at Modern Warfare 2 and Bad Company 2, and buying a car, so life has been pretty busy as of late. Have no fear though! I continue the look at the Top 25 Most Dangerous Programming Errors with numbers 15 to 11. 15. Improper Check for Unusual or Exceptional Conditions When you ASSUME things, you make an ASS out of U and ME. This is all about assumptions. You assume something will work, you assume …
Rails developers aren't exactly known for getting their indexes right (or even at all) on their databases. Granted, databases are a tough subject, and some people and companies make their living dealing with only databases, and some only with one database (like MySQL or Oracle). If you're coming to web development with no formal background in databases, and it's all new to you, then it's totally understandable to maybe forget about indexes initi…
I continue the look at 5 more of the Top 25 Most Dangerous Programming Errors. Here's part 1 (25-21) 20. Download of Code Without Integrity Check You might not think of this at first, but it's a doozy. If you are downloading things, like files, code, updates, whatever, they could be compromised. DNS poisoning or redirects could make your request for a file go to a different location. There could be a man in the middle messing with your data, or …
The Common Weakness Enumeration posted their Top 25 Most Dangerous Programming Errors last month. Most everything in the list is completely avoidable, but most new programmers, and especially those without real world experience (as opposed to trivial classroom projects), fall victim to at least some of them. A lot of them bit me in university and I still get nipped by some of them today. Proper education is the first step, and the CWE have done …
A quick post for today. Want to get rid of transactions from ActiveRecord for something? Here's a cheap way to do it. It only works for MySQL obviously, but you can roll your own if you are on postgres. I'll make it a bit less crappy and make it a gem or something.
If you are processing a bunch of data, grouping it, joining it, filtering it, then you should probably be using pig. So go download that, and get it all setup. You need: Java 1.6 (with JAVA_HOME setup) Hadoop (with HADOOP_HOME setup) pig (of course) Put all the relevant stuff in your PATH too. pig 101 So here's a simple pig script. This registers a jar file and defines a custom UDF(User Defined Function) for doing whatever. It happens to be a lo…
This post is part 2 in the Super MongoDB MapReduce Max Out! series. Read Part 1 Now, from the last post, you might still be wondering what's the whole point behind this MapReduce stuff? What can you really do with it? Well hold on, I'm going to tell you. But first, some back story. History lesson So I work at CodeBaby and we sell CodeBaby Characters and CodeBaby Conversations to live on your website and bring some emotion to a static page. In or…
I've been playing with MongoDB lately, and I must say, it's the shit. In case you haven't heard of MongoDB, let's drop some buzz words: Document oriented Dynamic queries Index support Replication support Query profiling MapReduce Auto sharding There are some more things, so check out their website for the full meal deal. I'm going to talk about the MapReduce part of things. MapReduce The idea behind MapReduce has been around for a while; since t…
jQuery is pretty much the gold standard for Javascript goodness, at least in my opinion. I use it for everything, and you should too. Jaml has only been around since October but it's already pretty damn awesome. Combining these two powers like peanut butter and jelly results in awesome. Jaml Jaml is a templating engine for Javascript based loosely on Haml. It lets you write code like this: So you can call this: Jaml.render('simple'); To output t…
I recently added a Javascript file to my bundle with sinatra-bundles that uses Javascript's eval functionality. The call to eval executed code that referenced a method parameter. sinatra-bundles compresses Javascript files, and as part of that, shrinks variable names. Normally this isn't a problem, but in this case of eval, it became a problem, since it was trying to reference a local variable that no longer existed (because it got shrunk to som…
AJAX requests are a grand thing. They let you request things from your server without refreshing the page. Now, if you are trying to proxy a page, you can rewrite all the links in the page to point back through your proxy, but AJAX requests are another thing. Oh wait no they're not! You can't rewrite them when you proxy the page (by proxy, I mean you request my page with a URL param to another page, and I pull in that page, do some stuff, and se…
It occurred to me the other day, that I should take a look at the middleware I use on this blog. I don't know what it was. My spidey senses just tingled. Boy was I right. I totally had it backwards. Rack middleware is a fantastic thing. It's like a little encapsulated rack application that you can use to filter, process, or otherwise mess with responses. There is middleware to add etags, configure caching, catch and log exceptions, deal with coo…
The nth-child pseudo selector is a nice feature in CSS3. Well, most of the things in CSS3 are pretty sweet. Chris Wanstrath has a good post on the nth-child selector, and I'd suggest reading it for a bit more in depth on what the nth-child selector actually does, as I just cover getting the same effect in all browsers. Unfortunately, while Internet Explorer does support some of the CSS3 stuff, it doesn't support a bunch of them.aspx) either. (Di…
sinatra-bundles is an easy way to bundle CSS and Javascript assets in your sinatra application. Yes! It has tests! They are on runcoderun Usage sinatra-bundles combines Javascript and CSS into one file. Meaning, you can bundle 2 or more Javascript files into one, similar with CSS stylesheets. Any bundled files are expected to be in the public directory, under 'javascripts' and 'stylesheets' Assuming you have the following files in public: ./styl…
I used to have some really ugly code to generate the archive links you see on the right column of this blog. It was terrible. Granted it was some of the first code I wrote on this blog, and I was cruising through it because I just wanted to get it done and working, but still, it's not really a valid excuse. It can be seen here. I had a thought the other day that it would be much better handled by the Range class, and boy was I right, although it…
I use swfobject to embed videos because, as I explained back here, just blindly copying the embed code doesn't work that well half the time, and videos end up being different sizes, etc. I was getting kind of fed up with having to go back and remember how to do it every time though. The format is pretty straightforward, but I don't embed videos often enough to actually remember the exact syntax, so I found myself going back to posts with videos …
The folks at Thoughtbot have a Ruby community survey online, and you should all go take it. Well, as long as you are a ruby developer. Otherwise it doesn't really matter. Anyway, I wanted to throw out what I do for ruby style (and general programming style in some cases). I hate the 80 character limit. Get a real monitor would you please? I don't align assignment operators. I don't indent private/protected keywords. I keep the code after private…
Hopefully you didn't notice much, except the speed increase, but my blog is no longer on the behemoth that is Wordpress. While Wordpress served me well for quite some time on my other blog it always kind of bugged me. Well no more! I took a couple days (basically 2 full days and 2 evenings) and wrote my own little blogging engine from scratch. You can find it on github and get forking if you so choose. What I used: ruby and sinatra They are pret…
tmm1 and joedamato put up a good slide show on slideshare about ruby threading issues, and their fixes. These things have been around for a while, but now they are here in slideshow form. Definitely check them out, even if you don't program ruby, as there are some interesting profiling/debugging shenanigans shown, among other things. Threaded Awesome from Aman Gupta
So check this: you have a nice little Rails app. You have some stuff for a JSON API type system. You've got an STI setup with the Widget model class and the more concrete FancyWidget and WeirdWidget classes. You've got a WidgetsController, and the corresponding FancyWidgetsController and WeirdWidgetsController Yay. It works. You can deal with both types of Widgets using JSON. Now you need an HTML interface to it. Fine, you can just throw in a fo…
Robert Martin's "What Killed Smalltalk Could Kill Ruby, Too" talk at RailsConf 2009. RailsConf 09: Robert Martin, What Killed Smalltalk Could Kill Ruby, Too
I needed jQuery to fadeout an item after a certain timeout, and I found it odd that I couldn't find a native jQuery way to do it. Whatever. jQuery is so awesome that it doesn't matter, because here's what I came up with. EDIT 28-Nov-2009 In retrospect, all I wanted was a jQuery like syntax, but leveraging jQuery to do the timeout is sort of wrong. After all, Javascript does have a setTimeout function. I must have been in a jQuery must do all of …
I looked at a few role systems for Rails, but never found what I wanted. They were all object based systems, never just "allow a user with this role to do this action". Either that or I never found the systems that did that, or totally missed the docs on how to configure those systems to do what I wanted. Well, actually acl9 seemed to do that, but whatever. So I made role_on The instructions are on Github, so I won't repeat them here, but it's p…
Picture this: You are reading some tutorial or whatever, and you need to install some things. So you run 'aptitude install prog1 prog2'. Then you realize you need prog3 and 4 too, so you CTRL+C that, and run 'aptitude install prog1 prog2 prog3 prog4'. Then you see you need something else. Rinse and repeat. This is really annoying. The worst part is you can't run multiple aptitude instances, because they'll whine about file locks or something. I …
(See (remote-inline)Part 1) And we're back! So, just take a look up below the title…see that little link? Yeah go ahead and click that. If I did my job right (tested in Safari on Windows, Chrome, FF), the contents for Part 1 should slide in above this post. In this post, since I use the Textile 2 plugin, I add this snippet at the top: (See [(remote-inline)Part 1](/2009/07/08/wordpress-multipart-posts-inlined-with-jquery-part-1)) In textile land,…
This is the first of a multipart post. I'll be the first to admit, after you read this, and part 2, ignoring the context and concentrating on the actually content, you'd wonder why, but it makes sense when it's all together. So I've seen many multipart posts out there, do this today, tomorrow do this, and every time, in order to view them all together, you, um, can't. You have to have multiple tabs open and read one, then read the next, flipping…
I needed to compile LLVM from scratch since the llvmruby gem needs it compiled with position independent code and the repo version doesn't seem to be, the gem whines compiling, etc, etc. The docs for LLVM don't seem to be that great when it comes to compiling this stuff from scratch, so here's what I did, as one big script chunk. You can probably copy and paste this, but I make no promises that it will work, only that it Works on My Machine. And…
I'm writing up some scripts to automate some EC2 setup, and SSH is required. All the examples for Net::SSH show using just a username and password, which is all good, but the Amazon stuff requires a key file. Here's how to do it: Net::SSH.start('my.amazon.hostname.amazonaws.com', 'user', :keys => '/path/to/keypair.pem') { |ssh| … } According to the docs, the :keys named param takes an array of file names of private keys to use for publickey and …
I found this little snippet on stackoverflow This is a strange way to do it, but if you format the date to yyyymmdd and subtract the date of birth from the current date then drop the last 4 digits you've got the age :) I don't know C#, but i believe this will work in any language. 20080814 - 19800703 = 280111 drop the last 4 digits = 28 All credit goes to ScArcher2 This is just a great little snippet of code, and as an upside, dates in that form…
I like frameworks, but sometimes debugging them is more entertaining. I don't know why I didn't think of this method before, but mischa on github has a great little repo showing how you can do it. The README Usage: Add: require 'ruby-debug' require 'cucumber_rails_debug/steps' To features/support/env.rb Then use: Then debug # opens the debugger or Then what # prints out params, url and html Check it out here
Selenium is a suite of tools to automate web app testing across many platforms. Cucumber is a BDD framework that allows you to write things in English (or whatever language you want, really), and have that execute as code. Put those together with webrat and rspec and you have a pretty mean stack to test your ruby on rails web application with. Sort of. I've been having some problems with it, getting it set up, but it's coming along. This isn't a…
Regex are always fun, and since regex expressions are first class citizens in ruby, it makes it so much easier. I found this Code Golf question on Stackoverflow and threw together a quick method to do it. I can't take all the credit, since I needed to search a bit to figure out if I could do matching parenthesis in ruby, and found that I could, but only in ruby 1.9, which ruby forum topic showed me. Then a commenter on SO pointed out another opt…
In one of my classes, we used Ruby and Gtk, but some issues popped up. The most obvious is using a block to do GUI update stuff and the like, from another thread. Things die. Puppies are killed. I found this post on Ruby Forum which fixed the problem. Relevant code. Basically, you call the Gtk.init_thread_protect method first when you start things up, then, whenever you need to do GUI update stuff, just wrap it in a Gtk.thread_protect {} block. …
In case you just crawled out from under your rock just to read my blog, and haven't the foggiest, cucumber is a ruby acceptance testing framework, and works great with rails. I was writing features for admin users in this application, and needed a step like this: Then I should be editing "test@example.com" Where the quoted email is the login. Later on (in fact right after…I was testing edit functionality, and after safe you end up on the view us…
The ruby-openid gem was giving me problems with Passenger, causing IOError problems. I found the fix here The gist of it? Add OpenID::Util.logger = RAILS_DEFAULT_LOGGER to environment.rb, and you're good!
Sometimes, checking RSS feeds is boring. Sometimes you just want to grab a picture or whatever from each item. For that, there's ruby. Oh and feedzirra. There is an RSS feed I read, except it's more of a picture feed and I just want to grab the pictures from it, and doing this through Google Reader is no fun. That's where ruby and feedzirra come in. feedzirra is a ruby gem for dealing with RSS feeds. It's got a great interface and just works. So…
If you go download the ruby-gnome stuff, and GTK fails to compile, it's easy to fix. It whines about some defines, and you can just comment out the block that's causing the problem.
Create a branch locally, and push it to origin: git checkout -b branchname git push origin branchname Get at that branch from elsewhere: git checkout -t -b branchname origin/branchname
I keep coming back to asking myself what the difference between stub and mock objects are and I have it figured out, so here it is: Stubs just return whatever you tell them do, and that's it. Mocks have expectations and cause tests to fail if those expectations aren't met.
I almost threw my laptop out the window figuring this out, but if you want to install ruby 1.9.1 alongside ruby 1.8.7 (whether the prefix is the same or not), you have to give ruby 1.9 a program suffix, but also a baseruby. So you need something like this: ./configure --prefix=$HOME/local --program-suffix=1.9 --with-baseruby=ruby --enable-pthread
I always find myself needing this but never remember. -fverbose-asm Throw that at gcc when you are outputting asm (-S flag) and you'll get some useful comments to see what some of the code is actually working on.
I wrote this a while ago on my old blog, so I'm just reposting here. It's useful since you can have an enum of error codes, which also, when converted to human readable text, are useful messages. Here's how I did it.
The good thing about design pattern writings is that they never really go out of date. Hence this link. It actually doesn't have a date, but I found it a long time ago. Anyway, here it is. Use them already! Design Patterns
I found this a long time ago (in a galaxy far, far, away), and it's still up and still good. If you want to learn python, fly through this article and you should be good. Learn Python in 10 minutes
Code Project is a great resource for developers. I use it, have projects bookmarked, read the newsletter, and got the T-shirt (okay that's a lie…just the underwear). This makes it even better. You can search Code Project by doing little more than highlighting or copy/pasting code, typing in a few words, and blamo!, there you have it. it uses Live Search for MSDN and the intertubes, which I'm not overly keen on, but if I want to really search my …
I found this slick little app a few years ago, and it looks like it's still around. Count your VC# and VC+ lines, and it differentiates between code lines, blank lines, designer lines, etc, which is nice. The downside: it's really only useful for VC# and VC+ projects, which is alright if that's all you are working with. Check it out. C#, Visual Basic and C++ .NET Line Count Utility - The Code Project - .NET PS. You'll note that I didn't mention …
Oh me, oh my. When I first posted about this, in June of 2007, my original post started with Ruby is sweet. I should use it more often. And now, on Monday, I get to start my new job playing with Rails all day long. Funny how things change. Regardless, the quality of this tutorial hasn't changed, so here it is again. Rails Envy: Ruby on Rails Rake Tutorial
I had to do auto increment in Oracle a while back and it was painful. It ended up happening, but not in the nice MySQL way. Whatever, it worked. This site has a few tricks. Autoincrement primary key for Oracle
If, like me, you participate in some sort of grid computing project, it's interesting to see your progress. I take part in Einstein@Home, and I wanted to display my stats in my sidebar (on my other blog). I'll give you two ways to accomplish this. First way is the quick way, which involves including the jQuery Javascript library, and a second which involves writing your own Javascript. The second option results in a smaller file, but the jQuery …
I still haven't used this, mainly just because I haven't had the need. I'm still convinced it's the greatest thing ever though. BugTrap
I'm so lazy! Almost two years ago I said I'd check out PARUS, and it never happened. Well now I'm more organized and can put it on my Tracks todo list. I'll get to it. Probably not this weekend, but eventually. PARUS
Full Archive
|
By Category
|
By Month