<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>plainlystated</title><link>https://plainlystated.com/</link><description>Recent content on plainlystated</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sat, 29 Mar 2014 00:00:00 +0000</lastBuildDate><atom:link href="https://plainlystated.com/index.xml" rel="self" type="application/rss+xml"/><item><title>TorVM for QubesOS</title><link>https://plainlystated.com/2014/torvm-for-qubesos/</link><pubDate>Sat, 29 Mar 2014 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2014/torvm-for-qubesos/</guid><description>&lt;p&gt;&lt;a href="qubes-torvm-arch6.png"&gt;&lt;img src="qubes-torvm-arch6.png" alt="qubes-torvm-arch"&gt;&lt;/a&gt;I&amp;rsquo;ve been using &lt;a href="https://qubes-os.org/trac" title="QubesOS" data-external rel="noopener" target="_blank"&gt;QubesOS&lt;/a&gt; (a xen/fedora distribution focused heavily on security by isolation) for a couple weeks now, and I&amp;rsquo;ve been really enjoying it. There are plenty of rough egdes when it comes to user-friendliess (granted, I&amp;rsquo;m on a beta release), but I&amp;rsquo;ve been able to get some pretty cool stuff working. Probably the coolest is having an independent VM which acts as a proxy and transparently makes all my (TCP) traffic go through the TOR network.&lt;/p&gt;</description></item><item><title>Creating a VM using KVM &amp; Proxmox</title><link>https://plainlystated.com/2014/creating-a-vm-kvm-proxmox/</link><pubDate>Sat, 01 Mar 2014 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2014/creating-a-vm-kvm-proxmox/</guid><description>&lt;p&gt;The next virtualization strategy I&amp;rsquo;m testing out is KVM. I&amp;rsquo;m using Proxmox as the management layer (similar to how I used XenServer on top of Xen), and this provides a nice API, command-line interface, and web-based GUI. Proxmox also makes it easy to do common tasks like pool servers and live migrations. To start, the first task is to automate getting a VM running.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Xen and KVM&lt;/strong&gt; KVM (Kernel Virtual Machine) is similar to Xen in that they&amp;rsquo;re both hypervisors (and in fact, both are &amp;ldquo;Type 1&amp;rdquo; hypervisors). They both allow you to partition off some disk space and plop an isolated virtual machine on it. They both manage CPU, IO, power, and memory for their virtual machines, and they both promise isolation and security. They differ, though, in how they perform these tasks, and that&amp;rsquo;s what I&amp;rsquo;ll be exploring in the next few posts.&lt;/p&gt;</description></item><item><title>XenServer Recap</title><link>https://plainlystated.com/2014/xenserver-recap/</link><pubDate>Sat, 22 Feb 2014 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2014/xenserver-recap/</guid><description>&lt;p&gt;Having spent a week playing with various features of XenServer (with a focus on automation), I&amp;rsquo;ve only scratched the surface of what it can do. I have a sense, though, for the power of the system, and what it would take to get it to work at my company. It has all the features that we need to start, some nice-to-have features that we&amp;rsquo;ll probably use, and then extras beyond that which we probably won&amp;rsquo;t play with for the foreseeable future.&lt;/p&gt;</description></item><item><title>Xen Workflow - Migrating a VM</title><link>https://plainlystated.com/2014/xen-workflow-migrating-a-vm/</link><pubDate>Sun, 09 Feb 2014 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2014/xen-workflow-migrating-a-vm/</guid><description>&lt;p&gt;One of the great features of a hypervisor management suite like XenServer is the ability to migrate a running VM from one physical host to another without affecting running services on that VM. This allows you to balance VMs appropriately across your hypervisors, as well as evacuate a hypervisor so it&amp;rsquo;s safe to perform maintenance. Doing this migration through the GUI gives you a step-by-step wizard to help set up appropriate options. For my needs, though, it&amp;rsquo;s got to be automated via the API.&lt;/p&gt;</description></item><item><title>Xen Workflow - Creating a Pool</title><link>https://plainlystated.com/2014/xen-workflow-creating-a-pool/</link><pubDate>Wed, 05 Feb 2014 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2014/xen-workflow-creating-a-pool/</guid><description>&lt;p&gt;Using Xen pools, you open the door to a lot of cool features, including high availability of VMs, migration of running VNs, and automatic placement of machines. Setting up the pool is pretty easy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prereq&lt;/strong&gt; There are some requirements/recommendations for pool servers listed in the &lt;a href="http://docs.vmd.citrix.com/XenServer/6.0.0/1.0/en_gb/reference.html#pool_creation" data-external rel="noopener" target="_blank"&gt;XenServer docs&lt;/a&gt;. For me, I&amp;rsquo;m using identical hardware, so the only weird thing I had to do was to unbond my private network interface on the server that&amp;rsquo;s going to be a slave. I&amp;rsquo;m not sure why this is a requirement, but it&amp;rsquo;s not a big deal since joining a pool will cause the slave to inherit the master&amp;rsquo;s networking configs (which will set bonding up again).&lt;/p&gt;</description></item><item><title>Xen Workflow - Copy VMs</title><link>https://plainlystated.com/2014/xen-workflow-copy-vms/</link><pubDate>Tue, 04 Feb 2014 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2014/xen-workflow-copy-vms/</guid><description>&lt;p&gt;Creating VMs from scratch in XenServer is a bit of a hassle, but that&amp;rsquo;s OK because it&amp;rsquo;s not a frequent task. Typically you&amp;rsquo;d create one (or a few) base templates, and then make copies whenever you want to spin up a new disk. This process is very simple and straightforward in XenServer, and easily automated.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prep&lt;/strong&gt; Using the method described in &lt;a href="https://plainlystated.com/2014/xenserver-create-a-vm-from-an-iso/" title="How to create a VM in XenServer"&gt;my last post&lt;/a&gt;, create a basic install of your chosen linux variety (the same process works for Windows, but there is an extra step). Once you have the base system installed shut it down. It&amp;rsquo;s now ready to be cloned.&lt;/p&gt;</description></item><item><title>XenServer - Create a VM from an ISO</title><link>https://plainlystated.com/2014/xenserver-create-a-vm-from-an-iso/</link><pubDate>Mon, 03 Feb 2014 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2014/xenserver-create-a-vm-from-an-iso/</guid><description>&lt;p&gt;When creating a new virtual machine in XenServer, the typical path is to clone a pre-built template of the type of linux/Windows you want to install, and add a network repository from which it can grab its packages. While this works well for popular OSes, it doesn&amp;rsquo;t help when you want to install something. To work through the manual process of installing something custom, I got Vyatta setup using a blank template and a downloaded ISO.&lt;/p&gt;</description></item><item><title>Xencap - Xen Management Library for Capistrano</title><link>https://plainlystated.com/2014/xencap-xen-management-library-for-capistrano/</link><pubDate>Sun, 02 Feb 2014 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2014/xencap-xen-management-library-for-capistrano/</guid><description>&lt;p&gt;I&amp;rsquo;m starting to dive into choosing from a variety of server virtualization options for work in order to determine which solution to roll into our environments. First up is &lt;a href="http://www.xenserver.org/" data-external rel="noopener" target="_blank"&gt;XenServer&lt;/a&gt;, with which I&amp;rsquo;ll stand up a pool of a couple machines and test out provisioning new servers, live migration, network isolation, and other cool features. While these tasks are more straightforward using the GUI (official GUI is Windows-only, but there are alternatives), I&amp;rsquo;m spiking out tooling that does as much as possible via the API (since we&amp;rsquo;ll want to automate it).&lt;/p&gt;</description></item><item><title>Virtualization Options</title><link>https://plainlystated.com/2014/virtualization-options/</link><pubDate>Sat, 01 Feb 2014 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2014/virtualization-options/</guid><description>&lt;p&gt;At my job, we have quite a few servers, all on dedicated hardware. Most of our servers relate directly to storing data on disk, and so physical hardware makes sense. For the scores of random, smallish servers, though, physical hardware is overkill. To help manage this inefficiency, we&amp;rsquo;re looking at various virtualization options, including XenServer, KVM, and containers/jails/zones.&lt;/p&gt;
&lt;p&gt;To tackle this project, I&amp;rsquo;ll spike out simple implementations in a few different tools, and get a feel for the setup and management requirements. One important requirement is that whatever we choose must have a decent set of tools for automating tasks, because we want things to be as hands-off as possible. Other features I&amp;rsquo;m looking for include:&lt;/p&gt;</description></item><item><title>Concept to Finished Piece - Generations of an Electronics Project</title><link>https://plainlystated.com/2013/concept-to-finished-piece-generations-of-an-electronics-project/</link><pubDate>Fri, 07 Jun 2013 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2013/concept-to-finished-piece-generations-of-an-electronics-project/</guid><description>&lt;p&gt;&lt;a href="telegraph-sounder-wire.jpg"&gt;&lt;img src="telegraph-sounder-wire.jpg" alt="Finished Product"&gt;&lt;/a&gt;I bought an &lt;a href="https://plainlystated.com/2011/communique-from-1863/" title="Telegraph Sounder"&gt;antique telegraph sounder&lt;/a&gt; a while back, and I&amp;rsquo;ve been working on a project that will click out emails from my Etsy store when I get an order. I&amp;rsquo;ve gone through several generations, and come up with something I really like. What follows is a description of my process for going from concept to finished piece. The code &amp;amp; PCB are open-source, and can be found on &lt;a href="https://github.com/plainlystated/email_to_telegraph" title="The code on github" data-external rel="noopener" target="_blank"&gt;my github&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Raspberry Pi Serial Console</title><link>https://plainlystated.com/2013/raspberry-pi-serial-console/</link><pubDate>Sat, 01 Jun 2013 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2013/raspberry-pi-serial-console/</guid><description>&lt;p&gt;When setting up a new &lt;a href="https://www.raspberrypi.org/" title="Raspberry Pi" data-external rel="noopener" target="_blank"&gt;Raspberry Pi&lt;/a&gt;, it&amp;rsquo;s helpful to have console access, which could mean hooking up a screen and keyboard to the pi. Another option is to connect your pi to your computer with a USB cable, and connect to the serial console (similar to connecting via SSH or telnet). You need a special cable, but it saves you from having to keep a monitor and keyboard just for the pi.&lt;/p&gt;</description></item><item><title>Architectural Primitives: Inter-Datacenter Tunnels</title><link>https://plainlystated.com/2013/architectural-primitives-inter-datacenter-tunnels/</link><pubDate>Tue, 14 May 2013 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2013/architectural-primitives-inter-datacenter-tunnels/</guid><description>&lt;p&gt;&lt;a href="tunneling-small.png"&gt;&lt;img src="tunneling-small.png" alt="tunneling-small"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At &lt;a href="https://tempo-db.com/" title="TempoDB" data-external rel="noopener" target="_blank"&gt;TempoDB&lt;/a&gt;, we maintain multiple environments (production, staging, etc), and each environment is in a datacenter (Dallas, Seattle, etc). For the most part, we want strict separation between environments, but we have a growing list of traffic that ought to be allowed to flow between them (see below). We designed a new architectural primitive which allows us to securely permit some traffic, while still blocking everything else.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Business Objectives&lt;/strong&gt; Right now, each environment (production/staging) is in one datacenter (Dallas/Seattle). What we developed allows us to connect two datacenters, which means that one environment can span multiple datacenters (intra-environment tunnel) or that two datacenters from different environments can be connected (inter-environment tunnel; eg a connection between production and staging). This allows features such as:&lt;/p&gt;</description></item><item><title>XCP (Xen) on a Mac Mini</title><link>https://plainlystated.com/2013/xcp-xen-on-a-mac-mini/</link><pubDate>Sun, 07 Apr 2013 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2013/xcp-xen-on-a-mac-mini/</guid><description>&lt;p&gt;&lt;img src="e981155158226a81.jpg" alt=""&gt;I picked up a new Mac Mini this Friday to play around with Xen at home. Right now I run a few services off of one server in my apartment, but I&amp;rsquo;d prefer to have separate VMs for each service, because I find that more manageable.&lt;/p&gt;
&lt;p&gt;The platform I&amp;rsquo;m using is &lt;a href="https://web.archive.org/web/20130503002758/http://www.xen.org/products/cloudxen.html" title="XCP" data-external rel="noopener" target="_blank"&gt;XCP&lt;/a&gt; (Xen Cloud Platform; an open-source &lt;a href="http://wiki.xen.org/wiki/XCP/XenServer_Feature_Matrix" title="XCP/XenServer comparison chart" data-external rel="noopener" target="_blank"&gt;alternative&lt;/a&gt; to Citrix XenServer). It requires the whole drive, so dual-booting isn&amp;rsquo;t an option (see note below: Dual Booting), which gave me problems. I could install it just fine (hold down &amp;lsquo;c&amp;rsquo; while booting to boot from CD), but on reboot I would just get a flashing file folder icon with a question mark in the middle. I finally found the solution on the &lt;a href="https://help.ubuntu.com/community/MactelSupportTeam/AppleIntelInstallation" title="Ubuntu on Mac" data-external rel="noopener" target="_blank"&gt;Ubuntu docs site&lt;/a&gt;. After installation is complete, reboot the computer and hold alt/option to get into the recovery partition (it takes a while to download the tool, presumably because they were on the partition that XCP blew away). When you get to the screen showing different options (restore from Time Machine, reinstall OSX, etc), go to Utilities &amp;gt; Terminal (at the top of the screen). Once in a terminal type: &lt;code&gt;bless --device /dev/disk0s1 --setBoot --legacy &lt;/code&gt;. Then reboot (&lt;code&gt;sudo shutdown -r now&lt;/code&gt; if you&amp;rsquo;re still in Terminal), and you should be in XCP.&lt;/p&gt;</description></item><item><title>SSH Honeypots &amp; DataViz</title><link>https://plainlystated.com/2013/ssh-honeypots-dataviz/</link><pubDate>Sat, 16 Feb 2013 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2013/ssh-honeypots-dataviz/</guid><description>&lt;p&gt;&lt;a href="http://www.plainlystated.com/honeypot-globe/" data-external rel="noopener" target="_blank"&gt;&lt;img src="Screen-Shot-2013-02-16-at-6.16.44-PM.png" alt="Honeypot Globe"&gt;&lt;/a&gt;I put up a handful of small servers with SSH honeypots running, and have been watching who tries to break in. I didn&amp;rsquo;t publicize the addresses, or point any DNS at them, but they almost immediately got found by hackers across the globe. Here&amp;rsquo;s &lt;a href="http://www.plainlystated.com/honeypot-globe/" data-external rel="noopener" target="_blank"&gt;a visualization&lt;/a&gt; and analysis of the data so far.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What&amp;rsquo;s a Honeypot?&lt;/strong&gt; A honeypot is a fake service that runs on a standard port, waiting for people to try to break in. There are lots of different kinds, covering different protocols and interaction levels. I&amp;rsquo;m using &lt;a href="http://code.google.com/p/kippo/" data-external rel="noopener" target="_blank"&gt;kippo&lt;/a&gt;, which is a medium-interaction (or &amp;ldquo;research&amp;rdquo;) honeypot. If someone spends enough time guessing, they&amp;rsquo;ll eventually get in, and once in they are in a protected area where all their actions are recorded for future analysis. This yields a treasure trove of data, including patterns of who is trying to break in, how are they going about it, and what do they do if they are successful. For a production environment, honeypots may still be a good idea, but a low-interaction environment would be more appropriate (meaning people can attack it all they want, but will never get into anything).&lt;/p&gt;</description></item><item><title>Bulk Loading Time-Series Data @ TempoDB</title><link>https://plainlystated.com/2013/bulk-loading-time-series-data-tempodb/</link><pubDate>Wed, 09 Jan 2013 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2013/bulk-loading-time-series-data-tempodb/</guid><description>&lt;p&gt;&lt;em&gt;(Cross-posted to &lt;a href="https://web.archive.org/web/20140703012849/http://blog.tempo-db.com" title="blog.tempo-db.com" data-external rel="noopener" target="_blank"&gt;blog.tempo-db.com&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In addition to our REST API and language-specific client libraries, we now offer the ability to bulk import data by uploading CSVs. The intent of this feature is to support the initial load of large amounts of historical data (many millions or billions of data points). By sending us CSVs (instead of just using our API normally), customers save themselves from having to build and monitor a large one-time job, and the problem is simplified to CSV generation.&lt;/p&gt;</description></item><item><title>How Not To Get Sales On Etsy</title><link>https://plainlystated.com/2012/how-not-to-get-sales-on-etsy/</link><pubDate>Sat, 08 Sep 2012 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2012/how-not-to-get-sales-on-etsy/</guid><description>&lt;p&gt;I opened my &lt;a href="https://web.archive.org/web/20230607145059/http://www.etsy.com/shop/PlainlyStated" data-external rel="noopener" target="_blank"&gt;Etsy store&lt;/a&gt; in January (about 9 months ago), and have learned a lot about effectively marketing my store. For the first several months I was trying everything I could think of to increase my visitor count, and I did get a ton of people coming into my store, but the effort required on my part was substantial, and 3 months in I lost interest. That&amp;rsquo;s when things got interesting.&lt;/p&gt;</description></item><item><title>Timewise</title><link>https://plainlystated.com/2012/timewise/</link><pubDate>Tue, 01 May 2012 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2012/timewise/</guid><description>&lt;p&gt;I have two similar data collection projects, both of which collect time-series data and serve it up with graphs and such. The &lt;a href="https://github.com/plainlystated/power_hungry" data-external rel="noopener" target="_blank"&gt;first one I did&lt;/a&gt; uses postgres, and manually (in code, not postgres) manages averaging, data at various resolutions, and a few other complicated issues that are inherent in time-series data. For the &lt;a href="http://hot-or-not.plainlystated.com/" title="Hot Or Not" data-external rel="noopener" target="_blank"&gt;second project&lt;/a&gt;, I went with RRD instead of postgres, and it vastly simplified data management (other than having to write the RRD integration code for javascript myself). Now, I&amp;rsquo;m working on refactoring these projects, because it makes sense to move to the first project over to RRD and then there&amp;rsquo;s no reason to have the graphing bits separate.&lt;/p&gt;</description></item><item><title>Hot Or Not: Back Up, Kind Of</title><link>https://plainlystated.com/2012/hot-or-not-back-up-kind-of/</link><pubDate>Mon, 30 Apr 2012 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2012/hot-or-not-back-up-kind-of/</guid><description>&lt;p&gt;A while back I &lt;a href="https://plainlystated.com/2011/building-a-thermostat-using-arduino/"&gt;built my own thermostat&lt;/a&gt; using an Arduino, nodejs, and Google Calendar. It worked really well, but when I moved to a new apartment last year I couldn&amp;rsquo;t use it (because I now have window units instead of centralized heating/AC). I finally got around to putting it back together this weekend, but I had to rip out the (now unused) thermostat code. What was a Google-Calendar-controlled thermostat is now just a thermometer. Not nearly as cool, but I&amp;rsquo;m at least glad to have the portion that makes sense back up. You can see it &lt;a href="http://hot-or-not.plainlystated.com/" data-external rel="noopener" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Cutting Pageload Time by 50%</title><link>https://plainlystated.com/2012/cutting-pageload-time-by-50/</link><pubDate>Thu, 16 Feb 2012 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2012/cutting-pageload-time-by-50/</guid><description>&lt;p&gt;The &lt;a href="http://www.creativeretrospection.com" title="Creative Retrospection" data-external rel="noopener" target="_blank"&gt;site I&amp;rsquo;m working on now&lt;/a&gt;, deploys as static files. I haven&amp;rsquo;t put up a non-server-side-dynamic site since high school, so I&amp;rsquo;m exploring my options. I thought I could just throw the whole thing up on Amazon S3, but was surprised that it was slower than the current setup (nginx on Linode). I have been reading about the importance of fast load speeds on conversion, google ranking, etc (&lt;a href="https://web.archive.org/web/20150919012827/http://www.plaveb.com/blog/the-importance-of-decreasing-page-load-time-for-improving-conversions" data-external rel="noopener" target="_blank"&gt;for example&lt;/a&gt;), so speed is a big priority for me. Here&amp;rsquo;s how I cut my site&amp;rsquo;s page load time down from around a second to around 500ms.&lt;/p&gt;</description></item><item><title>Weekend Project: Generate an (HTML + JS) eCommerce Site</title><link>https://plainlystated.com/2012/weekend-project-generate-an-html-js-ecommerce-site/</link><pubDate>Mon, 13 Feb 2012 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2012/weekend-project-generate-an-html-js-ecommerce-site/</guid><description>&lt;p&gt;My &lt;a href="http://plainlystated.etsy.com" title="Etsy store" data-external rel="noopener" target="_blank"&gt;Etsy store&lt;/a&gt; has been doing well, but I&amp;rsquo;d like to overcome the friction of requiring an Etsy account. To reach a wider audience, I&amp;rsquo;d like to additionally offer my products on a site that wasn&amp;rsquo;t specific to a community. To that end, I created &lt;a href="https://github.com/plainlystated/small_store" title="Small Store Project" data-external rel="noopener" target="_blank"&gt;a tool&lt;/a&gt; which generates a static HTML + Javascript eCommerce site. Here&amp;rsquo;s the result: &lt;a href="http://www.creativeretrospection.com" title="Creative Retrospection" data-external rel="noopener" target="_blank"&gt;Creative Retrospection&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Goals&lt;/strong&gt; I looked at a few options to get my own eCommerce site up and running (Shopify, etc), but everything was really out of my price range (for the volumes I&amp;rsquo;m doing). There are some open source projects that look interesting, but nothing that seemed a clear winner. For my needs, I just wanted something simple, fast, and secure. Static assets with all the logic client-side gives me that.&lt;/p&gt;</description></item><item><title>Etsy - The Importance of Sales Goals</title><link>https://plainlystated.com/2012/etsy-the-importance-of-sales-goals/</link><pubDate>Mon, 30 Jan 2012 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2012/etsy-the-importance-of-sales-goals/</guid><description>&lt;p&gt;&lt;a href="http://www.etsy.com/listing/91116344/flowering-vine-mirror" data-external rel="noopener" target="_blank"&gt;&lt;img src="23b8885d5f83fe10.jpg" alt=""&gt;&lt;/a&gt;It&amp;rsquo;s hard to say what sort of sales rate is reasonable or average for a new Etsy store. I spend a fair amount of time in the team forums, and the general consensus I&amp;rsquo;m getting is that it&amp;rsquo;s really hard to make any/many sales for smaller shops, but that larger shops (100+ items) tend to make several sales per week. Given that understanding, I have set a goal for myself that I think is aggressive but achievable.&lt;/p&gt;</description></item><item><title>Opening an Etsy Store: Two Weeks In</title><link>https://plainlystated.com/2012/opening-an-etsy-store-two-weeks-in/</link><pubDate>Mon, 16 Jan 2012 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2012/opening-an-etsy-store-two-weeks-in/</guid><description>&lt;p&gt;&lt;img src="IMG_8693.jpg" alt=""&gt;I opened my &lt;a href="https://web.archive.org/web/20230607145059/http://www.etsy.com/shop/PlainlyStated" data-external rel="noopener" target="_blank"&gt;Etsy store&lt;/a&gt; two weeks ago today, and I&amp;rsquo;ve learned a ton in the time. I have a long way to go before having any significant success, but it&amp;rsquo;s a fun experiment and side-project for me. Here&amp;rsquo;s where things stand so far.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sales&lt;/strong&gt; First and foremost, I got my first two sales at just under two weeks in. This is great, mostly because it&amp;rsquo;s encouraging. I am well beyond my expertise and comfort level in a lot of ways, so my first sales serve as a little confirmation that I&amp;rsquo;m on the right track. My first sale was an &lt;a href="http://www.etsy.com/listing/89722237/illinois-shaped-accent-mirror" data-external rel="noopener" target="_blank"&gt;Illinois-shaped mirror&lt;/a&gt;, and the second sale was a custom-requested piece: a District of Columbia mirror. It seems like there could be some demand for a line of state mirrors, and I am working on California and Texas now. I also put two new pieces up for sale. The one I particularly like is the image to the right: the Celtic knot mirror. There hasn&amp;rsquo;t been much traffic on it yet, but personally it&amp;rsquo;s my favorite thing in my store. There&amp;rsquo;s no accounting for taste, though.&lt;/p&gt;</description></item><item><title>Laser Cutting for Fun &amp; Profit</title><link>https://plainlystated.com/2012/laser-cutting-for-fun-profit/</link><pubDate>Sun, 08 Jan 2012 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2012/laser-cutting-for-fun-profit/</guid><description>&lt;p&gt;&lt;img src="e1afa077bc8d9b1d.jpg" alt=""&gt; I&amp;rsquo;ve been experimenting with laser cutting lately, and starting to get some results I like. It turned out to be more accessible than I expected, and what started as a single-purpose project is growing into an interesting creative outlet (You can follow my experiments on my &lt;a href="http://plainlystated.etsy.com" title="Plainlystated&amp;#39;s Etsy" data-external rel="noopener" target="_blank"&gt;Etsy store&lt;/a&gt;). Here&amp;rsquo;s what I&amp;rsquo;ve learned so far.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why &amp;amp; What to Laser Cut&lt;/strong&gt; Laser cutting is awesome. You create designs in some vector-based art program (such as Inkscape or Adobe Illustrator), send them to a giant computer-controlled laser, and out pops the shapes you drew. You have a ton of precision to play with, and a huge variety of materials to choose from. You can give your two-dimensional designs some depth, or create interlocking pieces for a 3D result.&lt;/p&gt;</description></item><item><title>Snake Attack!</title><link>https://plainlystated.com/2011/snake-attack/</link><pubDate>Sun, 16 Oct 2011 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2011/snake-attack/</guid><description>&lt;p&gt;&lt;img src="e344bad7c8732403.jpg" alt=""&gt;Here&amp;rsquo;s a quick post to show off my first project using the LED canvas I have been working on (nicknamed Square Wave). It&amp;rsquo;s based on the old &lt;a href="https://en.wikipedia.org/wiki/Snake_%28video_game%29" data-external rel="noopener" target="_blank"&gt;snake game&lt;/a&gt;, where the player controls a snake that slithers around looking for apples that appear and disappear. When he finds (and eats) an apple, he grows. When he crashes into himself, he dies.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=uKgDl_qzc3U" data-external rel="noopener" target="_blank"&gt;Watch on YouTube&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt; The code is open source, and you can find it &lt;a href="https://github.com/plainlystated/snakeAttack" title="Snake Attack on Github" data-external rel="noopener" target="_blank"&gt;on github&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Arduino From Vim</title><link>https://plainlystated.com/2011/arduino-from-vim/</link><pubDate>Fri, 07 Oct 2011 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2011/arduino-from-vim/</guid><description>&lt;p&gt;Arduino is awesome, but using their IDE is uncomfortable for people that would prefer vim or emacs. There is an option in the IDE to allow you to use an external editor, but you still need to use the GUI to get access to the compile &amp;amp; upload tools. Here&amp;rsquo;s my setup, for a vim-only setup (would be similar for emacs).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Goals&lt;/strong&gt; My goals for this project are simple:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Proper syntax highlighting&lt;/li&gt;
&lt;li&gt;Compile &amp;amp; upload code from within editor&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Syntax Highlighting&lt;/strong&gt; I use &lt;a href="https://github.com/vim-scripts/Arduino-syntax-file" title="Johannes Hoff&amp;#39;s syntax file" data-external rel="noopener" target="_blank"&gt;Johannes Hoff&amp;rsquo;s syntax file&lt;/a&gt; for this. Just put arduino.vim in your $HOME/.vim/syntax directory.&lt;/p&gt;</description></item><item><title>Addressable LED Grid</title><link>https://plainlystated.com/2011/addressable-led-grid/</link><pubDate>Fri, 23 Sep 2011 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2011/addressable-led-grid/</guid><description>&lt;p&gt;&lt;img src="bb0d4b9be0aff13d.jpg" alt=""&gt;As prep for future projects, I&amp;rsquo;ve built a simple 2D array of individually addressable LEDs. This canvas will ultimately serve as the platform for some games (snake, pong, etc), but I&amp;rsquo;m hopeful that other people will find this useful and come up with some cool applications.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Hardware&lt;/strong&gt; I &lt;a href="https://plainlystated.com/2011/led-strips-cheaper-vs-cooler/" title="LED Strips, Cheaper vs. Cooler"&gt;previously wrote&lt;/a&gt; about different types of LED strips. For this project, I went with the cheaper (HL1606-based) strip, because I am probably going to use up a lot of the ribbon, and it&amp;rsquo;s significantly cheaper. The downside to using this over the more expensive strip is that I&amp;rsquo;ll have fewer colors, but I think that&amp;rsquo;ll be ok for the projects I have in mind. To make the array, I cut an LED strip into 8-LED segments, and then wired those segments serially. Electrically this means there was no change, but it allowed me to lay the strips side-by-side, to form an 8 LED by 8 LED canvas, where each LED is individually controllable by a microcontroller.&lt;/p&gt;</description></item><item><title>Communique From 1863</title><link>https://plainlystated.com/2011/communique-from-1863/</link><pubDate>Thu, 22 Sep 2011 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2011/communique-from-1863/</guid><description>&lt;p&gt;&lt;img src="548881023aba446e.jpg" alt=""&gt;I picked up a telegraph sounder on &lt;a href="http://www.ebay.com/sch/i.html?_nkw=telegraph&amp;#43;sounder" title="Ebay - Telegraph Sounders" data-external rel="noopener" target="_blank"&gt;ebay&lt;/a&gt; this week. I don&amp;rsquo;t know much about its heritage, but it definitely looks vintage. I wrote some code (see below) to get my Arduino to clack away on it. In the video, the sounder is tapping out the Gettysburg Address, which is the example text in the code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How Telegraph Sounders Work&lt;/strong&gt; Mechanically, they are very simple, which is the reason that, even though they have moving parts, you can still find old ones that work quite well. The way mine works is that there is a lever, fixed at one end. Halfway down the lever, there is a cross-bar which sits just above two large electromagnets (one on either side). When the magnets are activated, the lever is pulled down, causing the far end of the lever to hit a stop on its underside. When the magnets are released, the bar raises (due to a spring), and hits a stop above it. On both the up and down motion, the stop it hits is metal, and gives a satisfying clack.&lt;/p&gt;</description></item><item><title>LED Strips, Cheaper vs. Cooler</title><link>https://plainlystated.com/2011/led-strips-cheaper-vs-cooler/</link><pubDate>Mon, 19 Sep 2011 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2011/led-strips-cheaper-vs-cooler/</guid><description>&lt;p&gt;&lt;img src="LED-strip.jpg" alt=""&gt;LED strips are growing in popularity and ease of use. I&amp;rsquo;ve been playing around with them lately (with my Arduino), and, for the uninitiated, here&amp;rsquo;s an overview of what&amp;rsquo;s available, and how much it costs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt; The strips are flexible ribbons of PCB material, with LEDs periodically fixed on them. They come in two basic varieties: addressable and non-addressable. With an addressable strip, you can control each individual light independently, but with a non-addressable strip you control the whole strip together.&lt;/p&gt;</description></item><item><title>Testing Singletons in Ruby</title><link>https://plainlystated.com/2011/testing-singletons-in-ruby/</link><pubDate>Sun, 28 Aug 2011 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2011/testing-singletons-in-ruby/</guid><description>&lt;p&gt;Ruby&amp;rsquo;s standard library includes the Singleton module, which lets you easily implement the singleton pattern. It can make unit testing a little difficult, though, because you cannot easily instantiate different versions of the class. This post will look at three solutions, two of which are hackish/wrong, and one of which is basic and clean (imho).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt; Let&amp;rsquo;s say we have a configuration class which reads some data from a YAML file and stores global state about the application (and you&amp;rsquo;ve decided to use a singleton). For this contrived example, we can specify our domain name (&amp;ldquo;foo.com&amp;rdquo;), and whether we want to use SSL. We&amp;rsquo;d like to unit test the &lt;code&gt;Configuration#website&lt;/code&gt; method, to make sure it properly prepends either http:// or https://, and that might look something like this:&lt;/p&gt;</description></item><item><title>Braintree 10% Time: LED Strip</title><link>https://plainlystated.com/2011/braintree-10-time-led-strip/</link><pubDate>Sat, 27 Aug 2011 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2011/braintree-10-time-led-strip/</guid><description>&lt;p&gt;At &lt;a href="http://www.braintreepayments.com/" data-external rel="noopener" target="_blank"&gt;Braintree&lt;/a&gt;, the developers get every other Friday to work on non-work-related projects of their choosing. Collaboration is encouraged, but even if you end up working on something alone, it&amp;rsquo;s a great way to spread your excitement about whatever interests you at the moment (and it&amp;rsquo;s a nice perk to the job).&lt;/p&gt;
&lt;p&gt;This week, my project was to get some LED strips unboxed and working. The strips are flexible circuit boards, with full-color LEDs dotting one side. Each &amp;ldquo;LED&amp;rdquo; is actually three LEDs clustered together (one red, one green, one blue), and with 21 control bits, they can display more colors than the human eye can distinguish. I bought a variety of strips, with different features, and I don&amp;rsquo;t know exactly what I&amp;rsquo;m going to do with them, but step 1 is to learn how to use them.&lt;/p&gt;</description></item><item><title>Coffeescript, VowsJS, &amp; Asynchronous Testing</title><link>https://plainlystated.com/2011/coffeescript-vowsjs-asynchronous-testing/</link><pubDate>Fri, 29 Jul 2011 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2011/coffeescript-vowsjs-asynchronous-testing/</guid><description>&lt;p&gt;Before releasing my &lt;a href="https://github.com/plainlystated/coffeescript-rrd" data-external rel="noopener" target="_blank"&gt;coffeescript RRD library&lt;/a&gt;, I needed to write some tests around it (RDT: Release-Driven Testing). I went with &lt;a href="https://vowsjs.org/" data-external rel="noopener" target="_blank"&gt;Vows&lt;/a&gt; (in coffeescript), and I had no problems writing tests around the few synchronous (&lt;em&gt;gasp&lt;/em&gt;) functions, but the asynchronous parts just didn&amp;rsquo;t work. At first, I punted on it, and switched my vows from coffeescript to javascript (which all the docs/examples are in). Later, when I came back to it, I was able to figure out the problem, and a dirty hack to get around it.&lt;/p&gt;</description></item><item><title>Building A Thermostat Using Arduino</title><link>https://plainlystated.com/2011/building-a-thermostat-using-arduino/</link><pubDate>Tue, 19 Jul 2011 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2011/building-a-thermostat-using-arduino/</guid><description>&lt;p&gt;I&amp;rsquo;ve completed the first pass of what seems to be a popular electronics self-education project: a home thermostat. I&amp;rsquo;ve &lt;a href="http://www.plainlystated.com/category/my-projects/my-projects-hot-or-not/" data-external rel="noopener" target="_blank"&gt;already written&lt;/a&gt; about some of the software, and now I&amp;rsquo;d like to share some of the hardware details.&lt;/p&gt;
&lt;p&gt;&lt;img src="f602ff8e90ec3777.jpg" alt="Arduino Thermostat"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Detecting the Temperature&lt;/strong&gt; The brains of the project is an arduino nano (a digital microcontroller). It has an input connected to a &lt;a href="http://www.adafruit.com/products/165" data-external rel="noopener" target="_blank"&gt;temperature sensor&lt;/a&gt; from Adafruit, and it does a little math to convert the analog reading from the sensor into the ambient temperature.&lt;/p&gt;</description></item><item><title>Fork &amp; Extend vs. Build Your Own, a NodeJS Example</title><link>https://plainlystated.com/2011/fork-extend-vs-build-your-own-a-nodejs-example/</link><pubDate>Mon, 18 Jul 2011 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2011/fork-extend-vs-build-your-own-a-nodejs-example/</guid><description>&lt;p&gt;For &lt;a href="http://hot-or-not.plainlystated.com" data-external rel="noopener" target="_blank"&gt;Hot or Not&lt;/a&gt;, I wanted to leverage as much existing code (open-source libraries) as possible, so I could focus on the more interesting application logic. I found a library to work with the database (RRD), but there were a few things about it that didn&amp;rsquo;t fit my needs, so I ended up releasing a new library. What follows are the reasons I decided to build my own solution, and the downsides to that course of action.&lt;/p&gt;</description></item><item><title>Fighting Back After Hacker News Took Down My Site</title><link>https://plainlystated.com/2011/fighting-back-after-hacker-news-took-down-my-site/</link><pubDate>Thu, 14 Jul 2011 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2011/fighting-back-after-hacker-news-took-down-my-site/</guid><description>&lt;p&gt;Last week I had &lt;a href="https://plainlystated.com/2011/beyond-nosql-using-rrd-to-store-temporal-data/"&gt;a post&lt;/a&gt; make it to the Hacker News front page, and my site immediately went down. After fighting with it for a while, I was able to get it limping along well enough to last the day, and since then I&amp;rsquo;ve made several simple changes that serve as a much more robust solution. I imagine there are a ton of self-hosters out there with similar setups as I had, so hopefully the details of my comeuppance will help others preventatively.&lt;/p&gt;</description></item><item><title>Beyond NoSQL: Using RRD to store temporal data</title><link>https://plainlystated.com/2011/beyond-nosql-using-rrd-to-store-temporal-data/</link><pubDate>Fri, 08 Jul 2011 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2011/beyond-nosql-using-rrd-to-store-temporal-data/</guid><description>&lt;p&gt;Recently, I&amp;rsquo;ve worked on two projects (&lt;a href="http://power-hungry.plainlystated.com" data-external rel="noopener" target="_blank"&gt;Power Hungry&lt;/a&gt;, &lt;a href="http://hot-or-not.plainlystated.com" data-external rel="noopener" target="_blank"&gt;Hot or Not&lt;/a&gt;) which (among other things) collect write-once data over time, and graph the results. The projects collect very different data, but this task was painful enough in postgres that I ended up switching to a temporal database for the second go, and it made the data collection &amp;amp; querying much easier. What follows is a brief discussion of the problems I faced with postgres, and how moving to RRD solved them.&lt;/p&gt;</description></item><item><title>Announcing Hot Or Not</title><link>https://plainlystated.com/2011/announcing-hot-or-not/</link><pubDate>Mon, 27 Jun 2011 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2011/announcing-hot-or-not/</guid><description>&lt;p&gt;My latest project, Hot Or Not, is live! It combines Arduino, NodeJS, Coffeescript, and Google Calendar, to make a thermostat which is remotely controllable via the internet. You can check out graphs of the data &lt;a href="http://hot-or-not.plainlystated.com" data-external rel="noopener" target="_blank"&gt;on the site&lt;/a&gt;, and get the code &lt;a href="https://github.com/plainlystated/Thermostat" data-external rel="noopener" target="_blank"&gt;on github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There were three basic things I wanted to address with this project. I will discuss each in more detail in future posts, but here&amp;rsquo;s an overview:&lt;/p&gt;</description></item><item><title>Power Hungry</title><link>https://plainlystated.com/2011/power-hungry/</link><pubDate>Tue, 29 Mar 2011 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2011/power-hungry/</guid><description>&lt;p&gt;I finished my first significant electronics project in a while: &lt;a href="http://www.power-hungry.com/" data-external rel="noopener" target="_blank"&gt;Power Hungry&lt;/a&gt;.  The idea is that I use sensors to monitor the actual voltage &amp;amp; amperage usage of various devices in my apartment, and I wirelessly transmit that to a base station, which calculates various statistics.  The results are then beamed to my linode server, where I have some graphs of the data.  The ultimate goal is to use this data to reduce my overall energy usage, but for now I&amp;rsquo;m just working on establishing a baseline, so I can best judge the effectiveness of whatever changes I make.  The results so far, though, are fairly interesting.&lt;/p&gt;</description></item><item><title>Poor Man's LCD Touchscreen Breakout Board</title><link>https://plainlystated.com/2011/poor-mans-lcd-touchscreen-breakout-board/</link><pubDate>Sun, 27 Mar 2011 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2011/poor-mans-lcd-touchscreen-breakout-board/</guid><description>&lt;p&gt;I recently picked up a &lt;a href="http://www.adafruit.com/index.php?main_page=product_info&amp;amp;cPath=37&amp;amp;products_id=250" data-external rel="noopener" target="_blank"&gt;graphic LCD display&lt;/a&gt; and a clear &lt;a href="http://www.adafruit.com/index.php?main_page=product_info&amp;amp;cPath=35&amp;amp;products_id=333" data-external rel="noopener" target="_blank"&gt;touchscreen panel&lt;/a&gt; for a project I&amp;rsquo;m starting.  They&amp;rsquo;re a lot of fun (and pretty cheap), but there are a lot of wires needed to get it hooked up, which means it&amp;rsquo;s somewhat fragile to move around.&lt;/p&gt;
&lt;p&gt;&lt;a href="0828bb8dd9c1685a.jpg"&gt;&lt;img src="d47c3cca00ec32c0.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If (like me) you like to move around when you code (couch/coffeeshop/bed/etc), then you&amp;rsquo;ll want to build a breakout board for your setup.  I soldered the level shifter IC (4050, required for 5V microcontrollers) and some stackable headers to a perfboard, then screwed the screen &amp;amp; perfboard onto a project box&amp;rsquo;s lid. I also added two screws to hold a full-sized arduino board in place, when it&amp;rsquo;s hooked up. The details:&lt;/p&gt;</description></item><item><title>Drop-Dead Simple Authentication for Microapps</title><link>https://plainlystated.com/2010/drop-dead-simple-authentication-for-microapps/</link><pubDate>Wed, 03 Mar 2010 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2010/drop-dead-simple-authentication-for-microapps/</guid><description>&lt;p&gt;For &lt;a href="http://www.inspectinator.com/" data-external rel="noopener" target="_blank"&gt;Inspectinator&lt;/a&gt; (a sinatra microapp), I needed a database-less authentication solution that was as lightweight as possible, but with a reasonable amount of security and maintainability. I came up with something that suits this purpose well, and &lt;a href="http://gist.github.com/321413" data-external rel="noopener" target="_blank"&gt;I&amp;rsquo;m sharing it&lt;/a&gt; in case anyone is looking for something similar. I call it EasyAuth.&lt;/p&gt;
&lt;p&gt;To use EasyAuth to authenticate your sinatra app, you first need to generate hashed passwords for each user you want to allow into your system. You can do this easily in IRB:&lt;br&gt;
$ irb -r lib/easy_auth/easy_auth.rb&lt;br&gt;
irb(main):001:0&amp;gt; EasyAuth.encrypt_password(&amp;ldquo;foobar&amp;rdquo;)&lt;br&gt;
=&amp;gt; [&amp;quot;$2a$10$bNh/qPqZt2sgLqetuOkpWuqIt6ANFzoZrtrEevQYjrlUP2Ka/JLNS&amp;quot;, &amp;ldquo;d84/Q&amp;rdquo;]This should be stored in your easy_auth.rb, in the AUTHORIZED_USERS hash.&lt;/p&gt;</description></item><item><title>Announcing Inspectinator</title><link>https://plainlystated.com/2010/announcing-inspectinator/</link><pubDate>Sun, 14 Feb 2010 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2010/announcing-inspectinator/</guid><description>&lt;p&gt;I&amp;rsquo;ve been wanting to experiment with sinatra for a while, so I popped something off my things-to-do-someday list and put together &lt;a href="http://www.inspectinator.com/" data-external rel="noopener" target="_blank"&gt;Inspectinator&lt;/a&gt;.  It&amp;rsquo;s aim is pretty straight-forward: parse standard ruby #inspect strings into a more palatable form.  It parses a string into a system of nested objects, and displays it as a tree.  Some simple jQuery let&amp;rsquo;s you drill down to the level of detail you want.  You can also link to your results (like pastie for inspects).&lt;/p&gt;</description></item><item><title>Drop-Dead Simple Token Generation -- Fixnum#to_s</title><link>https://plainlystated.com/2010/drop-dead-simple-token-generation-fixnumto_s/</link><pubDate>Sun, 14 Feb 2010 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2010/drop-dead-simple-token-generation-fixnumto_s/</guid><description>&lt;p&gt;For &lt;a href="http://www.inspectinator.com/" data-external rel="noopener" target="_blank"&gt;Inspectinator&lt;/a&gt;, I needed a lightweight token generator to allow people to share their results. I &lt;a href="https://web.archive.org/web/20121026000606/http://blog.logeek.fr/2009/7/2/creating-small-unique-tokens-in-ruby" data-external rel="noopener" target="_blank"&gt;found&lt;/a&gt; a great solution, and learned a cool ruby trick, too.&lt;/p&gt;
&lt;p&gt;The trick is in Fixnum (and Bignum), #to_s takes an optional argument: a number in (2..36). That number is the base it will print the number in (default is 10).&lt;/p&gt;
&lt;p&gt;So, for instance (from the ruby docs), to convert a number to binary:&lt;/p&gt;</description></item><item><title>Ruby Hoedown '09</title><link>https://plainlystated.com/2009/ruby-hoedown-09/</link><pubDate>Sun, 30 Aug 2009 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2009/ruby-hoedown-09/</guid><description>&lt;p&gt;This weekend I was in Nashville, TN for &lt;a href="http://rubyhoedown.com/" data-external rel="noopener" target="_blank"&gt;Ruby Hoedown 2009&lt;/a&gt;.  There were some great talks &amp;ndash; my favorites were Ben Mabey&amp;rsquo;s Cucumber &lt;a href="https://web.archive.org/web/20100402065905/http://www.benmabey.com/2009/08/28/writing-software-not-code-with-cucumber-slides-from-ruby-hoedown/" data-external rel="noopener" target="_blank"&gt;talk&lt;/a&gt;, Luigi Montanez&amp;rsquo;s &lt;a href="http://luigimontanez.com/2009/on-being-a-civic-coder" data-external rel="noopener" target="_blank"&gt;talk&lt;/a&gt; on using public data APIs for civic coding, and Jim Weirich&amp;rsquo;s excellent (and impromtu) &lt;a href="https://github.com/jimweirich/presentation_source_control/tree/master" data-external rel="noopener" target="_blank"&gt;talk&lt;/a&gt; on Git&amp;rsquo;s internals.&lt;/p&gt;
&lt;p&gt;After my recent difficulties with getting Rhodes working for mobile development, I was really excited about Leon Gersing&amp;rsquo;s talk about Appcelerator Titanium, but I missed all but the last five minutes of it because the schedule was changed for some reason (I was skipping what I *thought* was something else). =/  Hopefully he&amp;rsquo;ll post some slides.&lt;/p&gt;</description></item><item><title>Erlang &amp; Ruby</title><link>https://plainlystated.com/2009/erlang-ruby/</link><pubDate>Mon, 24 Aug 2009 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2009/erlang-ruby/</guid><description>&lt;p&gt;I&amp;rsquo;ve been playing around with Erlang lately, and it&amp;rsquo;s been quite a departure from the language I&amp;rsquo;m most comfortable with (and use everyday): Ruby. As part of my exploration, I&amp;rsquo;m doing a variety of sample problems (from the &amp;ldquo;Programming Erlang&amp;rdquo; book, among other places) in both Ruby and Erlang, and comparing the different implementations I come up with. Erlang and Ruby are meant to solve different types of problems, and the apples-to-oranges nature of the comparison should be kept in mind. The goal is to improve both my Erlang and my Ruby.&lt;/p&gt;</description></item><item><title>Erlang &amp; Ruby -- Ring Network</title><link>https://plainlystated.com/2009/erlang-ruby-ring-network/</link><pubDate>Mon, 24 Aug 2009 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2009/erlang-ruby-ring-network/</guid><description>&lt;p&gt;As part of my Erlang self-education, I&amp;rsquo;m doing a selection of sample problems (from the &amp;ldquo;Programming Erlang&amp;rdquo; book) in both Erlang and my language of choice: Ruby. The idea is to explore the differences between these very different languages.&lt;/p&gt;
&lt;p&gt;Today&amp;rsquo;s problem is to write a ring network benchmark. Given a network of N nodes, where each node is pointing to the next in line (or back to the first), each node should forward a received message along, until it has gone around the ring M times (so that a total of N * M messages are sent).&lt;/p&gt;</description></item><item><title>ActiveRecord Callbacks Trigger on Clean Objects</title><link>https://plainlystated.com/2009/activerecord-callbacks-trigger-on-clean-objects/</link><pubDate>Wed, 19 Aug 2009 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2009/activerecord-callbacks-trigger-on-clean-objects/</guid><description>&lt;p&gt;I came across this issue the other day at work, and I&amp;rsquo;m not really sure how I feel about it. It doesn&amp;rsquo;t necessarily seem right or wrong, but was definitely unintuitive for me&amp;hellip;&lt;/p&gt;
&lt;p&gt;Since Rails 2.1, we have had dirty object checking, which prevents ActiveRecord from saving an object if if hasn&amp;rsquo;t changed:&lt;br&gt;
&amp;gt;&amp;gt; person = Person.first&lt;/p&gt;
&lt;p&gt;  Person Load (0.9ms)  &lt;/p&gt;
&lt;p&gt;SELECT * FROM &amp;ldquo;people&amp;rdquo; LIMIT 1&lt;br&gt;
=&amp;gt; #&lt;/p&gt;
&lt;p&gt;&amp;gt;&amp;gt; person.save&lt;br&gt;
=&amp;gt; true&lt;/p&gt;</description></item><item><title>Ruby on Android -- Part 2</title><link>https://plainlystated.com/2009/ruby-on-android-part-2/</link><pubDate>Sun, 16 Aug 2009 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2009/ruby-on-android-part-2/</guid><description>&lt;p&gt;Continuing towards my goal of developing an application in ruby for my Android (see &lt;a href="http://techspeak.plainlystated.com/2009/07/ruby-on-android.html" data-external rel="noopener" target="_blank"&gt;part 1&lt;/a&gt;), I&amp;rsquo;ve been getting into &lt;a href="http://www.rhomobile.com/products/rhodes" data-external rel="noopener" target="_blank"&gt;Rhodes&lt;/a&gt;, which is an open-source project that aims to allow you to build native apps for a variety of mobile platforms, all from a lightweight ruby framework. For Android, it uses xruby (not Jruby).&lt;/p&gt;
&lt;p&gt;I started with the documentation at the &lt;a href="https://web.archive.org/web/20100413161543/http://wiki.rhomobile.com/index.php/Rhodes" data-external rel="noopener" target="_blank"&gt;Rhodes wiki&lt;/a&gt;, and checked out a &lt;a href="https://www.youtube.com/watch?v=T2pztOky_L0&amp;amp;feature=related" data-external rel="noopener" target="_blank"&gt;Google Talk&lt;/a&gt;. I tried to duplicate the sample application in the video, but quickly starting hitting walls, which I have been trying to work through. I haven&amp;rsquo;t had a ton of success with it yet, but I&amp;rsquo;ll document what success I have had.&lt;/p&gt;</description></item><item><title>Ruby on Android -- Part I</title><link>https://plainlystated.com/2009/ruby-on-android-part-i/</link><pubDate>Tue, 21 Jul 2009 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2009/ruby-on-android-part-i/</guid><description>&lt;p&gt;Of course, now that I have a &lt;a href="http://forthright.plainlystated.com/2009/07/google-phone.html" data-external rel="noopener" target="_blank"&gt;new G1&lt;/a&gt;, I want to start writing apps for it. Android apps are written in Java, but not having touched that since college, I started looking at ways to get ruby onto it instead. There was plenty of chatter about the possibility of running jruby on the device, but there are also frameworks that claim to allow you to write apps in ruby and push them to a variety of mobile platforms (android, iPhone, etc). I&amp;rsquo;ll be hearing a talk about &lt;a href="https://web.archive.org/web/20210802041015/https://www.appcelerator.com/" data-external rel="noopener" target="_blank"&gt;Appcelerator Titanium&lt;/a&gt; at Ruby Hoedown in August, but I haven&amp;rsquo;t gotten into their closed beta, so I&amp;rsquo;ll have to wait to try that out. The other (similar) solution I came across was &lt;a href="http://rhomobile.com/" data-external rel="noopener" target="_blank"&gt;Rhodes&lt;/a&gt;, which is available now (so that&amp;rsquo;s what I&amp;rsquo;ll start with).&lt;/p&gt;</description></item><item><title>Vim</title><link>https://plainlystated.com/2009/vim/</link><pubDate>Thu, 21 May 2009 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2009/vim/</guid><description>&lt;p&gt;I use vim daily for my routine development work, and I get along fine with it. When I first got into it, I scrambled up the steep learning curve until I got to a plateau where I could be productive, and haven&amp;rsquo;t given it much thought since then. I can do all the basic stuff (and a few cool tricks), but other than that my editor is pretty low on the list of things I want to devote thought to.&lt;/p&gt;</description></item><item><title>Vim Statusline</title><link>https://plainlystated.com/2009/vim-statusline/</link><pubDate>Thu, 21 May 2009 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2009/vim-statusline/</guid><description>&lt;p&gt;To start off my reinvigorated vim education, I looked into why I get a helpful info bar when I have :split windows, but not when I am looking at a single file. The bar is called the statusline (:help status-line), and you can change the visibility option with&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;laststatus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;&lt;span class="c1"&gt;#&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It defaults (on my system) to 1, meaning that it only shows for split windows. To make it always show, set it to 2.&lt;/p&gt;</description></item><item><title>Firebug's Console Pitfall</title><link>https://plainlystated.com/2009/firebugs-console-pitfall/</link><pubDate>Tue, 12 May 2009 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2009/firebugs-console-pitfall/</guid><description>&lt;p&gt;Beware &amp;ndash; if you leave a reference to the &amp;lsquo;console&amp;rsquo; object in your javascript and deploy it out, your site will not behave!&lt;/p&gt;
&lt;p&gt;I absentmindedly deployed code with a &amp;lsquo;console.debug()&amp;rsquo; in the javascript, and a quick test showed the site to be functioning. When I tried again in the morning (from my work computer), a dropdown was unpopulated. I enabled firebug for the site to check things out, but when the page reloaded things were fixed.&lt;/p&gt;</description></item><item><title>Rails Association Caching Pitfalls</title><link>https://plainlystated.com/2009/rails-association-caching-pitfalls/</link><pubDate>Sat, 21 Mar 2009 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2009/rails-association-caching-pitfalls/</guid><description>&lt;p&gt;This week at work I was disappointed to find that calling #new on an association collection doesn&amp;rsquo;t add the new instance to the cached collection:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;patrick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Poster&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;poster id:=&amp;#34;id:&amp;#34;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;patrick&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;new_post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;patrick&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Another post&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;post id:=&amp;#34;id:&amp;#34; nil=&amp;#34;nil&amp;#34;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;patrick&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/post&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;poster&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If I like the post and decide to save it to the database, my cached posts still doesn&amp;rsquo;t get updated:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;new_post&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;patrick&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In order to get the collection up-to-date I have to know that this is a trouble spot, and call #reload on the association:&lt;/p&gt;</description></item><item><title>Watching Your Logs From The Console</title><link>https://plainlystated.com/2009/watching-your-logs-from-the-console/</link><pubDate>Mon, 16 Mar 2009 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2009/watching-your-logs-from-the-console/</guid><description>&lt;p&gt;I&amp;rsquo;ve often wished there was a way to see the rails logs right inside the console window, instead of having to switch back and forth betweeh console and a &amp;ldquo;tail -f&amp;rdquo; process. It wasn&amp;rsquo;t hard to find an answer &amp;ndash; Jamis Buck &lt;a href="http://weblog.jamisbuck.org/2007/1/8/watching-activerecord-do-it-s-thing" data-external rel="noopener" target="_blank"&gt;blogged about it&lt;/a&gt; back in 2007 &amp;ndash; but it didn&amp;rsquo;t quite do all I was hoping for, so I ended up going a different route, which I think gives a more complete solution.&lt;/p&gt;</description></item><item><title>When Your Data Leaves Home Without You</title><link>https://plainlystated.com/2009/when-your-data-leaves-home-without-you/</link><pubDate>Wed, 04 Mar 2009 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2009/when-your-data-leaves-home-without-you/</guid><description>&lt;p&gt;Those that know me best know that I much prefer to keep my data on my own servers, as opposed to using services such as PicasaWeb, Blogspot, and github. Something about giving up possession of my original content doesn&amp;rsquo;t sit quite right with me &amp;ndash; maybe it&amp;rsquo;s my own experience with the &amp;ldquo;possession is nine-tenths of the law&amp;rdquo; adage, or maybe I&amp;rsquo;m just wary of free services. There&amp;rsquo;s also the problem of building up a brand that is on someone else&amp;rsquo;s domain &amp;ndash; whatever popularity my content gets should be associated with my domain, not the provider&amp;rsquo;s. Whatever the reason, I am generally willing to put up with poorer performance (etc.) in order to host my services myself.&lt;/p&gt;</description></item><item><title>New Blog</title><link>https://plainlystated.com/2009/new-blog/</link><pubDate>Tue, 03 Mar 2009 00:00:00 +0000</pubDate><guid>https://plainlystated.com/2009/new-blog/</guid><description>&lt;p&gt;Just a quick post to introduce my new blog&amp;hellip; This, along with my other new blog &lt;a href="http://forthright.plainlystated.com" data-external rel="noopener" target="_blank"&gt;forthright.plainlystated.com&lt;/a&gt; (non-technical) are meant to be my new home in the ether.&lt;/p&gt;
&lt;p&gt;This blog (techspeak.plainlystated.com) will generally be about my adventures in Ruby on Rails, as I continue growing my expertise in the field. (I have been working professionally with Rails for about 2 years, including the past 1.5 years at Medical Decision Logic working on medical research management software.)&lt;/p&gt;</description></item><item><title>About</title><link>https://plainlystated.com/about/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://plainlystated.com/about/</guid><description>&lt;p&gt;I&amp;rsquo;m Patrick Schless. I&amp;rsquo;m the technical co-founder and CTO of &lt;a href="https://communityjournalismproject.com" data-external rel="noopener" target="_blank"&gt;The Community Journalism Project&lt;/a&gt;, where we build software for local newsrooms.&lt;/p&gt;
&lt;p&gt;Before CJP I was at &lt;a href="https://www.braintreepayments.com" data-external rel="noopener" target="_blank"&gt;Braintree&lt;/a&gt; (payments, on the engineering side of the PayPal acquisition) and TempoIQ (a time-series database that became part of Carbon Black). Twelve years of mostly Rails and Postgres, some Go, a stretch of operations work I miss more than I expected to.&lt;/p&gt;
&lt;p&gt;I write here when I have something specific to say. Mostly notes on shipping, on infra at small companies, and on what I&amp;rsquo;ve found works for newsrooms that don&amp;rsquo;t have an engineering team.&lt;/p&gt;</description></item></channel></rss>