<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <id>tag:andrewberls.com,2005:/feed</id>
  <link rel="alternate" type="text/html" href="http://andrewberls.com" />
  
  <title>Andrew Berls</title>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/andrewberls" /><feedburner:info uri="andrewberls" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <id>tag:andrewberls.com,2005:Post/24</id>
    <published>2013-05-14T20:58:50Z</published>
    <updated>2013-05-14T21:06:20Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/TBDaTuxws-I/24" />
    <url>http://andrewberls.com/blog/post/24</url>
    <title>Ruby tips: Procs vs lambdas</title>
    <content type="html">&lt;p&gt;I recently ran into a Ruby subtlety that I had heard of but never encountered before, regarding the use of the &lt;code&gt;return&lt;/code&gt; keyword within blocks. Let&amp;#39;s jump right into an example. Let&amp;#39;s say you have an array of numbers and you want to &lt;a href="http://ruby-doc.org/core-2.0/Enumerable.html#method-i-select"&gt;select&lt;/a&gt; all the even ones. What will the following output?&lt;/p&gt;

&lt;pre class='prettyprint lang-ruby'&gt;&lt;code&gt;def evensWithReturn(items)
  items.select do |item|
    if item.even?
      return true
    else
      return false
    end
  end
end

&gt; evensWithReturn([1,2,3,4,5,6])
# =&gt; false
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;break /&gt;&lt;/p&gt;

&lt;p&gt;Wait, what? We&amp;#39;re expecting to see &lt;code&gt;[2, 4, 6]&lt;/code&gt;, not &lt;code&gt;false&lt;/code&gt;. What&amp;#39;s going on here? Let&amp;#39;s try it again, this time removing the &lt;code&gt;return&lt;/code&gt; keyword from the &lt;code&gt;select&lt;/code&gt; block.&lt;/p&gt;

&lt;pre class='prettyprint lang-ruby'&gt;&lt;code&gt;def evensWithoutReturn(items)
  items.select do |item|
    if item.even?
      true
    else
      false
    end
  end
end

&gt; evensWithoutReturn([1,2,3,4,5,6])
# =&gt; [2, 4, 6]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Much better. Although why was the &lt;code&gt;return&lt;/code&gt; keyword messing things up? It turns out that this is a result of the subtle differences between Procs and lambdas in Ruby, both of which represent chunks of reusable code. For the most part, the two are identical, although one of the differences is that &lt;span class="bold"&gt;a Proc returns from its enclosing block/method&lt;/span&gt;, while &lt;span class="bold"&gt;a lamba simply returns from the lambda&lt;/span&gt;. Let&amp;#39;s see some more examples. First, using Procs:&lt;/p&gt;

&lt;pre class='prettyprint lang-ruby'&gt;&lt;code&gt;def procWithReturn(items)
  myProc = Proc.new do |item|
    if item.even?
      return true
    else
      return false
    end
  end

  items.select(&amp;myProc)
end

&gt; procWithReturn([1,2,3,4,5,6])
# =&gt; false
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is the same result as we saw with the block. Still not the result we wanted, but at least we know why. As soon as the proc gets the first item (1), it will call &lt;code&gt;.even?&lt;/code&gt; on it and return false, and consequently return false from the entire &lt;code&gt;procWithReturn&lt;/code&gt; method. However, it we try the same example using a lambda instead of a proc:&lt;/p&gt;

&lt;pre class='prettyprint lang-ruby'&gt;&lt;code&gt;def lambdaWithReturn(items)
  myLambda = lambda do |item|
    if item.even?
      return true
    else
      return false
    end
  end

  items.select(&amp;myLambda)
end

&gt; lambdaWithReturn([1,2,3,4,5,6])
# =&gt; [2, 4, 6]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Success! Here, the lambda returns values to the &lt;code&gt;select&lt;/code&gt; block, but doesn&amp;#39;t exit the enclosing method. For completeness, the other difference between Procs and lambdas is that lambdas enforce &lt;em&gt;arity&lt;/em&gt;, meaning it will throw an &lt;code&gt;ArgumentError&lt;/code&gt; if you don&amp;#39;t pass the number of arguments it specifies.&lt;/p&gt;

&lt;p&gt;For the record, this example is fairly contrived for illustrative purposes - before you jump down my throat, I know that you can do&lt;/p&gt;

&lt;pre class='prettyprint lang-ruby'&gt;&lt;code&gt;[1,2,3,4,5,6].select(&amp;:even?)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I hope this clarifies some of the subtleties between procs and lambdas. For interested readers, I recommend &lt;a href="http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/"&gt;this excellent blog post&lt;/a&gt; which goes into further detail.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/TBDaTuxws-I" height="1" width="1"/&gt;</content>
    <updated>2013-05-14T21:06:20Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/24</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/23</id>
    <published>2013-05-09T17:56:21Z</published>
    <updated>2013-05-09T17:59:24Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/iunYlE08Cqk/23" />
    <url>http://andrewberls.com/blog/post/23</url>
    <title>Faking keyword arguments in Ruby</title>
    <content type="html">&lt;p&gt;With the official release of &lt;a href="http://www.ruby-lang.org/en/news/2013/02/24/ruby-2-0-0-p0-is-released/"&gt;Ruby 2.0&lt;/a&gt;, there have been a myriad of posts about all of its shiny new features. Of those, my personal favorite is the addition of &lt;a href="http://globaldev.co.uk/2013/03/ruby-2-0-0-in-detail/"&gt;keyword arguments&lt;/a&gt;. This is essentially built-in support for what&amp;#39;s been traditionally accomplished in Ruby using options hashes.  For example, it&amp;#39;s not uncommon to see method calls like &lt;code class="prettyprint lang-ruby"&gt;foo(bar: &amp;quot;one&amp;quot;, baz: &amp;quot;two&amp;quot;)&lt;/code&gt;. However, under the hood this might be implemented as:&lt;/p&gt;

&lt;pre class="prettyprint lang-ruby"&gt;&lt;code&gt;def foo(options={})
  bar = options.delete(:bar)
  baz = options.delete(:baz)
  puts "#{bar} #{baz}"
end

foo(bar: "one", baz: "two") # =&gt; "one two"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;break /&gt;&lt;/p&gt;

&lt;p&gt;In fact &lt;a href="https://github.com/rails/rails/blob/3-2-13/activesupport/lib/active_support/core_ext/array/extract_options.rb"&gt;ActiveSupport in Rails 3.2.13&lt;/a&gt; defines a method called &lt;code&gt;extract_options!&lt;/code&gt; that deals with exactly this. However, if we&amp;#39;re stuck on Ruby &amp;lt; 2.0, defining every method to use an options hash is often more work than necessary, especially when a method only takes one or two parameters. We can get around this with a clever trick. If we change our method slightly from the previous example to work without an options hash:&lt;/p&gt;

&lt;pre class="prettyprint lang-ruby"&gt;&lt;code&gt;def foo(bar, baz)
  puts "#{bar} #{baz}"
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can then fake keyword arguments by calling it like this: &lt;/p&gt;

&lt;pre class="prettyprint lang-ruby"&gt;&lt;code&gt;foo(bar = "one", baz = "two")
# =&gt; "one two"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This trick exploits the fact that the returned value from the assignments in the call to &lt;code class="prettyprint lang-ruby"&gt;foo()&lt;/code&gt; will be the value that&amp;#39;s assigned, so at the end of the day &lt;code class="prettyprint lang-ruby"&gt;&amp;quot;one&amp;quot;&lt;/code&gt; and &lt;code class="prettyprint lang-ruby"&gt;&amp;quot;two&amp;quot;&lt;/code&gt; will still be passed in! This saves us having to work with options hashes and still looks pretty, although it&amp;#39;s important to note that unlike hashes and Ruby 2 keyword arguments, order matters here. If you change up the order you pass in &lt;code&gt;baz&lt;/code&gt; and &lt;code&gt;bar&lt;/code&gt;, things won&amp;#39;t work as expected. &lt;/p&gt;

&lt;p&gt;Personally, I can&amp;#39;t wait to switch my projects to use Ruby 2.0 and use keywords arguments for real, but in the mean time this is a neat trick I hadn&amp;#39;t seen before to emulate them!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/iunYlE08Cqk" height="1" width="1"/&gt;</content>
    <updated>2013-05-09T17:59:24Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/23</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/22</id>
    <published>2013-05-06T01:36:08Z</published>
    <updated>2013-05-06T01:36:08Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/agTLe0cAb-c/22" />
    <url>http://andrewberls.com/blog/post/22</url>
    <title>Git tricks: Unstaging files</title>
    <content type="html">&lt;p&gt;&lt;em&gt;This post dives a bit into the git reset command. If you want to jump straight to the good stuff, click &lt;a href="#alias"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I wanted to share a handy alias I use for removing files from the staging area in git. Often I&amp;#39;ll be working and adding files to the staging area with &lt;code&gt;git add&lt;/code&gt;, and then decide (for example), that I don&amp;#39;t want to commit some files with the others and get them out of the staging area (but keep my work intact). Let&amp;#39;s look at an example case - running &lt;code&gt;git status&lt;/code&gt; after staging a file might look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git add example.txt
$ git status
# On branch test
# Changes to be committed:
#   (use "git reset HEAD &lt;file&gt;..." to unstage)
#
#   modified:   example.txt
#&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;break /&gt;&lt;/p&gt;

&lt;p&gt;Hey, that&amp;#39;s neat - it tells us right there how to unstage files! This is accomplished using the &lt;a href="https://www.kernel.org/pub/software/scm/git/docs/git-reset.html"&gt;git reset&lt;/a&gt; command. From the docs:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git reset [-q] [&amp;lt;commit&amp;gt;] [--] &amp;lt;paths&amp;gt;…
This form resets the index entries for all &amp;lt;paths&amp;gt to their state at &amp;lt;commit&amp;gt;. 
(It does not affect the working tree, nor the current branch.)

This means that git reset &amp;lt;paths&amp;gt is the opposite of git add &amp;lt;paths&amp;gt.&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;git reset&lt;/code&gt; can be used for several things -it can point the current HEAD at a specified state, and we&amp;#39;ll be using it to copy entries from HEAD to the index, or staging area, thus removing our file from the staging area and leaving our working tree unchanged. Also important is that &lt;code&gt;&amp;lt;commit&amp;gt;&lt;/code&gt; defaults to HEAD, so we can leave that bit out. Let&amp;#39;s give it a shot!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git reset -- example.txt
Unstaged changes after reset:
M   example.txt
$ git status
# On branch test
# Changes not staged for commit:
#   (use "git add &lt;file&gt;..." to update what will be committed)
#   (use "git checkout -- &lt;file&gt;..." to discard changes in working directory)
#
#   modified:   example.txt
#
no changes added to commit (use "git add" and/or "git commit -a")&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And our changes are left intact but removed from the staging area! Mission accomplished! However, you might be wondering about the strange &lt;code&gt;--&lt;/code&gt; that shows up in the command. Those are referred to as the &amp;#39;bare double dashes&amp;#39;, and they prevent ambiguity by ensuring that we&amp;#39;re resetting a file and not specifying a branch. For example, if you have a branch and a file both named &lt;code&gt;example&lt;/code&gt; and you run &lt;code&gt;git reset example&lt;/code&gt;, you might see the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;fatal: ambiguous argument 'example': both revision and filename
Use '--' to separate filenames from revisions&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Git can&amp;#39;t tell if you&amp;#39;re talking about the branch or the file (each of which has very different consequences), so the &lt;code&gt;--&lt;/code&gt; makes it clear we&amp;#39;re not talking about a branch and that we want to reset our file.&lt;/p&gt;

&lt;p&gt;So we&amp;#39;ve seen that we can use &lt;code&gt;git reset&lt;/code&gt; to unstage our files. However, it&amp;#39;d be nice to be able to say &lt;code&gt;git unstage &amp;lt;paths&amp;gt;&lt;/code&gt;, so let&amp;#39;s define that using a git alias:&lt;/p&gt;

&lt;p&gt;&lt;a name="alias"&gt;&lt;/a&gt;
&lt;pre&gt;&lt;code&gt;git config --global alias.unstage &amp;#39;reset --&amp;#39;&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;And there you have it! Now we can run &lt;code&gt;git unstage example.txt&lt;/code&gt; to our heart&amp;#39;s content.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/agTLe0cAb-c" height="1" width="1"/&gt;</content>
    <updated>2013-05-06T01:36:08Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/22</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/21</id>
    <published>2013-04-10T18:14:47Z</published>
    <updated>2013-04-10T18:36:05Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/sXqLvHTyNhU/21" />
    <url>http://andrewberls.com/blog/post/21</url>
    <title>Naked asterisk parameters in Ruby</title>
    <content type="html">&lt;p&gt;I came across a Ruby idiom I hadn&amp;#39;t seen before browing through some of the &lt;a href="https://github.com/rails/rails/blob/master/activerecord/lib/active_record/persistence.rb#L102"&gt;Rails source&lt;/a&gt; the other day. Specifically, the method in question looked like this:&lt;/p&gt;

&lt;pre class='prettyprint lang-ruby'&gt;
&lt;code&gt;def save(*)
    create_or_update
rescue ActiveRecord::RecordInvalid
    false
 end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&amp;#39;ve never seen the asterisk as a parameter by itself, and to explain it a brief review of the &lt;a href="#"&gt;splat operator&lt;/a&gt; is in order. The splat operator allows methods in Ruby to accept a variable number of arguments. For example:&lt;/p&gt;

&lt;pre class='prettyprint lang-ruby'&gt;
&lt;code&gt;def say_hello(*people)
  people.each { |person| puts "Hello #{person}!" }
end
 
say_hello("Alice", "Bob", "John")
# "Hello Alice!"
# "Hello Bob!"
# "Hello John!"&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;break /&gt;&lt;/p&gt;

&lt;p&gt;The splat can be used with named arguments as well - it will just gather up all of the unnamed arguments into an array. It can also be used for a couple other really neat tricks, which are explained in detail &lt;a href="http://endofline.wordpress.com/2011/01/21/the-strange-ruby-splat/"&gt;in this post&lt;/a&gt;. However,when using the splat, it&amp;#39;s much more common to see a definition like&lt;/p&gt;

&lt;pre class='prettyprint lang-ruby'&gt;
&lt;code&gt;def some_method(*args)
  # do something with args
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So what&amp;#39;s the deal with the unnamed asterisk? Well, this is still the same splat operator at work, the difference being that it does not name the argument array. This may not seem useful, but it actually comes into play when you&amp;#39;re not referring to the arguments inside the function, and instead calling &lt;code&gt;super&lt;/code&gt;. To experiment, I put together this quick snippet:&lt;/p&gt;

&lt;pre class='prettyprint lang-ruby'&gt;
&lt;code&gt;class Bar
  def save(*args)
    puts "Args passed to superclass Bar#save: #{args.inspect}"
  end
end
 
class Foo &lt; Bar
  def save(*)
    puts "Entered Foo#save"
    super
  end
end
 
Foo.new.save("one", "two")&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;which will print out the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Entered Foo#save
Args passed to superclass Bar#save: [&amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The globbed arguments are automatically passed up to the superclass method. Some might be of the opinion that it&amp;#39;s better to be explicit and define methods with &lt;code&gt;def method(*args)&lt;/code&gt;, but in any case it&amp;#39;s a neat trick worth knowing!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/sXqLvHTyNhU" height="1" width="1"/&gt;</content>
    <updated>2013-04-10T18:36:05Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/21</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/20</id>
    <published>2013-01-14T21:47:11Z</published>
    <updated>2013-01-14T21:47:11Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/VCdZ8WxNzR4/20" />
    <url>http://andrewberls.com/blog/post/20</url>
    <title>A gem for managing your code notes</title>
    <content type="html">&lt;p&gt;I just released my first gem to the world, a little command line tool for managing source code annotations. I found myself constantly scattering little notes such as TODO, OPTIMIZE, etc into my code comments, and I wanted a way to quickly view all such notes in my project directories. The result, the &lt;a href="https://github.com/andrewberls/notes-cli"&gt;Notes-CLI&lt;/a&gt; gem, packages an executable for recursively searching through source files for common annotations with the flexibility to add your own search terms. If you&amp;#39;ve ever worked with Rails, this is very similar to the &lt;code&gt;rake notes&lt;/code&gt; command, extracted to work with any project.&lt;/p&gt;

&lt;p&gt;The gem installs the &lt;code&gt;notes&lt;/code&gt; executable, which can be run with &lt;code&gt;-h&lt;/code&gt; for some more information. For an example, if I run the &lt;code&gt;notes&lt;/code&gt; command in one of my project directories (a Rails app), I get something similar to the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ notes app/    # Only search in the app/ directory

app/models/user.rb:
  ln 32: # OPTIMIZE: this method can be cleaner
  ln 34: # TODO: this parameter is a hack

app/views/expenses/_net_total.html.erb:
  ln 1: &amp;lt;%# TODO: condense this eventually  %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The options for adding custom search terms or excluding directories from search are documented on the project&amp;#39;s &lt;a href="https://github.com/andrewberls/notes-cli"&gt;Github page&lt;/a&gt;. If you want to jump right in, just run &lt;code&gt;gem install notes-cli&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;This project started as a tiny script with a bash alias. Converting it into a gem for distribution turned out to be a trivial process, thanks to &lt;a href="http://guides.rubygems.org/make-your-own-gem/"&gt;this article&lt;/a&gt;. I&amp;#39;ve found it to be super useful, and I hope someone else is able to get some value out of it. Give it a shot and let me know what you think!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/VCdZ8WxNzR4" height="1" width="1"/&gt;</content>
    <updated>2013-01-14T21:47:11Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/20</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/19</id>
    <published>2012-12-10T17:31:03Z</published>
    <updated>2012-12-11T18:23:48Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/ZDuSfqv7rvU/19" />
    <url>http://andrewberls.com/blog/post/19</url>
    <title>Winter Break - A Reading List</title>
    <content type="html">&lt;p&gt;Winter break is coming up fast, meaning I have a few weeks of rare free time. I want to use the time to learn as much as possible about topics I don't consider myself strong in. I've put together a list of things I've been wanting to learn, but it's incomplete. I welcome suggestions and additions, and I'll add them to the list - I'd love to foster a discussion on some interesting topics!&lt;/p&gt;

&lt;h3&gt;Scala&lt;/h3&gt;

&lt;p class="list-head"&gt;This is the big one for me - Scala is a statically typed language that brings functional programming concepts to the JVM. It's very fast (sorry Ruby), and gaining popularity, notably at Twitter. I have a feeling it will become one of the next big things.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://blog.redfin.com/devblog/2010/05/how_and_why_twitter_uses_scala.html"&gt;Why does Twitter use Scala?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.scala-lang.org/node/1305"&gt;Learning Scala&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://typesafe.com/resources/book/scala-for-the-impatient"&gt;Scala for the Impatient&lt;/a&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;break /&gt;&lt;/p&gt;

&lt;h3&gt;Backbone.js&lt;/h3&gt;

&lt;p class="list-head"&gt;Client-side MVC (MV*) applications and frameworks are becoming more and more popular. I've never spent too much time working with Backbone, so I want to learn more about how apps with it are structured and built.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.jamesyu.org/2011/01/27/cloudedit-a-backbone-js-tutorial-by-example/"&gt;A BackboneJS Tutorial By Example&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://addyosmani.github.com/backbone-fundamentals/"&gt;Developing Backbone.js Applications&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://bennolan.com/2010/11/24/backbone-jquery-demo.html"&gt;Backbone Mobile Example&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://addyosmani.github.com/backbone-fundamentals/#stack-1-building-a-backbone-app-with-node.js-express-mongoose-and-mongodb"&gt;Building A Backbone App With Node.js, Express, Mongoose and MongoDB&lt;/a&gt;
&lt;/ul&gt;

&lt;h3&gt;Graphs&lt;/h3&gt;

&lt;p class="list-head"&gt;Graphs play a central role in most large companies today (think Facebook's social graph), and I have a feeling it's something I'll absolutely need to know very soon. Goal: understand the basics of graph theory and their various uses.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Graph_theory"&gt;Graph Theory (Wikipedia)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="ttp://arxiv.org/abs/cond-mat/0303516/"&gt;Paper: Structure and Function of Complex Networks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;SQL&lt;/h3&gt;

&lt;p class="list-head"&gt;I spend most of my time working with SQL databases through an ORM. I've been putting off learning the basics of raw SQL.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www2.aao.gov.au/2dfgrs/Public/Release/Database/sql_intro.pdf"&gt;Intro to Structured Query Language (1)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.thundersoftware.com/churchdb/sqltutorial/sql_tutorial.html"&gt;Intro to Structured Query Language (2)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;NoSQL&lt;/h3&gt;

&lt;p class="list-head"&gt;NoSQL is everybody's favorite buzzword nowadays. The term is rather poorly defined, but I want to understand the implications and advantages of using a 'NoSQL' database such as MongoDB or Redis over a relational one.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.slideshare.net/dvirsky/introduction-to-redis"&gt;Introduction to Redis&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://simonwillison.net/static/2010/redis-tutorial/"&gt;Redis Tutorial&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.mongodb.org/display/DOCS/Introduction"&gt;Introduction to MongoDB&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Google&lt;/h3&gt;

&lt;p class="list-head"&gt;Google has built some amazing technologies to power a business of their size - MapReduce is an extremely popular paradigm that inspired the Hadoop project, and Spanner is a revolutionary globally distributed database. Their papers are essential reading.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://research.google.com/archive/bigtable.html"&gt;Paper: BigTable&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://research.google.com/archive/mapreduce.html"&gt;Paper: MapReduce&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://research.google.com/archive/spanner.html"&gt;Paper: Spanner&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Ruby&lt;/h3&gt;

&lt;p class="list-head"&gt;I consider myself fairly strong at Ruby, so this is the 'fun' stuff. It's always interesting to look at the internals.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.rubyinside.com/ruby-mri-code-walk-tour-6020.html"&gt;A Simple Tour of the Ruby MRI Source Code&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.youtube.com/watch?v=aISNtCAZlMg"&gt;Symbol#to_proc with Peter Cooper&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://confreaks.com/videos/1233-aloharuby2012-refactoring-from-good-to-great"&gt;Refactoring from Good to Great&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Data Warehousing&lt;/h3&gt;

&lt;p class="list-head"&gt;This is a topic I know very little about and will likely run into later. Key questions: why do companies do it? How is it accomplished - what is a dimension? What is a fact?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Data_warehouse"&gt;Data Warehouse (Wikipedia)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://www.slideshare.net/jsbi/introduction-to-data-warehousing"&gt;Introduction to Data Warehousing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;D3.js&lt;/h3&gt;

&lt;p class="list-head"&gt;D3 is a library for manipulating and displaying documents based on data. The possibilities here are endless - I want to see if I can make something out of it. Idea: mash up open source datasets.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://d3js.org/"&gt;http://d3js.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Misc&lt;/h3&gt;

&lt;p class="list-head"&gt;This is an aggregation of stuff that doesn't really fit into any of the previous categories.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://kunststube.net/encoding/"&gt;What Every Programmer Needs To Know About Encoding&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/ZDuSfqv7rvU" height="1" width="1"/&gt;</content>
    <updated>2012-12-11T18:23:48Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/19</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/18</id>
    <published>2012-10-24T02:51:52Z</published>
    <updated>2012-12-26T05:53:04Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/jrJeqp7uIBE/18" />
    <url>http://andrewberls.com/blog/post/18</url>
    <title>Intuitive Design</title>
    <content type="html">&lt;p&gt;I&amp;#39;m not sure when this happened, but the new (ish?) &lt;a href="https://bitly.com/"&gt;bit.ly&lt;/a&gt; homepage is not at all one that I would expect from a URL shortening service. The box to actually shorten a link is small and tucked to the side, instead of front and center like you might expect, and the user&amp;#39;s eye is now instead drawn to links to sign up and log in. &lt;/p&gt;

&lt;p&gt;&lt;a href="http://andrewberls.com/images/posts/bitly.png"&gt;&lt;img src="http://andrewberls.com/images/posts/bitly.png" alt="Bit.ly Homepage"&gt;&lt;/a&gt;
&lt;p class="img-caption"&gt;Click for larger image&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I would be willing to bet that a large percentage of their traffic is from users who are not registered on the site. While I understand that they&amp;#39;re expanding the platform functionality and trying to reverse that trend, the new design still strikes me as straying from the core offering and not focusing on what most of their users are looking for.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/jrJeqp7uIBE" height="1" width="1"/&gt;</content>
    <updated>2012-12-26T05:53:04Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/18</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/17</id>
    <published>2012-10-15T04:49:17Z</published>
    <updated>2013-01-07T00:58:53Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/4rXFcfBC1c8/17" />
    <url>http://andrewberls.com/blog/post/17</url>
    <title>Adding SFTP support to cURL</title>
    <content type="html">&lt;p&gt;I was surprised today to find out that &lt;a href="http://curl.haxx.se/"&gt;cURL&lt;/a&gt; does not have SFTP support built in. I ran into the issue trying to get set up with René Moser&amp;#39;s awesome &lt;a href="https://github.com/resmo/git-ftp"&gt;git-ftp&lt;/a&gt; script, which is exactly what I needed to manage deployments for one of my sites running in a restricted server environment. I&amp;#39;ll write more about git-ftp later, but in short, it gives you all the deployment goodness and capabilities of git when you only have FTP access to a server. In particular, I need to use it with SFTP, but kept running into the error &lt;code&gt;Protocol sftp not supported or disabled in libcurl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As it turns out, there&amp;#39;s no easy way to add SFTP support to cURL. In the end, I had to rebuild the library from source with some special tweaks. I  got frustrated from poring over archaic mailing list posts and jumbled documentation, so I wanted to share the steps I took to get it to work.&lt;/p&gt;

&lt;p&gt;&lt;break /&gt;&lt;/p&gt;

&lt;h3&gt;What you&amp;#39;ll need&lt;/h3&gt;

&lt;p&gt;You&amp;#39;ll need to be comfortable doing things at the command line. You&amp;#39;ll also need a C compiler of some sort. If you&amp;#39;re on a Mac, the &lt;a href="https://developer.apple.com/xcode/"&gt;XCode Command Line Tools&lt;/a&gt; package everything together nicely, otherwise I assume you have an equivalent installed. I did all of this on a Mac, but it should work on Linux as well.&lt;/p&gt;

&lt;h3&gt;1. Install libssh2&lt;/h3&gt;

&lt;p&gt;libssh2 is a client-side C library that implements the SSH2 protocol - we need to configure cURL to use this to get SFTP support. Download the tarball from &lt;a href="http://www.libssh2.org/"&gt;this page&lt;/a&gt;, unpack it, and &lt;code&gt;cd&lt;/code&gt; into the directory. Then run:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;./configure
make
make install
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It will output a ton of noise to your console, but that&amp;#39;s all you have to do here.&lt;/p&gt;

&lt;h3&gt;2. Install/configure/build cURL using libssh2&lt;/h3&gt;

&lt;p&gt;Here we&amp;#39;re building cURL from source, and linking to libssh2 in the configuration. Same process as before - download the latest release from &lt;a href="http://curl.haxx.se/download.html"&gt;here&lt;/a&gt;, unpack it, and &lt;code&gt;cd&lt;/code&gt; in.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;./configure --with-libssh2=/usr/local
make
make install
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To check that it worked, run &lt;code&gt;curl -V&lt;/code&gt; and ensure that sftp appears somewhere in the Protocols list. If it doesn&amp;#39;t, see the note below or make sure that something didn&amp;#39;t fail unnoticed during the config/build steps (you may need to run some commands with &lt;code&gt;sudo&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;In my case, I found that the executable &lt;code&gt;/usr/bin/curl&lt;/code&gt; was outdated and taking precedence over my custom build, which installs to &lt;code&gt;/usr/local/bin/&lt;/code&gt;. I chose to just move the one in &lt;code&gt;/usr/bin/&lt;/code&gt; to &lt;code&gt;/usr/bin/curl_backup&lt;/code&gt; - if you like, you could copy the one from &lt;code&gt;/usr/local/&lt;/code&gt; into &lt;code&gt;/usr/bin/&lt;/code&gt;. Your call. Edit: The reason for this was that &lt;code&gt;/usr/bin&lt;/code&gt; came before &lt;code&gt;/usr/local/bin&lt;/code&gt; in my path. You can fix this if you like using &lt;code&gt;export PATH=/usr/local/bin:$PATH&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I hope this can be of some use to someone! Feel free to leave a comment if you run into any trouble with any of the steps.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/4rXFcfBC1c8" height="1" width="1"/&gt;</content>
    <updated>2013-01-07T00:58:53Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/17</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/16</id>
    <published>2012-07-15T22:18:46Z</published>
    <updated>2013-04-02T17:21:17Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/2JTvYvb66tM/16" />
    <url>http://andrewberls.com/blog/post/16</url>
    <title>A Rakefile to build CoffeeScript projects</title>
    <content type="html">&lt;p&gt;&lt;em style="font-size:1.1em"&gt;Update: I&amp;#39;ve since overhauled this project to be an npm package called Arabica. You should &lt;a href="https://github.com/andrewberls/arabica"&gt;check it out.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;
I recently started a new project in CoffeeScript, and began by looking for a good build system. When developing a JavaScript-heavy application, concatenating and minifying scripts is crucial in order to reduce the number of HTTP requests and download size, making your app nice and snappy. Unfortunately order can matter when concatenating files, so randomly lumping together everything in the source directory isn't enough. I set out to find a solution that allowed me to specify files in the order to compile, with the ability to watch a directory for convenience. This is what I threw together - a Ruby Rakefile that makes use of the uglifier and listen gems, inspired by a script by &lt;a href="https://github.com/claydotio/Slime-Volley/blob/master/Rakefile"&gt;Clay.io&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;&lt;break /&gt;&lt;/p&gt;

&lt;script src="http://gist.github.com/3118851.js"&gt;&lt;/script&gt;

&lt;h3&gt;Usage&lt;/h3&gt;

&lt;p&gt;
Using the script is very simple, but there are a few dependencies that must be resolved beforehand. An installation of &lt;a href="http://www.ruby-lang.org/en/downloads/"&gt;Ruby&lt;/a&gt; and &lt;a href="http://rubygems.org/pages/download/"&gt;RubyGems&lt;/a&gt; is required. The Gemfile is only present for convenience - the script should work just fine if happen to already have the gems installed or want to install them manually, but you'll want the Rakefile in your project's root. If you're installing using the Gemfile, grab bundler if necessary with &lt;code&gt;gem install bundler&lt;/code&gt; and finally &lt;code&gt;bundle install&lt;/code&gt; to install the uglifier and listen gems. Once you've set up all dependencies, put your project filenames (in the desired order) in the &lt;code&gt;FILENAMES&lt;/code&gt; array, and customize the &lt;code&gt;SRC_PATH&lt;/code&gt;, &lt;code&gt;BUILD_PATH&lt;/code&gt;, and &lt;code&gt;DIST_PATH&lt;/code&gt; variables to your needs. You can call &lt;code&gt;rake build&lt;/code&gt; manually to build the application, or just watch the source files with &lt;code&gt;rake watch&lt;/code&gt; which will compile automatically anytime you save a change.
&lt;/p&gt;

&lt;h3&gt;Notes&lt;/h3&gt;

&lt;p&gt;
I tend to keep my editor and terminal on separate workspaces, so I added a &lt;a href="http://growl.info/"&gt;Growl notification&lt;/a&gt; that alerts you if a compile attempt failed - this is totally optional and can be removed if you prefer. Finally, the &lt;code&gt;rake clean&lt;/code&gt; task removes all compiled files (including distribution files) if you ever need to clean up your directory.
&lt;/p&gt;

&lt;p&gt;
I've already run into the issue trying to include non-CoffeeScript files (such as vendor JS libraries), but it's entirely possible with a small hack and I can update to post that if anyone would like. As always, I welcome ideas or suggestions for improvement!
&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/2JTvYvb66tM" height="1" width="1"/&gt;</content>
    <updated>2013-04-02T17:21:17Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/16</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/15</id>
    <published>2012-05-28T23:29:49Z</published>
    <updated>2012-05-29T04:43:08Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/C069VhsulZI/15" />
    <url>http://andrewberls.com/blog/post/15</url>
    <title>Suggesting URL aliases with CoffeeScript</title>
    <content type="html">&lt;p&gt;
If you're familiar with any blogging platform or content management system, you've likely heard the term 'URL alias'. But what exactly does this refer to, and what problem does it solve? Let's start by looking at some common examples. If you've ever used Drupal, something like the path &lt;code&gt;node/369&lt;/code&gt; might look familiar to you. Then consider some example post on this site, accessible through the path &lt;code&gt;andrewberls.com/blog/post/1234&lt;/code&gt;. What's happening in both of these schemes is that we're accessing a piece of content based on its ID in a database. However, these URLs are not particularly revealing - the difference between &lt;code&gt;node/369&lt;/code&gt; and &lt;code&gt;node/254&lt;/code&gt; is a mystery as far as we're concerned. Instead, we'd like to define URLs with a human-readable structure that describes a page's content. This is what a URL alias is -  a readable path that allows us to access a resource. 
We'd like to create aliases for our content so that instead of using database IDs, we can using something more descriptive, perhaps using the content title to get something of the form &lt;code&gt;andrewberls.com/blog/post/my-awesome-post&lt;/code&gt;. Implementing an aliasing scheme is beyond the scope of this article -  instead, this is a small feature I wrote for my blog which automatically suggests paths based on a post's title.
&lt;/p&gt;

&lt;p&gt;&lt;break /&gt;&lt;/p&gt;

&lt;h3&gt;Suggesting a path&lt;/h3&gt;

&lt;p&gt;
The algorithm here is relatively straightforward. Let's say that when we're writing a new post, we're given input fields for the title, body, and URL alias. We're given the option to fill in the alias manually if we'd like, but the task is sort of a pain so we'd like to cover it automatically. When the user enters a title, we have to slice it up and make it 'safe' for a URL, and fill the alias field with the URL. Let's get our setup out of the way:
&lt;/p&gt;

&lt;pre&gt;
&lt;span class="comment"&gt;&amp;lt;!-- HTML --&amp;gt;&lt;/span&gt;
&amp;lt;form&amp;gt;
 &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;title&amp;quot; placeholder=&amp;quot;Title&amp;quot;&amp;gt;
 &amp;lt;textarea placeholder=&amp;quot;Body&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;
 &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;url_alias&amp;quot;&amp;gt;
&amp;lt;/form&amp;gt;

&lt;span class="comment"&gt;# CoffeeScript&lt;/span&gt;
$ -&gt;
  $("#title").bind "propertychange keyup input paste", -&gt;
    url = $(@).val()
    $("#url_alias").val urlsafe(url)
&lt;/pre&gt;

&lt;p&gt;
What are we accomplishing here? We're binding some anonymous function to a mess of events on the title field. When I first starting writing this, I just used the &lt;code&gt;change()&lt;/code&gt; event on the title field, which was only called when the field lost focus (i.e., you enter a title and move on the body). This still worked, but we can do better than that. It would be cool if we filled in the URL alias as the user types the title. By binding our function to all these events, we're monitoring the title field in real time. But what does this anonymous function do? It starts by grabbing the value of the title field. The &lt;code&gt;$(@)&lt;/code&gt; bit looks a bit strange though. In CoffeeScript, &lt;code&gt;@&lt;/code&gt; is a shortcut for &lt;code&gt;this&lt;/code&gt;. As a result, you can use &lt;code&gt;@property&lt;/code&gt; as a shorthand for &lt;code&gt;this.property&lt;/code&gt;, and &lt;code&gt;$(@)&lt;/code&gt; is the same as &lt;code&gt;$(this)&lt;/code&gt;. Once we have the title, it gets passed into some method called &lt;code&gt;urlsafe()&lt;/code&gt; before filling in the alias field. This isn't a built-in method though - we're going to have to define it ourselves! 
&lt;/p&gt;

&lt;h3&gt;The urlsafe() method&lt;/h3&gt;

&lt;p&gt;We need to define a method called &lt;code&gt;urlsafe&lt;/code&gt; that takes in a string and makes it safe for use as a URL. I'll start with another code dump, and then walk through what's going on.&lt;/p&gt;

&lt;pre&gt;
urlsafe = (url) -&gt;
  url = $.trim url
  url = url.replace(/\s+/g, ' ')
  url = url.replace(/[\.,-\/#!$@%\^\*;&amp;:\[\]{}=\-_`~()]/g, '')
  url.split(' ').join('-').toLowerCase()
&lt;/pre&gt;

&lt;p&gt;
This method looks confusing at first, but we'll see that its nothing to be afraid of. We need to think about our goal - what exactly constitutes 'safe' for a URL? For starters, we're going to want to get rid of any whitespace such as spaces or tabs. We start by removing any whitespace at the beginning or end using &lt;a href="http://api.jquery.com/jQuery.trim/"&gt;jQuery.trim()&lt;/a&gt;. The first call to &lt;a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/replace"&gt;replace()&lt;/a&gt; after &lt;code&gt;trim()&lt;/code&gt; covers the edge case of repeated spaces inside the url, and compacts them down to a single space. This is unlikely to occur and not entirely necessary, but we might as well be on the safe side. The next call to &lt;code&gt;replace()&lt;/code&gt; involves an ugly-looking regex that's simple in purpose - we're just removing any punctuation. The chained call to &lt;code&gt;split(' ').join('-')&lt;/code&gt; replaces spaces with hyphens by first splitting the url into an array, separating tokens by spaces, and then just joining it back into a string with hyphens between tokens. Finally, we lowercase the entire thing and return the now-safe URL!
&lt;/p&gt;

&lt;h3&gt;The result&lt;/h3&gt;

&lt;p&gt;
Everything works as expected - the alias field updates in real time, and if you are compelled for reason to name title your post &lt;code&gt;&amp;nbsp;&amp;nbsp;this&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;is@%!*#&amp; the TITLE&lt;/code&gt;, the suggestion comes out to the friendly &lt;code&gt;this-is-the-title&lt;/code&gt;. I've set up a demo page where you can play with the result more &lt;a href="http://andrewberls.com/demos/urlsuggest/"&gt;here&lt;/a&gt;. If you find any issues, hassle me on &lt;a href="http://www.github.com/andrewberls"&gt;GitHub&lt;/a&gt;, and if you use it in any of your projects be sure to let me know on &lt;a href="http://twitter.com/aberls"&gt;Twitter&lt;/a&gt;!
&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/C069VhsulZI" height="1" width="1"/&gt;</content>
    <updated>2012-05-29T04:43:08Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/15</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/14</id>
    <published>2012-05-19T01:11:22Z</published>
    <updated>2012-05-22T08:01:30Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/THWU4Yp0mt0/14" />
    <url>http://andrewberls.com/blog/post/14</url>
    <title>Introducing Cheeky: The responsive grid with Sass</title>
    <content type="html">&lt;p&gt;
&lt;strong&gt;Mobile development doesn't have to be hard.&lt;/strong&gt; That's why I created my latest project - Cheeky.css, a grid system that makes building responsive sites a breeze. It's more important than ever to create mobile-friendly sites, but defining a separate version or stylesheet just for handhelds is a pain. With Cheeky, you only have to style your page once, and your content will automatically scale to fit the browser width.
&lt;/p&gt;

&lt;h3&gt;Using Cheeky&lt;/h3&gt;

&lt;p&gt;
If you've used any grid before, the syntax will be very familiar. Cheeky is based off an 1100px grid with 16 columns contained in rows. 16 is an arbitrary number, but combined with familiar column offsets, you have the freedom to structure your content exactly how you like. To get started, everything is unsurprisingly contained in a &lt;code&gt;&amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;&lt;/code&gt;. From there, you lay out your columns inside a &lt;code&gt;&amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;&lt;/code&gt;, 16 to a row. Columns are defined using the syntax &lt;code&gt;&amp;lt;div class=&amp;quot;span-#&amp;quot;&amp;gt;&lt;/code&gt;, where # is any number between 1 and 16. Offsets are almost identical - just toss on a &lt;code&gt;class=&amp;quot;offset-#&amp;quot;&lt;/code&gt;, except that you can only offset up to 15. Let's take a look at the bare minimum example:
&lt;/p&gt;

&lt;p&gt;&lt;break /&gt;&lt;/p&gt;

&lt;pre&gt;
&amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;
  &amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;
    &amp;lt;div class=&amp;quot;span-8&amp;quot;&amp;gt;This is 8 columns&amp;lt;/div&amp;gt;
    &amp;lt;div class=&amp;quot;span-4 offset-4&amp;quot;&amp;gt;This is 4 columns, offset by 4!&amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;

&lt;p&gt;
That's all there is to it! Once you get used to working with spans and offsets, structuring your content is easy and Cheeky does all the work for you. Nested columns are totally possible as well - just stick in another row and structure nested content the same way. You can find more usage information and downloads &lt;a href="http://andrewberls.github.com/Cheeky/"&gt;here&lt;/a&gt;!
&lt;/p&gt;

&lt;h3&gt;Details&lt;/h3&gt;

&lt;p&gt;
As mentioned before, Cheeky's base is an 1100px grid for desktop screens. Once the browser is resized, CSS media queries are used to progressively scale the grid down to 790px and 630px (In the code, these two states are listed as 'small' and 'tiny' grids). Past that point (portrait phones and below), Cheeky reverts to displaying columns stacked on top of each other. Cheeky is built with Sass (hence the tagline. Don't be misled; it's actually very friendly), so the entire grid system can be customized and tweaked just by changing a few variables.
&lt;/p&gt;

&lt;h3&gt;Tips and Tricks&lt;/h3&gt;

&lt;p&gt;
I learned a great deal about grid-based design and CSS media queries writing Cheeky, and I wanted to pass on a neat Sass trick I just discovered. For example, I use a mixin called &lt;code&gt;width&lt;/code&gt; when defining spans, which takes in an integer and uses it to calculate the correct width. I had written a bunch of code that looked like this:
&lt;/p&gt;

&lt;pre&gt;
.span-1  { @include width(1); }
.span-2  { @include width(2); }
.span-3  { @include width(3); }
.span-4  { @include width(4); }
.span-5  { @include width(5); }
&lt;span class="comment"&gt;/*...on and on, up to 16 */&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;
This went on and on for spans and offsets in all of the various media queries, creating a ton of repetitive code. Then I discovered that it's a perfect candidate for refactoring using a Sass loop, which reduces the example above to something like this: 
&lt;/p&gt;

&lt;pre&gt;
@for $i from 1 to 17 {
  .span-#{$i} { @include width($i); }
}
&lt;/pre&gt;

&lt;p&gt;
That by itself generates the code for 16 classes (it doesn't include the endpoint) including the proper mixin! Turns out that &lt;code&gt;for&lt;/code&gt; is only one of the Sass control directives; &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;each&lt;/code&gt;, and &lt;code&gt;while&lt;/code&gt; are also included. I don't have too much experience with them yet, but you can read more about them &lt;a href="http://thesassway.com/intermediate/if-for-each-while"&gt;here&lt;/a&gt;.
&lt;/p&gt;

&lt;h3&gt;Why?&lt;/h3&gt;

&lt;p&gt;
With a large number of grid systems already available, one might ask why bother writing another one. Cheeky was created entirely as a learning exercise to practice responsive design techniques, and derives much inspiration from the excellent Twitter &lt;a href="http://github.com/twitter/bootstrap"&gt;Bootstrap&lt;/a&gt; project. I'm using Cheeky in production on this site (resize this window!) and several other projects, and it's held up to the task. If you'd like to read more about Cheeky, I've set up a more extensive info page &lt;a href="http://andrewberls.github.com/Cheeky/"&gt;here&lt;/a&gt;, and the project is hosted on GitHub &lt;a href="http://github.com/andrewberls/Cheeky"&gt;here&lt;/a&gt;. Finally, if you use Cheeky in any of your projects be sure to let me know on &lt;a href="http://twitter.com/aberls"&gt;Twitter&lt;/a&gt;!
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update 5/22: As pointed out in the comments, some of the media queries were causing a horizontal scrollbar at certain dimensions. The framework has since been updated to fix this issue.&lt;/em&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/THWU4Yp0mt0" height="1" width="1"/&gt;</content>
    <updated>2012-05-22T08:01:30Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/14</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/13</id>
    <published>2012-05-12T23:13:03Z</published>
    <updated>2012-05-16T21:51:24Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/4F4UlHdP_NE/13" />
    <url>http://andrewberls.com/blog/post/13</url>
    <title>Reducing bad signup emails with mailcheck.js</title>
    <content type="html">&lt;p&gt;
I recently stumbled across &lt;a href="https://github.com/kicksend/mailcheck"&gt;mailcheck.js&lt;/a&gt;, a little jQuery plugin from &lt;a href="http://kicksend.com/"&gt;Kicksend&lt;/a&gt; that suggests domains based on common typos in email forms. For example, 'user@gnail.co' will generate a suggestion for 'user@gmail.com'. It's perfect for preventing errors in user signups, and the authors claim its reduced their email bounces by 50%. After playing around with it, I've decided to bundle it into production for most, if not all of my projects, and this is just a brief demo of what can be done with it.
&lt;/p&gt;

&lt;h3&gt;Getting Set Up&lt;/h3&gt;

&lt;p&gt;
Our goal is to create a simple display that shows email suggestions to the user and offers a way to automatically fill in the field with the suggestion. If you want to play with the end result before we dive into the details, I have a simple demo set up &lt;a href="http://andrewberls.com/demos/mailcheck.html"&gt;here&lt;/a&gt;.

The plugin is used in two steps - first, it has to be attached to a text field, and then you have to actually do something with its suggestions. Let's get the basic JavaScript structure set up (make sure you include the actual plugin on your page as well!)
&lt;/p&gt;

&lt;pre&gt;
&lt;span class="comment"&gt;&amp;lt;!-- The HTML --&amp;gt;&lt;/span&gt;
&amp;lt;input id=&amp;quot;email&amp;quot; type=&amp;quot;text&amp;quot; placeholder=&amp;quot;Email&amp;quot;&amp;gt;
&amp;lt;div id=&amp;quot;hint&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;


&lt;span class="comment"&gt;// The JavaScript&lt;/span&gt;
var $email = $('#email'); &lt;span class="comment"&gt;// Cache jQuery objects into variables&lt;/span&gt;
var $hint = $("#hint");

$email.on('blur', function() {
  $(this).mailcheck({
    suggested: function(element, suggestion) {

    }
  });
});
&lt;/pre&gt;

&lt;p&gt;
The setup is only a few lines, although it's important to understand what's going on. Our HTML is fairly straightforward - we start with a generic input that we'll be using the plugin on. The &lt;code&gt;&amp;lt;div id=&amp;quot;hint&amp;quot;&amp;gt;&lt;/code&gt; is an initially hidden div that will contain our suggestions to the user. In our JavaScript, we're first sticking jQuery objects into variables for convenience. Then we're attaching the &lt;code&gt;mailcheck()&lt;/code&gt; function to our email field on its blur event, which is called whenever the element loses focus (i.e., the user moves on to the next field). Mailcheck takes two callbacks, &lt;code&gt;suggested()&lt;/code&gt; and &lt;code&gt;empty()&lt;/code&gt;. &lt;code&gt;suggested()&lt;/code&gt; is called whenever a suggestion is available for the field, and &lt;code&gt;empty()&lt;/code&gt; whenever the field is left blank. We'll only be using &lt;code&gt;suggested()&lt;/code&gt; in this demo, although depending on how you use the plugin it's generally a good idea to use both.
&lt;/p&gt;

&lt;p&gt;&lt;break /&gt;&lt;/p&gt;

&lt;h3&gt;Using the suggestion object&lt;/h3&gt;

&lt;p&gt;
Mailcheck automatically generates our field suggestions for us, but how do we use them? Note that the &lt;code&gt;suggested()&lt;/code&gt; method from before is passed in two parameters - &lt;code&gt;element&lt;/code&gt;, which is the field that we're checking, and something called &lt;code&gt;suggestion&lt;/code&gt;. If you enter user@gnail.co and use your favorite tool to inspect it, you'll notice it's an object with three fields:
&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/posts/mailcheck_object.png" alt="The mailcheck suggestion object"&gt;&lt;/p&gt;

&lt;p&gt;
We have access to the address (what comes before the @), the suggested domain, and the entire suggested text. We can use these fields to populate and show a hint to the user using the previously mentioned &lt;code&gt;&amp;lt;div id=&amp;quot;hint&amp;quot;&amp;gt;&lt;/code&gt;. Here's how you could go about filling the hint element:
&lt;/p&gt;

&lt;pre&gt;
var $email = $('#email');
var $hint = $("#hint");

$email.on('blur',function() {
  $hint.css('display', 'none'); &lt;span class="comment"&gt;// Hide the hint&lt;/span&gt;
  $(this).mailcheck({
    suggested: function(element, suggestion) {
      if(!$hint.html()) {
        &lt;span class="comment"&gt;// First error - fill in/show entire hint element&lt;/span&gt;
        var suggestion = &amp;quot;Yikes! Did you mean &amp;lt;span class='suggestion'&amp;gt;&amp;quot; +
                          &amp;quot;&amp;lt;span class='address'&amp;gt;&amp;quot; + suggestion.address + &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;
                          + &amp;quot;@&amp;lt;a href='#' class='domain'&amp;gt;&amp;quot; + suggestion.domain + 
                          &amp;quot;&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;?&amp;quot;;
                          
        $hint.html(suggestion).fadeIn(150);
      } else {
        &lt;span class="comment"&gt;// Subsequent errors&lt;/span&gt;
        $(".address").html(suggestion.address);
        $(".domain").html(suggestion.domain);
      }
    }
  });
});
&lt;/pre&gt;

&lt;p&gt;
Before we do anything with the suggestion, we're making sure to hide the hint element. If there's a suggestion, we'll be repopulating it with the suggested domain, but this handles the case that a valid email is entered after we've already suggested a hint. At the beginning of the &lt;code&gt;suggested()&lt;/code&gt; callback, we're checking to see if the hint element is empty (&lt;code&gt;if (!$hint.html()) {...}&lt;/code&gt;). If so, then we can assume it's the user's first error. The suggestion variable is a rather nasty string of HTML that we'll be inserting into the hint element. There are other ways of doing this such as template systems or DOM libraries, but this is a quick and dirty solution. On the first error, we first fill in the hint with our suggestion (&lt;code&gt;$hint.html(suggestion)&lt;/code&gt;) and fade it in by chaining it to jQuery's &lt;a href="http://api.jquery.com/fadeIn/"&gt;fadeIn&lt;/a&gt; method. On subsequent errors, instead of fading in the hint, all we have to do is modify its contents to reflect the new contents of the field. At this point, we should have a working hint!
&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/posts/mailcheck_suggestion.png" alt="Email suggestion to the user"&gt;&lt;/p&gt;

&lt;p&gt;
At this point, we're missing the last piece of the puzzle - I've styled the domain to look like an inviting link, but clicking it doesn't actually do anything. It should be a link automatically fill in the suggestion for you - let's implement it!
&lt;/p&gt;

&lt;pre&gt;
&lt;span class="label"&gt;// After our other code:&lt;/span&gt;
$hint.on('click', '.domain', function() {
  &lt;span class="comment"&gt;// On click, fill in the field with the suggestion and remove the hint&lt;/span&gt;
  $email.val($(".suggestion").text());
  $hint.fadeOut(200, function() {
    $(this).empty();
  });
  return false;
});
&lt;/pre&gt;

&lt;p&gt;
The code is much shorter for this bit - we're using jQuery's &lt;a href="http://api.jquery.com/on/"&gt;on()&lt;/a&gt; method to attach a click handler to the &lt;code&gt;.domain&lt;/code&gt; link. All we're doing is filling in the field with the suggestion text, and fading out the hint, emptying it when it's complete. And that's it! We have a fully functional hint element that displays suggestions to the user and provides a link to automatically fill the suggestion into the field. Be sure to check out the working example &lt;a href="http://andrewberls.com/demos/mailcheck.html"&gt;here&lt;/a&gt; and grab the plugin &lt;a href="https://github.com/Kicksend/mailcheck"&gt;here&lt;/a&gt;!
&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/4F4UlHdP_NE" height="1" width="1"/&gt;</content>
    <updated>2012-05-16T21:51:24Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/13</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/12</id>
    <published>2012-05-02T23:28:00Z</published>
    <updated>2012-05-16T21:51:33Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/IMwNkB7-QB4/12" />
    <url>http://andrewberls.com/blog/post/12</url>
    <title>A fresh coat of paint</title>
    <content type="html">&lt;p&gt;
I'm happy to unveil a much needed makeover for andrewberls.com! I've learned a huge amount since I first started this site what &lt;a href="http://andrewberls.com/blog/post/5"&gt;seems like forever ago&lt;/a&gt;, and I figured it was time to update the site to reflect that.
&lt;/p&gt;

&lt;p&gt;
The process began with a much needed migration to Heroku's &lt;a href="https://devcenter.heroku.com/articles/cedar"&gt;Cedar stack&lt;/a&gt;. Cedar is the successor to the previous Bamboo runtime stack on which my old site was deployed, and the migration was actually surprisingly easy with the help of this &lt;a href="https://devcenter.heroku.com/articles/cedar-migration"&gt;Dev Center article&lt;/a&gt;. Theoretically, Cedar offers all sorts of cool things such as a process model and 'Twelve-factor methodology', but the most important thing for me is support for Rails' 3.1 asset pipeline. This means that I can take full advantage of Sass and CoffeeScript, and easily serve up concatenated/compressed assets in production.
&lt;/p&gt;

&lt;p&gt;
My favorite part is that the new site is fully responsive, thanks to a &lt;a href="http://andrewberls.github.com/Cheeky/"&gt;tiny grid framework&lt;/a&gt; I wrote called Cheeky.css. Syntactically, Cheeky is very similar to other grid frameworks in that you contain content in &lt;strong&gt;rows&lt;/strong&gt;, with 16 columns available for positioning. Once you've defined &lt;strong&gt;spans&lt;/strong&gt; and &lt;strong&gt;offsets&lt;/strong&gt;, Cheeky uses responsive media queries to automatically scale the page as the browser resizes. I'll write more about Cheeky later, but in the meantime you can read more about it &lt;a href="http://andrewberls.github.com/Cheeky/"&gt;here&lt;/a&gt;. Check it out - try resizing your browser on this page!
&lt;/p&gt;

&lt;p&gt;&lt;break /&gt;&lt;/p&gt;

&lt;h5&gt;Tips and Tricks&lt;/h5&gt;

&lt;p&gt;
I'm currently using Eric Martin's &lt;a href="http://www.ericmmartin.com/projects/simplemodal/"&gt;Simple Modal&lt;/a&gt; jQuery plugin for the modals on the front page. I've only played around with it a little bit, but it's been super easy to use and I recommend it.
&lt;/p&gt;

&lt;p&gt;
I also made a new discovery - I'm convinced that &lt;code&gt;box-sizing: border-box;&lt;/code&gt; is the best thing to ever happen to CSS. In the traditional box model, padding adds to the rendered width of an element. This can be confusing sometimes, as elements are wider than their declared widths. This is especially an issue if you want to add padding to an element of width: 100%. In the normal, or &lt;code&gt;content-box&lt;/code&gt; box model, the element will actually break outside of the parent. Enter &lt;code&gt;box-sizing: border-box&lt;/code&gt;! Elements with this property declared will render with their declared width, and padding/borders will cut inside the box. Now you can add padding to elements without breaking a grid layout, or have 100% width form inputs with padding but without ugly hacks!
&lt;/p&gt;

&lt;p&gt;
Let's take a look at a very basic form example:
&lt;/p&gt;

&lt;pre&gt;
&lt;span class="comment"&gt;&amp;lt;!-- The HTML --&amp;gt;&lt;/span&gt;
&amp;lt;form class=&amp;quot;contact-form&amp;quot;&amp;gt;
  &amp;lt;input type=&amp;quot;text&amp;quot; placeholder=&amp;quot;Name&amp;quot;&amp;gt;
  &amp;lt;textarea placeholder=&amp;quot;Enter your message&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;
&amp;lt;/form&amp;gt;

&lt;span class="comment"&gt;/* The CSS */&lt;/span&gt;
.contact-form { padding: 20px; }

input[type="text"], textarea {
  /* The magic bit! */
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;

  margin-top: 15px; /* Space things out a bit */
  padding: 5px;
  width: 100%;
} 
&lt;/pre&gt;

&lt;p&gt;
And now you'll have beautiful inputs with padding that fill the content area! Hooray! We're using the &lt;code&gt;[type="text"]&lt;/code&gt; selector here in order to exclude &lt;code&gt;[type="submit"]&lt;/code&gt;. Note that this is also using the &lt;a href="http://davidwalsh.name/html5-placeholder"&gt;placeholder&lt;/a&gt; attribute, a neat HTML5 feature.
&lt;/p&gt;

&lt;p&gt;
To wrap things up, border-box is a property that can make the box-model a lot more intuitive. However, I'm still wary of using a rule like &lt;code&gt;* { box-sizing: border-box; }&lt;/code&gt; as &lt;a href="http://paulirish.com/2012/box-sizing-border-box-ftw/"&gt;described by Paul Irish&lt;/a&gt;, and one has to keep in mind that browser prefixes are still necessary, so this should be reserved for projects supporting IE8 and up.
&lt;/p&gt;

&lt;h5&gt;What's next&lt;/h5&gt;

&lt;p&gt;
Now that things are nice and pretty on the front end, I plan to dive in and rewrite the blog engine that powers this site. I wrote it when I was first learning Rails, and there's much to be done in the way of refactoring and cleaning up my first attempt. I'll likely be taking a lot of inspiration from Nate Wienert's &lt;a href="http://natewienert.com/codename-obtvse"&gt;Obtvse&lt;/a&gt; project. As always, all the code is open source over at &lt;a href="https://github.com/andrewberls/andrewberls"&gt;GitHub&lt;/a&gt;. I'd love to hear any ideas or criticisms!
&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/IMwNkB7-QB4" height="1" width="1"/&gt;</content>
    <updated>2012-05-16T21:51:33Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/12</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/10</id>
    <published>2012-03-03T00:43:47Z</published>
    <updated>2012-12-26T05:53:39Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/mMMBeHuUWxg/10" />
    <url>http://andrewberls.com/blog/post/10</url>
    <title>The Trouble with Skeuomorphic Design</title>
    <content type="html">&lt;p&gt;&lt;a href="http://andrewberls.com/images/posts/reason2.jpg"&gt;
    &lt;img src="http://andrewberls.com/images/posts/reason2.jpg" alt="Reason DAW"&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
Take a look at that picture for a second or two. If you can tell me at a glance what absolutely any of that does, that you are a much smarter person than I. (Or a producer. One of the two). That's a screenshot from the popular &lt;a href="http://www.propellerheads.se/"&gt;Reason audio software&lt;/a&gt;, and in my opinion it's an absolutely terrible design. At a glance, it's cluttered and non-intuitive, and non-functional elements waste space on the green. Its design is governed by something called a skeuomorph, an extremely prevalent concept in digital interfaces.
&lt;/p&gt;

&lt;p&gt;&lt;break /&gt;&lt;/p&gt;

&lt;h5&gt;What is a skeuomorph?&lt;/h5&gt;

&lt;p&gt;According to Wikipedia, a skeuomorph is "a derivative object that retains ornamental design cues to a structure that was necessary in the original". More simply, a skeuomorph is a design that retains elements of a predecessor or previous design, purely for visual purposes. Even that may be a little tricky to grasp, so I think the best way to become familiar with skeuomorphs is by example. They're just about everywhere we look - I'll focus on skeuomorphs in digital designs, although there are plenty to be found in the physical world as well.
&lt;/p&gt;

&lt;h5&gt;Skeuomorphs in the wild&lt;/h5&gt;

&lt;p&gt;
Digital skeuomorphs are absolutely everywhere. The floppy disk icon for Save, or the scissors to Cut have become ubiquitous, and the paint bucket is classic in illustration programs. And what about the fact that we sort files on our computers into 'folders'? On the web, retailers hold your items in a shopping cart, and buttons seemingly depress when you click them. One that's always annoyed me is the artificial shutter sound on cell phone cameras; regardless, someone thought it was important enough to make a default setting. Many of the digital interfaces we interact with on a daily basis are governed by skeuomorphs without us even thinking about it. But why such a focus on potentially outdated design elements?

&lt;/p&gt;

&lt;h5&gt;Why do we use skeuomorphs?&lt;/h5&gt;

&lt;p&gt;
Most technology has a learning curve associated with it. Skeuomorphs are used to make the transition easier, and to make a new design or concept feel more comfortable and familiar to us. Certain skeuomorphs are universally recognizable, and enable consistency across applications. Others drastically improve usability - Amazon's Kindle is a great device, and it's incredible easy to use because it mirrors the experience of paging through a real book. These are elements that we've come to expect, and they certainly have their place. But I'm writing this post because I think an over-reliance on familar elements can be harmful. The screenshot I posted from Reason is a particularly extreme example that characterizes what happens when too much focus is on emulating a predecessor. At its core, the modular component idea is nice. But the dangling wires clutter and complicate the screen, and extraneous elements such as power cables or cooling fans are gross wastes of space. Alternatively, think about calendar software. Let's say it's late in the week, and you're looking at your weekly view. It's common to see previous days, maybe grayed out, but still present and taking up space. This is a skeuomorphic relic of physical calendars, but digital calendars give us the power to do better. A rolling display containing the week ahead of the current day is a much more efficient display. Simply shifting our focus away from skeuomorphs can allow for much more efficient and elegant interfaces.

&lt;/p&gt;

&lt;h5&gt;It's too late to change&lt;/h5&gt;

&lt;p&gt;
It's hard to argue against the use of skeuomorphs completely. We've come to depend on our familiar interfaces, and even the slightest change would throw people off. Imagine what would happen if a developer decided to use something besides the iconic floppy disk for the Save action in their program. It certainly doesn't seem like a monumental change. But clicking on the floppy disk is a mindless action at this point, and changing it to something else requires thought from the user. Even if it's just a second, people will notice and get annoyed. These skeuomorphs are so ingrained in our everyday experiences that the slighest change throws us off, and so it's difficult to sit here and argue against their merits. It's too late to change the interface elements that we've become so accustomed to. Or is it?
&lt;/p&gt;

&lt;h5&gt;Defining a new generation of experiences&lt;/h5&gt;

&lt;p&gt;
Admittedly, that's a bold title. I try to avoid such grandiose statements, but recent technology has presented us with unique opportunities to define and create new standards of interaction. Think about the common elements of the current generation. My kids will have little context to grasp the idea of a floppy disk - sure, it means 'save', but what on earth is a floppy disk anyways? These things aren't even present in my generation, and yet they live on in our software. The skeuomorphs that are considered perfectly valid (and even expected) in current interfaces are quickly becoming outdated. Computing is rapidly shifting away from the traditional desktop model, and instead enabling an ever more mobile world. iPads and smartphones present an entirely new and more tactile way to interact with our devices, and I fear that too much of a focus on skeuomorphic designs of old spoils the opportunity to create new experiences and interfaces.
&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/mMMBeHuUWxg" height="1" width="1"/&gt;</content>
    <updated>2012-12-26T05:53:39Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/10</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/9</id>
    <published>2012-02-21T17:42:11Z</published>
    <updated>2012-02-21T17:42:11Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/AlEXnBzH3AQ/9" />
    <url>http://andrewberls.com/blog/post/9</url>
    <title>Why one monitor is better than two</title>
    <content type="html">&lt;p&gt;
I interact with two computers on a daily basis. I have a desktop and a laptop, both running Windows. My desktop is a stock Vostro 430 - I haven't done much in the way of customizing the hardware, so it's no powerhouse, but it's capable. The selling point is the monitors, two 24-inch beauties I've acquired over the course of a year or two. On the other hand, my laptop is a wee Vostro V13 (notice a trend?). The hardware is minimal, and the screen is only 13 inches. I bought it primarily for taking notes once I got to college- I didn't expect to use it for much else than notes or the occasional trip, which is why I was surprised when I realized I was doing most of my coding and development on my laptop. After all, I'm a sucker for screen real estate, and here I had the ideal work desktop setup! Big monitors, a nice keyboard, and a &lt;a href="http://store.razerzone.com/store/razerusa/en_US/pd/productID.169416100"&gt;great mouse&lt;/a&gt;. So why was I doing all my work on my laptop?
&lt;/p&gt;

&lt;p&gt;&lt;break /&gt;&lt;/p&gt;

&lt;h5&gt;Focus&lt;/h5&gt;

&lt;p&gt;
Admittedly, it took me a while to realize why I was doing all my work on my dinky laptop and not my desktop. After all, why would I do such a thing? Multiple screens allow me to keep an editor and a browser (or multiple browsers) all open and visible on one desktop. There's infinitely more room for API references, Stack Overflow searches, you name it. I'm not particularly a fan of alt-tabbing all over the place, so the ability to keep everything open at once was like a godsend to me. And yet, most of this website was written on my laptop, along with most of my other web development and school projects of late. I've realized it all boils down to one thing: focus. After all, on a desktop there is indeed more room for browsers/API stuff, etc. But I found it was also enabling distractions. For example, my most common setup was an editor on screen and a testing browser on the other. But being the distractable person I am, I would often find myself pulling up reddit or Hacker News on a peripheral monitor the instant I got bored or temporarily lost focus. It was trivial to pop open a window or tab for something inane or distracting and stop working on my productive enterprises.
&lt;/p&gt;

&lt;p&gt;
Although I find I tend to be able to focus more while I'm working on my laptop, there are still the tradeoffs I mentioned before. Small screens suck, and alt-tabbing is worse. There's not much that can be done about the screen itself, but there are workarounds that can make life more manageable. After some experimenting with virtual desktop programs, I came across &lt;a href="http://virtuawin.sourceforge.net/"&gt;VirtuaWin&lt;/a&gt;, which provides a fairly unobtrusive and functional interface for Windows. I found I could now emulate the advantages of multiple monitors - one for an editor, one for testing, etc. The experience is virtually the same - with some configuration, you can zip back and forth between workspaces in a heartbeat, but without the instant access to distraction. The portability aspect presents a pretty significant advantage as well - as an intern at RingRevenue this summer, I expect to be shuttling a computer back and forth, and the &lt;a href="http://www.appleinsider.com/articles/12/02/10/apple_to_disrupt_notebook_space_with_radically_redesigned_macbook_pros.html"&gt;rumored MacBook Pro redesign&lt;/a&gt; is looking pretty tempting. I'm not a particularly disciplined person, and so I find that the 'confines' of a laptop allow me to sit back and just &lt;span class="italic"&gt;work&lt;/span&gt;, something I wasn't accomplishing as often as I'd like on my desktop. 
&lt;/p&gt;

&lt;h5&gt;Disclaimer&lt;/h5&gt;

&lt;p&gt;
What I'm describing here doesn't necessarily apply to everybody - many people work perfectly fine with desktops and dual monitors. However, I've learned that I'm extremely prone to distraction and  find myself not getting in the "zone" while trying to work at my desk because I'm constantly opening up tabs on another screen. By no means do I plan to get rid of my desktop - it still has its place. But when it comes time for getting work done, I'll take my laptop any day.
&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/AlEXnBzH3AQ" height="1" width="1"/&gt;</content>
    <updated>2012-02-21T17:42:11Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/9</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/8</id>
    <published>2012-02-11T01:23:03Z</published>
    <updated>2012-07-16T15:38:03Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/mW-9KEfYKp0/8" />
    <url>http://andrewberls.com/blog/post/8</url>
    <title>How It's Made: Sutro Post/Tag Associations</title>
    <content type="html">&lt;p&gt;
    As promised last week, today is dedicated to delicious Rails! This post is the first of several in which I'll talk about how the various feature implementations in Sutro, the blog engine that runs this site. In particular, today will focus on what it means to add tags to articles, and how to associate the models underneath.
&lt;/p&gt;

&lt;h5&gt;Models and Associations&lt;/h5&gt;

&lt;p&gt;
    Rails associations are a set of methods that enable us to tie conceptually related models together and describe their relationships. For example, a Car belongs to a Person, and a Customer has many Orders. The association keywords "belongs to" and "has many" are several of the built in associations that Rails provides. We'll see that by specifying the relationships between two models (posts and tags here), we gain access to high-level helper methods that make our lives infinitely easier.
&lt;/p&gt;

&lt;p&gt;
Our first step is the most important - determing the right relationship to use between posts and tags. The complete list of Rails model associations, as well as an explanation of their purpose and usage can be found at the RailsGuide &lt;a href="http://guides.rubyonrails.org/association_basics.html"&gt;here&lt;/a&gt;. So which ones are right for our needs? Well, clearly a post can have many tags. But remember, the relationship must be defined both ways. In that case, a &lt;code&gt;post has_many :tags&lt;/code&gt; and a &lt;code&gt;tag belongs_to :post&lt;/code&gt; relationship seems like the obvious choice. After some thought though, you'll realize that's not right. A post can have many tags, but a tag can also belong to many posts. For example, if a post is tagged with "ruby", the "ruby" tag is not locked to that post. Many posts can be tagged with the same name. So the association we're looking for is &lt;code&gt;has_and_belongs_to_many&lt;/code&gt;. A post has and belongs to many tags, and a tag has and belongs to many posts. This is a mouthful, and gets a bit complicated to put in place, but ultimately, it allows us to call the methods &lt;code&gt;@post.tags&lt;/code&gt; and &lt;code&gt;@tag.posts&lt;/code&gt;, which will be enormously useful. Let's move on to generating our models and migrations!
&lt;/p&gt;

&lt;p&gt;&lt;break /&gt;&lt;/p&gt;

&lt;p&gt;
Fortunately, our tag model is extremely simple. All we care about is the tag name. Let's generate a model to represent our tags - run &lt;code&gt;rails generate model tags&lt;/code&gt; to create the tag model, as well a migration to initialize the corresponding table.
&lt;/p&gt;

&lt;pre&gt;
&lt;span class="label"&gt;# db/migrate/(timestamp)_create_tags.rb&lt;/span&gt;
def change
  create_table :tags do |t|
    t.string "name"
    t.timestamps
  end
end
&lt;/pre&gt;

&lt;p&gt;That's all we have to do in our migration. Make sure to run a &lt;code&gt;rake db:migrate&lt;/code&gt; afterwards. Now let's write the actual associations between our two models!&lt;/p&gt;

&lt;pre&gt;
&lt;span class="label"&gt;# app/models/tag.rb&lt;/span&gt;
class Tag &amp;lt; ActiveRecord::Base
  has_and_belongs_to_many :posts
end

&lt;span class="label"&gt;# app/models/post.rb&lt;/span&gt;
class Post &amp;lt; ActiveRecord::Base
  has_and_belongs_to_many :tags
end
&lt;/pre&gt;

&lt;p&gt;
We're not quite done yet. If you were paying attention, you'll notice we haven't placed any foreign keys anywhere - nothing in either table references the other. For example, let's look at a customer/order relationship. A customer has many orders, and an order belongs to a single customer. The traditional approach would be to place a &lt;code&gt;customer_id&lt;/code&gt; field in the Order table, so that an order now references a Customer by foreign key lookup. But a many-to-many relationship is more complicated. Since we defined that a post has and belongs to many tags, and that a tag has and belongs to many posts, we need an intermediate table to keep track of the associations called a join table. This is a table with two columns only - &lt;code&gt;post_id&lt;/code&gt; and &lt;code&gt;tag_id&lt;/code&gt;. The join table holds no data about either model - purely association data for lookups.
&lt;/p&gt;

&lt;h5&gt;Creating the join table&lt;/h5&gt;

&lt;p&gt;
While join tables may be a tricky concept to master in your head, the implementation is fortunately fairly simple and Rails handles most of the heavy lifting for us. For example, it's Rails convention to define the table name in terms of the two model names in alphabetical order. So, our table joining Posts and Tags will be called &lt;code&gt;posts_tags&lt;/code&gt;. To implement it, all we have to do is generate the appropriate migration using &lt;code&gt;rails generate migration CreatePostTagJoinTable&lt;/code&gt;.
&lt;/p&gt;

&lt;pre&gt;
&lt;span class="label"&gt;# db/migrate/(timestamp)_create_post_tag_join_table.rb&lt;/span&gt;
def change
  create_table :posts_tags, :id =&gt; false do |t|
    t.integer :post_id
    t.integer :tag_id
  end
end
&lt;/pre&gt;

&lt;p&gt;
Note that we're specifying &lt;code&gt;:id =&gt; false&lt;/code&gt; here. Rails automatically adds an id primary key to tables, but since this a pure join table we don't need it. Be sure to run a &lt;code&gt;rake db:migrate&lt;/code&gt; again!
&lt;/p&gt;

&lt;p&gt;
That's all we need to worry about in terms of migrations. Now we have to create an interface for our tags, and the ability to actually add a tag to a post.
&lt;/p&gt;

&lt;h5&gt;has_and_belongs_to_many or has_many :through?&lt;/h5&gt;

&lt;p&gt;
Before I continue, I want to explain a design decision here. If you have experience with Rails, you'll know that we had the option of doing has_many :through instead of has_and_belongs_to_many. For those unfamiliar with the association, has_many :through creates an intermediary model for the relationship. For example, consider a system that tracks appointments for physicians and patients. A physician has many patients, and a patient (potentially) has many physicians, but we need information about the relationship itself as well, such as the appointment time. In this case, we'd want to create the intermediary model Appointments and change our associations so that a &lt;code&gt;physician has_many :patients, :through =&gt; :appointments&lt;/code&gt; and a &lt;code&gt;patient has_many :physicians, :through =&gt; :appointments&lt;/code&gt;. Again, Appointments acts as a join table tracking the relationship, but now we have access to other information about the relationship itself. Other tutorials I've seen have implemented the post-tag association using has_many :through and created an intermediary model called Taggings. This doesn't appeal to me - a direct relationship seems to make more sense, so I've chosen to implement it using has_and_belongs_to_many. For more information, I highly recommend the &lt;a href="http://guides.rubyonrails.org/association_basics.html"&gt;RailsGuide on Associations&lt;/a&gt; or the &lt;a href="http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html"&gt;ActiveRecord Associations ClassMethods Documentation&lt;/a&gt;.

&lt;h5&gt;Adding tags to posts&lt;/h5&gt;
&lt;p&gt;
Before writing out any code, it's critical to sit back and imagine how you want the end result to work. I think of it in terms of a story - here, "when writing a post, I want to input the tags as a comma-separated list and have Rails do the rest of the work". This is possible, but takes a little bit of extra work on our part since we're no longer doing direct input as in a post title, for example. Let's write the corresponding code in our view first.
&lt;/p&gt;

&lt;pre&gt;
&lt;span class="label"&gt;# app/views/admin/posts/new.html.erb&lt;/span&gt;
&amp;lt;%= form_for(:post, :url=&amp;gt;{:action =&amp;gt; 'create'}) do |f| %&amp;gt;  
  &amp;lt;%= f.label :title %&amp;gt;
  &amp;lt;%= f.text_field :title %&amp;gt;

  &amp;lt;%= f.label :body, "Post" %&amp;gt;
  &amp;lt;%= f.text_area :body %&amp;gt;

  &amp;lt;%= f.label :tag_list, "Tags (optional)" %&amp;gt;
  &amp;lt;%= f.text_field :tag_list %&amp;gt;   

  &amp;lt;%= f.submit "Publish" %&amp;gt;           
  &amp;lt;%= link_to "Cancel", dashboard_path %&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;
At this point, you're like to run into an error if you go to the page - after all, our Post model has no attribute &lt;code&gt;tag_list&lt;/code&gt;. We have to define methods to accept this tag list and transform it into a list of Tags associated with this post. Let's go into &lt;code&gt;post.rb&lt;/code&gt; and define the appropriate methods.
&lt;/p&gt;

&lt;pre&gt;
&lt;span class="label"&gt;# app/models/post.rb&lt;/span&gt;
def tag_list
  self.tags.map {|t| t.name }.join(", ")
end
&lt;/pre&gt;

&lt;p&gt;
With that defined, our &lt;code&gt;new&lt;/code&gt; view displays fine, and our &lt;code&gt;edit&lt;/code&gt; view displays the tags in a nicely comma separated list. But this doesn't actually associate any tags with a post yet. To do that, we have to define the special &lt;code&gt;tag_list=&lt;/code&gt; method back in &lt;code&gt;post.rb&lt;/code&gt;.
&lt;/p&gt;

&lt;pre&gt;
&lt;span class="label"&gt;# app/models/post.rb&lt;/span&gt;
def tag_list=(tag_list)
  self.tags.clear &lt;span class="comment"&gt;# For the update method, just in case we're changing tags&lt;/span&gt;
  
  &lt;span class="comment"&gt;# Split the tags into an array, strip whitespace , and convert to lowercase&lt;/span&gt;
  tags = tag_list.split(",").collect{|s| s.strip.downcase}
 
  &lt;span class="comment"&gt;# For each tag, find or create by name, and associate with the post&lt;/span&gt;
  tags.each do |tag_name|
    tag = Tag.find_or_create_by_name(tag_name)
    tag.name = tag_name      
    self.tags &amp;lt;&amp;lt; tag &lt;span class="comment"&gt;# Append the tag to the post&lt;/span&gt;
  end
end
&lt;/pre&gt;

&lt;p&gt;
We're making progress! We can now create posts with associated tags in a successful many to many relationship. Of course, we can't stop here. Tags aren't useful unless you have the ability to filter posts by their tags.
&lt;/p&gt;

&lt;h5&gt;Filtering posts by tag&lt;/h5&gt;

&lt;p&gt;
While it might seem like a good idea to generate a separate controller to handle our tags, I'm going to forgo that step. For now, it's somewhat of a lazy design decision, but we don't need that level of  functionality and instead can just build our filtering into our post controller's list action. Let's do routes first.
&lt;/p&gt;

&lt;pre&gt;
&lt;span class="label"&gt;# config/routes.rb&lt;/span&gt;
match "blog/tag/:tag"  =&gt; "posts#list", :as =&gt; "tag"
&lt;/pre&gt;

&lt;p&gt;
That gives us a simple named path that matches any tag string, such as &lt;code&gt;/blog/tag/ruby&lt;/code&gt; and dispatches it to the list action on the posts controller. In the post controller itself, all we have to do is add a little bit of logic to determine whether or not we're filtering by a tag or just looking at the main blog index.
&lt;/p&gt;

&lt;pre&gt;
&lt;span class="label"&gt;# app/controllers/posts_controller.rb&lt;/span&gt;
def list
    
  if !params[:tag].nil? &lt;span class="comment"&gt;# Are we looking at a tag?&lt;/span&gt;
    @tag = Tag.find_by_name(params[:tag])
    if @tag.nil?
      &lt;span class="comment"&gt;# Redirect if user is trying to look at a non-existent tag&lt;/span&gt;
      redirect_to blog_path
    else           
      @posts = @tag.posts.order("id DESC")
    end
  else
    &lt;span class="comment"&gt;# No tag - display posts as normal&lt;/span&gt;      
    @posts = Post.all.order("id DESC")
  end
                     
end
&lt;/pre&gt;

&lt;p&gt;The actual Sutro implementation is slightly different (I check for status and do some pagination), but I've left those off for brevity. The full controller source is available on GitHub &lt;a href="https://github.com/andrewberls/andrewberls/blob/master/app/controllers/posts_controller.rb"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since we're lumping this in with the existing action, let's add a notice in the view so there's some indication that you're viewing by tag. My solution, although simple, was this:&lt;/p&gt;

&lt;pre&gt;
&lt;span class="label"&gt;# app/views/posts/list.html.erb&lt;/span&gt;
&amp;lt;% unless @tag.nil? %&amp;gt;
  &amp;lt;h1&amp;gt;Tagged: &amp;lt;%= @tag.name %&amp;gt;&amp;lt;/h1&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;This creates an h1 at the top of the page displaying the current tag (if it exists)&lt;/p&gt;

&lt;h5&gt;Finishing touches&lt;/h5&gt;

&lt;p&gt;At this point, we've done all the real work for our tag implementation and now we're just working on presentational stuff. To close, this is how the tag 'pills' are displayed at the bottom of each post. A method called &lt;code&gt;render_tags&lt;/code&gt; is defined in a helper that takes an array of Tag objects (as outputted by @post.tags or similar), and outputs a raw HTML string containing formatted links to each tag's respective path.&lt;/p&gt;

&lt;pre&gt;
&lt;span class="label"&gt;# app/helpers/post_helper.rb&lt;/span&gt;
def render_tags(tag_list)
  raw tags.map { |t| link_to(t.name, tag_path(t.name), :class=&gt; "tag") }
    .join("")
end
&lt;/pre&gt;

&lt;p&gt;Note that the Sutro implementation differs in that I use the same method for the public 'pill' display, and the backend dashboard which is a comma-separated listing. The full code is available &lt;a href="https://github.com/andrewberls/andrewberls/blob/master/app/helpers/posts_helper.rb"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And we're done! We've succesfully created a many to many association between two models, the ability to enter tags with a post, and format them in a nice display. Rails provides powerful helpers to work with complex associations, and this is only a peek at what's possible. If you enjoyed what you read, or want to chide me on my lazy coding habits, make sure to inform me in the comments. Until next time!&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/mW-9KEfYKp0" height="1" width="1"/&gt;</content>
    <updated>2012-07-16T15:38:03Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/8</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/7</id>
    <published>2012-02-03T22:35:52Z</published>
    <updated>2012-05-16T21:52:18Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/w8IIUII8yhg/7" />
    <url>http://andrewberls.com/blog/post/7</url>
    <title>Easily formatting dynamic HTML tags in PHP</title>
    <content type="html">&lt;p&gt;
It's probably somewhat ironic that I'm writing my first code-oriented post about PHP. After all, I'm becoming more of a Rails fanboy the more I learn about it, and putting down PHP is one of my favorite pastimes. That being said, we're about to roll out a Drupal installation over at &lt;a href="http://www.soc.ucsb.edu/sexinfo/"&gt;SexInfo Online&lt;/a&gt;, and so at least a cursory knowledge of PHP is required.
&lt;/p&gt;

&lt;h5&gt;So what are we doing here?&lt;/h5&gt;

&lt;p&gt;I got sick of seeing code that looked like this:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;?php
  while($row = mysql_fetch_array($result)){
    echo "&amp;lt;div class=\"item\"&amp;gt;" . $row['field']; . "&amp;lt;/div&amp;gt;";
  }
?&amp;gt;
&lt;/pre&gt;

&lt;p&gt;I decided that I needed a utility function similar to Rails' own &lt;a href="http://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-content_tag"&gt;content_tag&lt;/a&gt; method, which allows you to do something like this:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;%= content_tag(:p, "Hello World!", :class =&gt; "strong") %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;The function is taking 3 parameters in this case: the type of tag (as a Ruby symbol), the content itself, and optional HTML attributes such as classes or an ID. So let's model our PHP version on this, and write down some sample usage.&lt;/p&gt;

&lt;pre&gt;
&lt;span class="label"&gt;// Our end goal:&lt;/span&gt;
&amp;lt;?php
  $content = "Hello World!";
  echo content_tag("p", $content, array("class" =&gt; "strong"));
  &lt;span class="comment"&gt;// Should return &amp;lt;p class="strong"&amp;gt;Hello World!&amp;lt;/p&amp;gt;&lt;/span&gt;
?&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Let's go about actually implementing this!&lt;/p&gt;

&lt;p&gt;&lt;break /&gt;&lt;/p&gt;

&lt;h5&gt;Getting Started&lt;/h5&gt;

&lt;p&gt;Our first step is to think about the parameters that our &lt;code&gt;content_tag()&lt;/code&gt; method will accept, but we've already covered that. We need to be able to specify the type of tag, the content, and optional attributes. Let's write our basic skeleton.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;?php
  function content_tag($tagName, $content, $attr=array()) {
    &lt;span class="comment"&gt;// Implementation later!&lt;/span&gt;
  }
?&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Nothing too complicated here. The &lt;code&gt;$tagName&lt;/code&gt; and &lt;code&gt;$content&lt;/code&gt; variables will be passed in as strings. Attributes are slightly more tricky; we're giving them a default value of a blank array, and will handle them as key-value pairs when used, e.g., &lt;code&gt;"class" =&gt; "strong"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Before we move on and start writing code, let's think about what an HTML tag actually consists of. Take a look at this simple tag:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;p&amp;gt;Hello World!&amp;lt;/p&amp;gt;
&lt;/pre&gt;

&lt;p&gt;This is about as simple as it gets. It consists of a the opening tag (&lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt;), the content, and the closing tag(&lt;code&gt;&amp;lt;/p&amp;gt;&lt;/code&gt;). Already some helper methods are becoming apparent: one each for the opening and closing tag. The methods will be very similar: each one needs to take in a &lt;code&gt;$tag&lt;/code&gt; parameter so that the appropriate tag can be output, but the opening tag also needs to account for possible HTML attributes. Let's start backwards and write the &lt;code&gt;close_tag()&lt;/code&gt; method first.&lt;/p&gt;

&lt;h5&gt;The close_tag() method&lt;/h5&gt;

&lt;p&gt;This is simplest helper method we'll be writing. All we need to pass in is the type of tag to be closed!&lt;/p&gt;

&lt;pre&gt;
&amp;lt;?php
  function close_tag($tag) {        
    return "&amp;lt;/" . $tag . "&amp;gt;";
  }
?&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Not a whole lot to say there. Onwards!&lt;/p&gt;

&lt;h5&gt;The open_tag() method.&lt;/h5&gt;

&lt;p&gt;Our job gets a little bit trickier here. The tag itself is very simple, similar to &lt;code&gt;close_tag()&lt;/code&gt;, except that we need to account for HTML attributes as a possible parameter. As I mentioned before, attributes will be handled as key-value pairs in an array. To translate this into HTML, we need to loop through all the pairs in our attribute array and output it as &lt;code&gt;key="value"&lt;/code&gt;. Let's put this in a helper method to prevent our &lt;code&gt;open_tag()&lt;/code&gt; method from getting cluttered, and call it &lt;code&gt;generate_attr_string()&lt;/code&gt;, a function which will take a single array parameter.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;?php
  &lt;span class="comment"&gt;// Example usage: generate_attr_string(array("id" =&gt; "nav", "class" =&gt; "item"));&lt;/span&gt;
  &lt;span class="comment"&gt;//=&gt; id="nav" class="item"&lt;/span&gt;
  
  function generate_attr_string($attr) {
    $attr_string = null;
    if (!empty($attr)) {
      foreach ($attr as $key =&gt; $value) {
        &lt;span class="comment"&gt;// If we have attributes, loop through the key/value pairs passed in&lt;/span&gt;
        &lt;span class="comment"&gt;//and return result HTML as a string&lt;/span&gt;
        
        &lt;span class="comment"&gt;// Don't put a space after the last value&lt;/span&gt;
        if ($value == end($attr)) {
          $attr_string .= $key . "=" . '"' . $value . '"';
        } else {
          $attr_string .= $key . "=" . '"' . $value . '" ';
        }
      }
    }       
  return $attr_string;      
}
?&amp;gt;
&lt;/pre&gt;

&lt;p&gt;That's a little ugly, but it makes our &lt;code&gt;open_tag()&lt;/code&gt; method trivial to finish. Let's wrap that up.&lt;/p&gt;

&lt;pre&gt;
&amp;lt;?php
  &lt;span class="comment"&gt;// Example usage: open_tag("p", array("id" =&gt; "nav", "class" =&gt; "item"));&lt;/span&gt;
  &lt;span class="comment"&gt;//=&gt; &amp;lt;p id="nav" class="item"&amp;gt;&lt;/span&gt;
  
  function open_tag() {
    $attr_string = generate_attr_string($attr);
    return "&amp;lt;" . $tag . " " . $attr_string . "&amp;gt;"; 
  }
?&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Starting to see how &lt;code&gt;content_tag()&lt;/code&gt; is going to work? Stay tuned - we're almost there!&lt;/p&gt;

&lt;h5&gt;The Final Function&lt;/h5&gt;

&lt;p&gt;At this point we're really just stringing together our utility methods, using our parameter signature from before. Let's see how it looks!&lt;/p&gt;

&lt;pre&gt;
&amp;lt;?php
  function content_tag($tagName, $content, $attr=array()) {
    return open_tag($tagName, $attr) . $content . close_tag($tagName);
  }
?&amp;gt;
&lt;/pre&gt;

&lt;p&gt;It's almost a disappointing finish - all the fun was in the helper methods! You could put keep all of the code in the &lt;code&gt;content_tag()&lt;/code&gt; method if you wanted to, but I generally try to keep everything separated out into functions. Your choice. Anyways, I hope that you find this function useful one day - the use case I described in the beginning of this post was trivial, but I find this comes in handy when looping through results returned by MySQL or similar.&lt;/p&gt;

&lt;p&gt;Anyways, that's hopefully the last I'll speak of PHP for a while. I promise the next code post will be delicious Rails :)&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/w8IIUII8yhg" height="1" width="1"/&gt;</content>
    <updated>2012-05-16T21:52:18Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/7</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/6</id>
    <published>2012-01-27T23:18:20Z</published>
    <updated>2012-02-19T18:45:24Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/K_1y7DukUj0/6" />
    <url>http://andrewberls.com/blog/post/6</url>
    <title>Are there any questions?</title>
    <content type="html">&lt;p&gt;
On Wednesday, I went to an information session hosted by the gentlemen over at &lt;a href="http://www.ringrevenue.com/"&gt;RingRevenue&lt;/a&gt;. They were there to give a presentation about what call performance marketing is all about and share some cool details about their Rails setup on the backend. There was maybe 20 people in the room at most - it was an ideal environment, very laid back and personal. But that's not what I'm writing to talk about - I'm writing to talk about a strange phenomenon that I've seen again and again in that setting. After the end of the presentation, the PowerPoint was turned off and the presenter asked "so, are there any questions?"
&lt;/p&gt;

&lt;p&gt;Silence.&lt;/p&gt;

&lt;p&gt;
It's the weirdest thing. Here I am in a room with a bunch of presumably intelligent CS undergrads and some incredibly smart engineers at a neat startup that's working on some big things. And yet, they're met with this awkward air of silence that just kinds of hangs over the room. I've seen this happen before at countless information sessions. And I always wonder what it is that prevents people from asking questions. Is it because there's nothing to ask? Perhaps partially. These guys are here talking about a vastly complicated enterprise-class platform. I didn't even know what "high ROI call performance tracking" meant going into the session. But my guess is that this stunned silence stems from something greater - fear. It's the fear of being singled out, of asking a "dumb question", or just interacting with someone you perceive to be smarter than you are. I've been guilty of it myself; I usually don't like to speak up when I'm in a large group of people. But the result is that you have a room full of people wasting an opportunity that's very literally presenting itself to them.
&lt;/p&gt;

&lt;p&gt;&lt;break /&gt;&lt;/p&gt;

&lt;h5&gt;Be Conversational&lt;/h5&gt;

&lt;p&gt;
I broke the silence and asked a question or two about scability issues with their Rails deployment. An easy start - it gets somebody talking. All of these presenters have done this many times, and pretty clearly love to talk about what they do. And I think that showing interest and getting somebody talking is the key to getting value (and a job!) out of these sessions. When you think of it as a conversation as opposed to a stiff me-vs-them panel scenario, you can have a lot of fun. One of my favorite questions to ask in these settings is something along the lines of "given the size of your company, do you feel that your (personal) contributions are visible in the company or the product?". I'm actually interested in the answer, and I think it's a question that should be asked, but more importantly, it leads into twenty other related questions. At that point, a previous intern piped up and talked about what she had done in her time there, and how she really felt like her contributions made a difference. Cool. At that point, you can start asking about the workflow. How do you interact with the other employees? What's the daily routine like? Do you find that all employees working in the same room leads to more distractions? Etc, etc, etc. It's all about finding that one entry question that leads to all the others, and not being the person who shows up with nothing to contribute (or take away).
&lt;/p&gt;

&lt;h5&gt;Be Exceptional&lt;/h5&gt;

&lt;p&gt;
This post is about more than awkward silences at information sessions. It's about how even once the conversation gets going, there's still the percentage of people in the room who say nothing. After the Q&amp;amp;A ends, it's the people who silently leave the room without chatting with the presenters. It strikes me as a waste of effort - after all, you came out to the information session. Step one! But step two is the most important, and I've seen a lot of people pass up the opportunity to spend five or ten minutes to schmooze with smart people. I recently read a &lt;a href="http://www.inc.com/magazine/20030101/25049.html"&gt;great article&lt;/a&gt; on so-called "master networker" Keith Ferrazzi. Now, I'm not saying everybody should strive to be at a point where they need two Palm Pilots to track all their contacts, or make a living out of knowing people. But networking is a critical skill in life, and information sessions like the one I went to are sort of a baby step into making contacts. There was one line from that article in particular that I will always remember. The author of the article, Tahl Raz, was attending a lunch with Ferrazzi and a TV executive, and at one point, Ferrazzi leaned over and said, "You're a fucking loser if you don't walk out of here with some reason for getting in touch with her again". Now, Mr. Ferrazzi's approach may be a little harsh, but the idea remains true. Find a reason to get in touch with people again. Get your face in their memory. It only takes a question or two.
&lt;/p&gt;

&lt;h5&gt;It's about doing more.&lt;/h5&gt;

&lt;p&gt;
Now, let's say you took that advice to heart and became a networker. People know your name. You know people in high places. Unfortunately, you only have half of the puzzle completed. If you know all the right people in all the right places but can't follow through then you're still no better off than before. What does it meant to follow through? Simply put, be the best at what you do. Be able to bring something to the table. I see many of my peers sort of 'coasting' through undergraduate computer science classes. If you ask them what their favorite programming language is, they respond with "C++, because it's the only thing we've learned in school". There's nothing wrong with C++ in itself (perhaps debatable - another time). It's the second half of that sentence that gets me every time. "It's the only thing we've learned in school". How can you possibly stand out to recruiters, employers, or anybody if you only do the bare minimum that's asked of you? There is by no means a shortage of CS undergrads. If you want to find yourself at the head of the pack, then you have to do more. And it doesn't take a slavish commitment to programming for 19 hours a day to stand out. You don't have to freak out and give up because you haven't written the next Facebook by now. It's the people who do things for the fun of it that will get ahead. It's the tinkerers, the hackers, the builders, the ones who take things apart and put them back together again. It's the people who write code and learn languages for kicks or try to write a program just to see if it's possible. These are the people who will become leaders and show up in the news one day. So don't be one of the people with a degree and no real direction to turn. There are thousands of resources out there to get started with, and people much smarter than you. Ask questions. Do more. Have fun.
&lt;/p&gt;

&lt;p&gt;Are there any questions?&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/K_1y7DukUj0" height="1" width="1"/&gt;</content>
    <updated>2012-02-19T18:45:24Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/6</feedburner:origLink></entry>
  <entry>
    <id>tag:andrewberls.com,2005:Post/5</id>
    <published>2012-01-18T22:28:57Z</published>
    <updated>2012-07-16T15:40:12Z</updated>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/andrewberls/~3/MJ7ySfaQFSg/5" />
    <url>http://andrewberls.com/blog/post/5</url>
    <title>Hello World!</title>
    <content type="html">&lt;p&gt;Even though this is the obligatory 'Hello World' post, it feels like it's been forever since I started work on planning and building this site. In early fall of last year, I was gifted the domain andrewberls.com. I had no particular use for it at the time, but it seemed like a handy thing to hold on to. I decided I wanted to build a portfolio site for myself, to show off a little of what I've done up until this point and shamelessly promote myself. After completing the first iteration while also frantically trying to juggle schoolwork, I decided that the site needed more to it. Everybody has a blog, and I wasn't going to be the exception. I pondered my options- I posted on tumblr for the time being and thought about throwing a Wordpal or Drupal installation onto my domain, but that seemed unexciting. Nobody cares if you can install Wordpress, and I wanted to focus on improving my technical knowledge and abilities rather than actual writing (god forbid) anyways. The result you see here is powered by Sutro, a blogging engine I wrote from scratch using Ruby on Rails.&lt;/p&gt;

&lt;p&gt;Going into all of this, I had absolutely no clue what Rails was all about, and had never used most of the tools I needed in any significant application. I had started learning a few snippets of PHP towards the end of the summer, and so the initial application was written in PHP. I started on the portfolio section, and only needed some basic scripting for the Contact form, so it seemed like a good fit. When I decided to write the blogging software as well, it was pretty clear that I would need a better solution, and so I had a good excuse to go learn Rails.&lt;/p&gt;

&lt;p&gt;In building this site, I've learned more than I could have possibly imagined. The various features I chose to initially implement forced me to finally learn Ruby and what Rails was all about, the  model-view-controller architecture, databases, authentication algorithms, optimization techniques, and some sneaky JavaScript tricks with a healthy dose of jQuery. It's not to say that I didn't know anything about these beforehand, but I'm a firm believer in that the only way to truly learn something is to get your hands dirty and work with it. I decided fairly early on that I wanted to avoid third-party plugins and pre-written code as much as possible. It's not because I don't see their value- to the contrary, I'm an advocate of letting other people do the heavy lifting for you, and believe it to be a best practice - but I wanted to make this a learning experience as much as possible for myself and see what I could accomplish from scratch. Some of the resulting features - slideshows, contact forms, etc, are a little rough around the edges, but they work and I get to say that it's something I wrote.&lt;/p&gt;

&lt;p&gt;&lt;break /&gt;&lt;/p&gt;

&lt;h5&gt;Behind the Scenes&lt;/h5&gt;

&lt;p&gt;The front end of the site is fairly straightforward.  I use the &lt;a href="http://code.google.com/p/zen-coding/"&gt;Zen Coding&lt;/a&gt; plugin with &lt;a href="http://www.aptana.com/"&gt;Aptana Studio&lt;/a&gt; as my primary editor environment. All of the CSS is processed through &lt;a href="http://sass-lang.com/"&gt;Sass&lt;/a&gt;, and most of the JavaScript is handled by jQuery. None of these particular tools are critical to the project or its structure, but they make life much easier, and save heaps of time. On the back end, I'm running Ruby on Rails with PostgreSQL deployed to Heroku (with Zerigo DNS to route back to BlueHost), which is a result of many, many hours of tearing my hair out over obscure bugs and errors. All of the source code is managed by Git and hosted on &lt;a href="https://github.com/andrewberls/andrewberls"&gt;GitHub&lt;/a&gt;. I'm still new to using Git, and so the freely-available &lt;a href="http://progit.org/book/"&gt;Pro Git&lt;/a&gt; has been invaluable in helping me get off the ground. As much as I wanted to avoid plugins, I had to cave on several things where it's simply too inconvenient to avoid. I use BCrypt for password hashing and salt generation, and &lt;a href="https://github.com/mislav/will_paginate/wiki"&gt;will_paginate&lt;/a&gt; for pagination of the post display (which is awesome for simple applications). What you see here is only half of the end result - everything is supported by a custom-built backend providing administrative views and actions on posts, as well as primitive support for multiple users with permission levels.&lt;/p&gt;

&lt;h5&gt;Design&lt;/h5&gt;

&lt;p&gt;I've gone back and forth on the design of the site. From the beginning, I knew I wanted a single-page scrolling layout for the front page, and a strong focus on clean, minimalist design. As it turns out, I'm terrible at design and coming up with something attractive and professional-looking is difficult to do. I constantly wavered on color palettes and layouts, and ended up changing the look of the blog at the very last minute. The design is heavily influenced by Twitter's &lt;a href="http://twitter.github.com/bootstrap/"&gt;Bootstrap&lt;/a&gt; framework which is absolutely brilliant, and I'll definitely be using it on my next project. The two tools I can no longer live without are &lt;a href="http://colorschemedesigner.com/"&gt;Color Scheme Designer&lt;/a&gt; and Eric Meyer's &lt;a href="http://meyerweb.com/eric/tools/color-blend/"&gt;Color Blender&lt;/a&gt;.&lt;/p&gt;

&lt;h5&gt;Looking Back&lt;/h5&gt;

&lt;p&gt;This may seem like a fairly trivial application in the end. Blogging software is actually relatively simple conceptually to write: a couple of forms POST to controllers which save the data and essentially spit it back out to the views for display. That's a generalization of course: the tricky bits are all in the tiny details in getting the bigger concepts to work, and I consider it a personal accomplishment. This is one of the first significant "real" projects I've worked on, and something I completed of my own volition. It's been fascinating to watch the project evolve, even from my own viewpoint. Since everything is hosted on GitHub, I can go back in time through the commit history and look at day one, where it was a single page written in PHP, up through where I first migrated to Rails (and wrote some pretty nasty code), and finally up to where the project is now.&lt;/p&gt;

&lt;h5&gt;The Future&lt;/h5&gt;

&lt;p&gt;So what's next? The site is not finished it any sense of the word. I have the ability to write and administer posts, which was my initial goal, but I plan to continue to expand the project in my free time. I only just touched on multi-user CMS-style support, and I have no shortage of refactoring and cleaning up to do (past me is a real slob). I have plenty of other projects on my plate as well. I'll be rolling out a complete rewrite of &lt;a href="http://www.soc.ucsb.edu/sexinfo/"&gt;SexInfo Online&lt;/a&gt; in the weeks to come. I'm also just starting to look more closely into JavaScript and the HTML5 canvas element as part of writing a scrolling browser game for a class. I'll be writing posts about all of these in the future, as well as more in-depth looks at some of the various Sutro feature implementations with tips and tricks.&lt;/p&gt;

&lt;h5&gt;Goodbye World (for now)&lt;/h5&gt;

&lt;p&gt;If you're interested, be sure to check out the nitty gritty implementation over on &lt;a href="https://github.com/andrewberls/andrewberls"&gt;GitHub&lt;/a&gt;, or &lt;a href="http://andrewberls.com/#contact"&gt;shoot me an email&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Oh, and the best part? This entire thing was developed on a Windows environment. How's that for a healthy dose of sadomasochism? ;)&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/andrewberls/~4/MJ7ySfaQFSg" height="1" width="1"/&gt;</content>
    <updated>2012-07-16T15:40:12Z</updated>
  <feedburner:origLink>http://andrewberls.com/blog/post/5</feedburner:origLink></entry>
</feed>
