Matt Gauger's posterous http://blog.mattgauger.com vegan code monkey. bike crash test dummy. coffee snob. posterous.com Fri, 17 Feb 2012 09:20:00 -0800 MadJS February 2012 - How CoffeeScript & Jasmine Made Me a Better JavaScript Developer http://blog.mattgauger.com/madjs-february-2012-how-coffeescript-jasmine http://blog.mattgauger.com/madjs-february-2012-how-coffeescript-jasmine

Recently, I spoke at the MadJS group about CoffeeScript & Jasmine. My slides appear below. Since Slideshare doesn't show my notes, you can either download the keynote file above, or you can read the notes below, which I've pulled out of the slides. I feel that the notes are necessary to know what I'm talking about, and I hate reading slide decks where there's no context or notes. This isn't going to be as helpful as having seen my talk in person, but hopefully you get some value out of my talk and the notes together:

How CoffeeScript & Jasmine made me a better JS developer

First, an introduction:

  • I’m Matt Gauger
  • @mathiasx on twitter

I work at Bendyworks

  • We primarily do Ruby on Rails work, with iOS now.
  • We care very deeply about software craftsmanship and honing our agile practices.

Which leads me to my dilemma

  • Are you familiar with impostor syndrome?
  • It's the idea that even very skilled practitioners may sometimes feel like an impostor due to over-emphasizing their weaknesses.
  • Further, it’s the inability to internalize your own accomplishments.

I felt like an impostor when it came to JavaScript.

  • Of course, I could read and write the syntax, pull in jQuery, manipulate the DOM, etc.
  • I had several projects under my belt at this time that used AJAX and were fairly complex
  • I'd even read JavaScript: The Good Parts several times, taken notes, etc.

So, what does this have to do with CoffeeScript?

  • My thesis: How CoffeeScript & Jasmine made me a better JS developer (and how it can help you, too)
  • But before that: Let me warn you that I'm not going to go over every piece of syntax here.
  • I'm not going to be able to teach you all of CoffeeScript or Jasmine in this talk.
  • For that, see the resources & books at the end of the talk.

CoffeeScript History

  • 2010 I learn about CoffeeScript, and it sort of looks like Ruby and Python.
  • It grabs my interest.
  • But at that point it's still a novelty: The compiler is in Ruby, no one uses it for real dev yet.
  • It was a *toy*

Today

  • Flash-forward to today, and everyone is extolling CoffeeScript.
  • It comes with Rails 3 by default now and gets compiled on the fly into JS for your app.
  • I’ve been using CoffeeScript for about a year now.

CoffeeScript has Good Parts?

So why use CoffeeScript? What are its good parts?

  • It restricts you to a subset of JS you’d recognize from JS: The Good Parts.
  • It puts JSLint & a compiler between me and the half dozen browsers I need to support
  • It warns me when I do something wrong

This might be the most important part of the talk, and reason to use CoffeeScript

  • If you’re like me, you’ll put the compiled JS up next to the CoffeeScript
  • By reading the output of the compiler, you’re learning what good JS looks like.

Criticisms of CoffeeScript:

  • It's not what runs in the browser.
  • Difficult to debug => Finding bugs (Names are the same between CoffeeScript & JS; its readable)
  • May feel like you’re learning a whole different language (It’s not, it’s less verbose JS)

That isn't to say that CoffeeScript eliminates all bugs

  • At this point we may want to differentiate between bugs that are caused by poor syntax and mistakes (mistake bugs), and bugs that come from the interaction between complicated data & edge cases (ie computer is in a state you didn't predict when you wrote the code)
  • CoffeeScript can help cut down on a lot of the former.

Some examples of CoffeeScript helping you with bugs:

Coercing the wrong types

  • This will print it’s true happily.
  • That’s not quite what you expect when the data is more complicated than 1 and the string 1.
  • Type coercion is the number 1 reason for WTFJS
  • Ok, so that’s a very simple example.
  • But how often are you going to get bitten by more complicated versions of that same bug?
  • And are you always going to remember to use triple equals? === I am now.

Scope

  • CoffeeScript scope is essentially the same as in JS
  • JS and CoffeeScript have “lexical scope”
  • 1. Every function creates a scope, and the only way to create a scope is to define a function.
  • 2. A variable lives in the outermost scope in which an assignment has been made to that variable.
  • 3. Outside of its scope, a variable is invisible.
  • The neat thing is that CoffeeScript’s compiler places the vars for each scope at the top of that scope
  • Define a variable at a specific scope by giving it a sensible initial value
  • Hopefully this is better than ‘null’, but you could do worse and just not initialize it at all.
  • JavaScript won’t force you to initialize it, but doing so can help you to figure out scope issues.

a ?= b

  • the ?= is syntactic sugar, the ? is called the existential operator in CoffeeScript
  • Combined with =, the existential operator means “a equals b unless a?” or
    • “Let b be the default value for a.”

Lastly, wrapping up your code.

  • CoffeeScript can wrap each compiled file into a scope
  • This may be the default, depending on the version of coffeescript you’re using - you might need to pass an option now to either wrap or not wrap your code in a scope.
  • This is actually pretty cool -- if you’re including a lot of JavaScripts on a website, you can’t mix scope there -- no accidental leakage into the global scope space.
  • Compiled CoffeeScript Example:
(function() {
  console.log "hello world!";
}).call(this);

Simpler Looping

  • You write list comprehensions rather than for loops in CoffeeScript
  • Comprehensions are expressions, and can be returned and assigned

Jeremy Ashkenas’s Example

  • Loop over every item in a list, in CoffeeScript:
for item in list
  process item

Intention gets obscured by managing the loop, in JS:

for (var i = 0, l = list.length; i < l; i++) {
  var item = list[i];
  process(item);
}
  • CoffeeScript allows “reasonably solid” JavaScript developers to accomplish the latter by simply writing the former.
  • In Review: CoffeeScript will help you:

    • Write OO, Prototype-based code
    • Avoid bugs in comparisons
    • Stop using ==, only use ===
    • Manage scope and avoid state through scope creep
    • Reduce off-by-one errors in looping, and generally write better loops than you were writing before

    Jasmine

    (My) History (with Jasmine)

    • I started using Jasmine last summer on a client project.
    • It’s enough like the BDD tool we use in Rails, Cucumber, that I consider it a BDD tool.
    • It makes the most sense to me of the BDD/TDD tools in JS I’ve used

    Why Jasmine?

    • All code should be tested => that’s what I believe.
    • You can spend some up-front time testing your code, or you can spend a lot of time bug fixing later
    • I realize that not all legacy codebases are going to have full test coverage overnight.

    The example on the Jasmine site:

    describe("Jasmine", function() {
      it("makes testing awesome!", function() {
        expect(yourCode).toBeLotsBetter();
      });
    });
    • This example sucks!
    • A better example:
    describe ('addition', function() {
      it('adds two numbers', function() {
        expect(1 + 2).toEqual(3);
      });
    });
    • Better? Not really. But we can see what the syntax is doing here and I’m using a real assertion!

    How should we test JS?

    • Functions should not depend on the DOM
    • Our Logic needs to be in separate pieces
      • to make it easier to test the logic, things like AJAX calls, etc
      • without interacting with the DOM

    Easier to test = better code

    • it just so turns out, that the abstraction for testing is a better abstraction overall
    • I've heard "The first implementation of your code is the unit tests" so it may not be DRY, but tests should show how to implement your code!

    Follow TDD/BDD:

    red, green, refactor

    • You can still do this in Jasmine, in fact, I find it kind of natural.

    Jasmine is designed to be standalone

    • This means you don’t need jQuery and you don’t need to run it in a real browser (but you can)

    Some really cool features of Jasmine:

    Matchers:

    • .toBe()
    • .toBeNull()
    • .toBeTruthy()
    • .toBeDefined()
    • .toBeUndefined()

    Setup and teardown:

    beforeEach()
    afterEach()
    • You can use after Each to run a teardown function after each successful test
    • If you need a teardown function after a test whether it passed or failed, use after()

    Spies: built-in mocking & stubbing

    • In Ruby, we’ve been doing mocking and stubbing for awhile.
    • Jasmine’s spies make it easy!
    • These let you do things like watch to see if a method was called
    • Or to stub out other methods so you don’t do real AJAX calls, etc.

    But what about legacy codebases?

    • So you’re thinking, "CoffeeScript and Jasmine sound great, but I have a legacy codebase."
    • Or, "I’ll never get to use either; and they don’t help my big legacy codebase."
    • Well, we’ve run into this and I have a plan.

    Start simple.

    • First, get your tools lined up.
    • Get the CoffeeScript compiler in your tool chain
    • Get Jasmine set up and passing a dummy test.
    • You still haven’t done anything with your legacy code at this point.

    Fix one bug.
    (red, green, refactor)

    • It all starts with one bug. Or one feature, if you’re feeling adventurous. 
    • You might not be able to pull out an entire feature and rewrite it. I understand that. Don't give in to this temptation yet!
    • The way to start this is to write a test around the bug and see it fail. (this might be hard -> depending on how tied your code is to the DOM -- see Jasmine-JQuery for DOM Fixtures)
    • Then fix the bug in regular old JavaScript. See the Jasmine test pass.

    Rewrite the affected code in CoffeeScript.

      You’ve got a working test around this bug.
    • (You know the test works because you saw it red then green.)
    • Now’s your chance to rewrite it in CoffeeScript. It may only be one function at this point. That’s ok.

    Start grouping in files / modules.

    • We found that even with a legacy codebase of a lot of JavaScript, we were able to figure out logical chunks that should live together in CoffeeScript files.

    Keep improving the codebase.

    • This is the hardest part.
    • The temptation is there to just give up and fix bugs only in JS, not to write unit tests, etc.
    • The other temptation is the one you usually can’t give into, which is to try to rewrite everything all at once -> this rarely is accomplishable, it’s better to stage the changes.
    • The big rewrite doesn't work!

    Lessons Learned:

    •  These tools can help you learn JS better.
    • Legacy codebases can slowly grow better through using CoffeeScript & Jasmine.
    • Taking advantage of these is up to you!

    Thanks!

    Resources to learn more:

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Sat, 21 Jan 2012 17:28:58 -0800 Invalid gemspec in [.rvm/gems/ruby-1.9.2-p180@gemset/specifications/actionmailer-3.2.0.gemspec]: Illformed requirement ["# 3.2.0"] http://blog.mattgauger.com/invalid-gemspec-in-usersmathiasxdeveloperrvmg http://blog.mattgauger.com/invalid-gemspec-in-usersmathiasxdeveloperrvmg

    Recently while trying to create a new Rails 3.2 project, I ran into this error after creating a new RVM gemset in Ruby 1.9.2-p180 and a Gemfile requiring only Rails 3.2.0:

    $ bundle
    Fetching source index for http://rubygems.org/
    Installing rake (0.9.2.2) 
    Installing i18n (0.6.0) 
    Installing multi_json (1.0.4) 
    Installing activesupport (3.2.0) 
    Installing builder (3.0.0) 
    Installing activemodel (3.2.0)
    Invalid gemspec in [/Users/mathiasx/Developer/.rvm/gems/ruby-1.9.2-p180@big_fan/specifications/activemodel-3.2.0.gemspec]: Illformed requirement ["# 3.2.0"]
    ... These Illformed requirement errors continue for every package Rails wants ...

    I thought that I might be able to continue on and ignore these errors, but I hadn't seen anything like them anymore.

    $ rails new .
    Invalid gemspec in [/Users/mathiasx/Developer/.rvm/gems/ruby-1.9.2-p180@big_fan/specifications/actionmailer-3.2.0.gemspec]: Illformed requirement ["# 3.2.0"]
    ... again, it throws this error many times ...

    That didn't generate a new Rails project in my current directory, so something was clearly wrong. But what does Illformed request: Syck:DefaultKey mean? Well, it turns out that the gemspecs of requirements in Rails 3.2.0 are using a new format that older Rubygems can't parse. The first indicator was that my version of Rubygems was out of date:

    $ gem -v
    Invalid gemspec in [/Users/mathiasx/Developer/.rvm/gems/ruby-1.9.2-p180@big_fan/specifications/actionmailer-3.2.0.gemspec]: Illformed requirement ["# 3.2.0"]
    ... I've cut out a bunch of the output from the invalid gemspecs here ...
    1.8.8

    We'd like to be on Rubygems 1.8.13 or newer, but I also don't want to see those invalid gemspec warnings anymore, so I clear out my gemset with:

    $ rvm gemset empty
    WARN: Are you SURE you wish to remove the installed gemset for gemset 'ruby-1.9.2-p180@big_fan' (/Users/mathiasx/Developer/.rvm/gems/ruby-1.9.2-p180@big_fan)?
    (anything other than 'yes' will cancel) > yes
    $ cd ..
    $ cd project/
    Using /Users/mathiasx/Developer/.rvm/gems/ruby-1.9.2-p180 with gemset big_fan

    Note that I have my rvmrc file like this so that it created and trusted the gemset upon encountering it:

    $ cat .rvmrc
    rvm use 1.9.2@big_fan --create

    Getting everything working again:

    Upgrade your Rubygems (this will only apply to this version of Ruby in RVM, not all versions of Ruby)

    $ gem update --system
    == 1.8.15 / 2012-01-06
    
    * 1 bug fix:
    
      * Don't eager load yaml, it creates a bad loop. Fixes #256
    
    
    ------------------------------------------------------------------------------
    
    RubyGems installed the following executables:
            /Users/mathiasx/Developer/.rvm/rubies/ruby-1.9.2-p180/bin/gem
    
    RubyGems system software updated

    Then just to be safe, make sure the gems we have are pristine (According to the manpage, gem pristine: "Restores installed gems to pristine condition from files located in the gem cache.")

    $ gem pristine --all

    And it is safe to now bundle:

    $ bundle
    Fetching source index for http://rubygems.org/
    Installing rake (0.9.2.2) 
    Installing i18n (0.6.0) 
    Installing multi_json (1.0.4) 
    Installing activesupport (3.2.0) 
    Installing builder (3.0.0) 
    Installing activemodel (3.2.0) 
    Installing erubis (2.7.0) 
    Installing journey (1.0.0) 
    Installing rack (1.4.0) 
    Installing rack-cache (1.1) 
    Installing rack-test (0.6.1) 
    Installing hike (1.2.1) 
    Installing tilt (1.3.3) 
    Installing sprockets (2.1.2) 
    Installing actionpack (3.2.0) 
    Installing mime-types (1.17.2) 
    Installing polyglot (0.3.3) 
    Installing treetop (1.4.10) 
    Installing mail (2.4.1) 
    Installing actionmailer (3.2.0) 
    Installing arel (3.0.0) 
    Installing tzinfo (0.3.31) 
    Installing activerecord (3.2.0) 
    Installing activeresource (3.2.0) 
    Using bundler (1.0.18) 
    Installing json (1.6.5) with native extensions 
    Installing rack-ssl (1.3.2) 
    Installing rdoc (3.12) 
    Installing thor (0.14.6) 
    Installing railties (3.2.0) 
    Installing rails (3.2.0) 
    Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.

    Now we should have a happy gemset and the error will be gone. Let me know if you have any questions. Happy hacking!

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Mon, 03 Jan 2011 15:58:00 -0800 Getting MongoDB and Devise to play well on Rails 3 http://blog.mattgauger.com/getting-mongodb-and-devise-to-play-together-o http://blog.mattgauger.com/getting-mongodb-and-devise-to-play-together-o

    While there's a good guide on the MongoDB site about getting mongo_mapper to work in Rails 3, I ran into some additional issues getting the popular devise authentication engine for Rails to work with Mongo. This documents how to create a Rails app from scratch that uses both MongoDB and Devise. So if you don't want to reinvent the wheel on authentication (read: Users, login, logout, etc) and want to run your app on MongoDB, this should be useful.

    First of all, you'll need Rails 3. I'm on Rails 3.0.3. I created a new gemset for this app, just to keep things clean. Run the rails new command with the --skip-active-record switch.

    $ rails new awesome_app --skip-active-record

    Open up the Gemfile of the new app. It's going to be pretty empty to start. This is what I ended up with, after reading the Mongo guide mentioned at the beginning of the post:

    require 'rubygems'
    require 'mongo'
    
    source :rubygems
    
    gem 'mongo_mapper'
    gem 'rails', '3.0.3'
    gem 'devise', '1.1.3'
    gem 'devise-mongo_mapper',
      :git    => 'git://github.com/collectiveidea/devise-mongo_mapper'
    
    group :test, :development do
      [whatever testing gems you want in here]
    end

    You'll notice the devise-mongo_mapper gem in there. That's the secret sauce that lets us use mongo_mapper as the ORM for Devise. As I haven't really played with the mongoid gem (and therefore don't have any experience with it) I didn't try to get mongoid to work.

    Go ahead and run a bundle install:

    $ bundle install

    Then run this to install devise files into the Rails app:

    $ rails generate devise:install

    There's two initializer files we'll need. We add the one for mongo, which I put in config/initializers/mongo.rb:

    MongoMapper.connection = Mongo::Connection.new('localhost', 27017)
    MongoMapper.database = "awesome-app-#{Rails.env}"
    
    if defined?(PhusionPassenger)
       PhusionPassenger.on_event(:starting_worker_process) do |forked|
         MongoMapper.connection.connect_to_master if forked
       end
    end

    And one for devise, which you'll find created for you in config/initializers/devise.rb. Change the ORM Configuration settings to this:

    # ==>; ORM configuration
    # Load and configure the ORM. Supports :active_record (default) and
    # :mongoid (bson_ext recommended) by default. Other ORMs may be
    # available as additional gems.
      require 'devise/orm/mongo_mapper'

    Be sure to add this line to config/application.rb and edit in the appropriate address. This will keep Devise from complaining later:

    config.action_mailer.default_url_options = { :host => "yourdomain.com" }

    The last step is to create an User model and tell Devise and mongo_mapper to do their thing. Tell Devise to make a Users model and then install the Devise Views to our app so that we can modify them later, if we wish:

    $ rails generate devise users
    $ rails generate devise:views

    In app/models/user.rb:

    class User
      include MongoMapper::Document         
      plugin MongoMapper::Devise
    
      devise :database_authenticatable, :confirmable, :lockable, 
             :recoverable, :rememberable, :registerable, :trackable, 
             :timeoutable, :validatable, :token_authenticatable
    
      attr_accessible :email, :password, :password_confirmation
       
    end

    You can, of course, choose which of those Devise options to enable for your user model. Refer to the devise documentation for more information.

    In app/controllers/application_controller.rb:

    class ApplicationController < ActionController::Base
      protect_from_forgery
      
      filter_parameter_logging :password, :password_confirmation
      
      def after_sign_out_path_for(resource_or_scope)
        new_user_session_path
      end
    end

    In config/routes.rb add these lines:

    devise_for :users, :admin
    resource :user

    At this point, you should probably check your app by running a quick `rails server` and seeing it if spits out any errors to your terminal. If it's all good, then you are probably thinking you'll want to actually use this authentication system now. Let's add a very basic "Home" controller:

    $ rails generate controller Home index token

    In app/controllers/home_controller.rb, add the following before_filter line to the beginning of the class so that it looks like this:

    class HomeController < ApplicationController
      before_filter :authenticate_user!, :only => :token
      
      def index
      end
    
      def token
      end
    
    end

    In app/views/home/index.haml (I'm using HAML, but I've also included an ERb example after this:

    - if user_signed_in?
      %ul
        %li= current_user.email
        %li= link_to 'My info', edit_user_path
        %li= link_to 'Sign out', destroy_user_session_path
    - else
      %ul
        %li= link_to 'Sign in', new_user_session_path
        %li= link_to 'Sign up', new_user_path
    # ERb version of app/views/home/index.html.erb:
    <% if user_signed_in? -%>
      <ul>
        <li><%= current_user.email %></li>
        <li> link_to 'My info', edit_user_registration_path %></li>
        <li><%= link_to 'Sign out', destroy_user_session_path %></li>
      </ul>
    <% else -%>
      </code><ul><code>
        <li><%= link_to 'Sign in', new_user_session_path %></li>
        <li><%= link_to 'Sign up', new_user_path %></li>
    <% end -%>

    This will enable very basic login / logouts using the Devise views that we installed earlier. If you run rails server again, you'll be able to create an account. But, if your system isn't set up to send mail (like mine) then you may get an error, or simply won't get a confirmation code, so you won't be able to login with that user. Here's a quick solution. Drop into the mongo shell:

    $ mongo
    MongoDB shell version: 1.6.4

    Use your database, which you set above in config/initializers/mongo.rb. In this case, it's awesome-app-development:

    > use awesome-app-development
    switched to db awesome-app-development

    Find all the entries in the Users document:

    > db.users.find();
    { "_id" : ObjectId("4d216ae217cacc289c000005"), "email" : "matt.gauger@gmail.com", "encrypted_password" : "$2aasdf", "password_salt" : "$2aasdf", "authentication_token" : null, "remember_token" : null, "remember_created_at" : null, "reset_password_token" : null, "confirmation_token" : "YsFg8CFBwNIm5kof7xC9", "confirmed_at" : null, "confirmation_sent_at" : "Mon Jan 03 2011 00:21:22 GMT-0600 (CST)", "failed_attempts" : 0, "unlock_token" : null, "locked_at" : null, "sign_in_count" : 0, "current_sign_in_at" : null, "last_sign_in_at" : null, "current_sign_in_ip" : null, "last_sign_in_ip" : null }

    The bit we need is the confirmation_token: "YsFg8CFBwNIm5kof7xC9". Copy the token and go to the following in your browser:

    http://localhost:3000/users/confirmation?confirmation_token=YsFg8CFBwNIm5kof7xC9

    Remember to replace your token with the one in that URL. You could alternatively make it so your app can send mail, or just turn off :confirmable in your Users model. This was a quick little solution that I found and wanted to share.

     

    Hopefully this gets you going with Mongo and Devise quickly and without any snags. There's a lot more to Devise, so I'd recommend you start looking at some of the Example applications and the documentation.

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Fri, 31 Dec 2010 13:55:48 -0800 What's new and great in Rails 3 - Milwaukee Ruby Users Group - December 2010 http://blog.mattgauger.com/whats-new-and-great-in-rails-3-milwaukee-ruby http://blog.mattgauger.com/whats-new-and-great-in-rails-3-milwaukee-ruby

    While I was going to write a whole blog post (essentially what I said during the talk) I think these slides stand on their own pretty well.

    View more presentations from mathiasx.

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Sun, 26 Dec 2010 13:40:00 -0800 Techniques for learning a new skill http://blog.mattgauger.com/techniques-for-learning-a-new-skill http://blog.mattgauger.com/techniques-for-learning-a-new-skill

    I just found these notes in an old notebook and figured they deserved a blog post . This isn't self-help type stuff, it's just practical. I'm blogging this so that some day I find it when reading my old blog posts, just as I found the list in an old notebook.

    Techniques helpful in learning any skill:

    • Know your starting point (measure it, somehow) => "You can't manage what you can't measure."
    • Set objectives.
    • Have techniques for improvement available.
    • Assess your progress after a reasonable period.
    • Have strategies for continuing improvement and maintaining the skill.

    I'd add in there to have a good way to record your progress. Something like Daytum will probably work if you want a web-based tool. Excel spreadsheets and notebooks work great, too.

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Tue, 14 Dec 2010 17:25:00 -0800 Presentation: LAMP vs. The World http://blog.mattgauger.com/presentation-lamp-vs-the-world-milwaukee-php http://blog.mattgauger.com/presentation-lamp-vs-the-world-milwaukee-php Matt Gauger - Lamp vs. the world - MKE PHP Users Group - December 14, 2010
    View more presentations from mathiasx.

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Sun, 12 Dec 2010 09:38:00 -0800 Open URL from Terminal.app and the 'open' command http://blog.mattgauger.com/go-to-url-from-terminalapp http://blog.mattgauger.com/go-to-url-from-terminalapp

    More and more as I blog, I find I like to post little tips, and beginners thank me for showing them something new, More advanced users may have simply overlooked whatever I'm sharing, so they can find it useful, too. So in that vein, I just reminded myself of a little Mac OSX Terminal.app trick I use all the time, and wanted to post it here.

    When you have a URL in Terminal.app, say in a README file you're reading, or coming back from a dig/whois command, you can just right-click (option-click) on the URL and click Open URL. It's fast, it works, and it saves me a few milliseconds of copy/pasting it. Awesomest trick ever? Not really. Useful? Definitely.

    Terminal-right-clic

    An alternative form of this is to use the Mac OSX "open" command on any number of things: Files, applications, URLs. Here's how it looks: 
    banshee:diaspora mathiasx$ open http://joindiaspora.com
    banshee:diaspora mathiasx$ open README.md 
    banshee:diaspora mathiasx$ open /Applications/Google\ Chrome.app/

    That will open the joindiaspora.com site in your default browser, a file called README.md in whatever your default text editor is, and the final command will open Google Chrome if it isn't open, otherwise it will simply switch focus to it.

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Fri, 10 Dec 2010 10:43:22 -0800 Git & Github: A Beginner's Guide http://blog.mattgauger.com/git-github-a-beginners-guide http://blog.mattgauger.com/git-github-a-beginners-guide

     Let me start off by saying that this blog post isn't going to introduce you to the intricacies of git. There is certainly a lot to be learned and a lot that I could write about branching, managing git servers, and any number of the git commands and ways to use them. I've linked to more resources where you can learn all of that at the bottom of this post.

    Instead, I'm going to focus on the beginner user, maybe someone that has never contributed to open source but wants to learn and wants to help out. They're not interested in learning the in's and out's of every single command. They just want to get stuff done.

    It's likely that a person would run into git for the first time by visiting Github. There are a lot of big, popular open source projects hosted there. Too many to list here, in fact, but here's a quick teaser: jQuery, scriptaculous, yui3, prototype, and mootools are all on Github. So are Ruby on Rails, Symfony, Django, web.py, and many other web app frameworks. The list goes on and on.

    But why is Github so popular? It certainly has a nice design. But design alone doesn't necessarily attract developers by the hundreds; most of them still use the arcane commandline with bitmapped fonts, after all.

    I'll put forward that Github is popular with developers because it optimizes for the things they need to do, without getting in the way. And because it's fun. There's very little barrier of entry for a developer to contribute back to open source, or upload new code, or even find projects that are interesting to them. It takes all the best features of git (which we'll get to in a minute) and smooths out all the rough, annoying edges of setting up a server, handling SSH key authentication, and tracking URLs to reference.

    Let's assume our beginner has stumbled upon Pete Prodoehl's Heard project, which lets you mirror your Last.fm scrobbles and host it in a decent way outside of Last.fm. The user wants to use it to back up their Last.fm, too. They likely came across Heard in Pete's blog. The blog post contains a link to the Heard Github repo, which looks like this:

    Raster_heard_-_github-smaller

    This is the first time the user has been to Github, so they don't quite know how it works. If the user hovers over the Watch or Fork buttons, they will be instructed to sign in. They might just click the big Download button and never come back, but let's assume this person wants to contribute back. They know they want to add a feature to Heard so that it draws gRaphaël graphs of their listening history, because they think graphs are pretty cool and gRaphaël draws very beautiful graphs:

    Graphael_line_charts

    The user then creates an account on Github, since they don't have one and it's required to click those Watch or Fork buttons. They go back to Pete's Heard project on Github and click Watch. The text changes from Watch to Unwatch but they don't notice anything immediately. Watch is a way to subscribe to repo changes in the Dashboard of Github, but our user doesn't know that yet. Looking for more immediate satisfaction from clicking buttons, our user clicks Fork. And then something magical happens. (Parents please make your children leave the room during this part of the program.)

    Hardcore-forking-action

    The user is now in their own copy of Heard. Github has forked the open source project, a task which once took Herculean strength and immense popularity to pull off in the dark days of Sourceforge! The user realizes this forked project is their very own kingdom to do with as they please. And the user, motivated by their hunger for pretty graphs and encouraged by the fact that Github is hosting their fork for free, is ready to jump into coding. (All open source projects get free hosting on Github, and open source does not count against your paid account's number of repositories.)

    The first step Github gives after setting up your account is to install git. We'll leave it up the to the reader to track down and install the latest version of git (at the time of this writing, v1.7.3.3) from http://git-scm.com/ for their particular operating system.Once our daring, brave fictional hero gets git compiled and installed, Github instructs them to generate an SSH key and enter it into their Account Settings on Github:

    Your_account_-_github-1

     

    Sidenote: What are SSH keys and why do I need them?

    SSH is a secure communications method that uses public/private key encryption. Explaining public/private key encryption with Bob, Alice and the gang is beyond the scope of this blog post, but in short, it works like this: You generate two keys, a public and a private key. A key is just a bunch of characters in a text file, but it's used as a very strong cryptographic key.The public and private key are linked in such a way that you can mathematically prove data came from the person holding the private key.

    The private key must be kept private! No one but you should ever possess it! When you cryptography "sign" a file, text, or other data with your private key, another party can verify that you (and only you) could have sent that data, by using your public key. You can also guarantee the identity of a server you're communicating with, because their public key allows you to verify data was signed by their private key. Make sense?

    So when you put your public key into Github, it can verify that any data sent to it claiming to be you is actually from you (and signed by your private key). It's much more complicated than this, but that's the idea.

    For more information on OpenSSH, SSH keys, and the like, refer to the OpenSSH FAQ.

    Back to Github:

    Our user runs the

    ssh-keygen

    command in their shell, hits enter for the defaults, and generates some files that live in /home/[username]/.ssh in Linux/BSD or /Users/[username]/.ssh if you're on Mac OSX. If you're still on Windows, it'll be in Cygwin somewhere, likely. Sorry. Can't help you there.

    One file is called id_rsa and the other is id_rsa.pub. The file with the .pub extension is, naturally, the public key. That's the one that you want to copy into Github's Account Settings page. Once you enter a public key (again, make sure it isn't the private key!) into Github, it will know who you are when you communicate with Github using the git commands. The great thing about this is, every time we communicate with the server, we don't have to type a password. Isn't that cool?

    At this point our beginner hasn't actually gotten any files, made any changes, or asked Pete nicely to accept his changes. That may seem like all this effort was a waste, but in practice it is fairly quick and once you've done it once (and setup a Github account) you're well on your way to doing all those things. Git also prefers to have your name and email address to identify changes as coming from you, and Github helpfully provides the commands for those when setting up a new account.

    The user is ready to work. At the top of their fork of the Heard project, Github gives the user a link says it is read+write. Which probably means that by using it somehow, we can write our changes back to Github and get one step closer to getting those changes back to Pete. Github even helpfully offers to copy the link for you.

    Mathias-presentation_heard_-_github

     Our user dives into the gitref.org page and discovers what they are supposed to do with this URL ending in .git: They must use the git clone command to clone it from Github down to wherever they are in the shell, like so:
    $ git clone git@github.com:mathias-presentation/Heard.git
    Cloning into Heard...
    remote: Counting objects: 22, done.
    remote: Compressing objects: 100% (22/22), done.
    remote: Total 22 (delta 7), reused 0 (delta 0)
    Unpacking objects: 100% (22/22), done.

    If the user's SSH key was right, this will work. If not, they'll have to go back and fix it. Looks like it worked, though, so we'll move on.

    The git clone command has created a directory named Heard in the user's home directory. There's also a hidden .git directory in there, but that's where git keeps its affairs in order, and for the purposes of this post, it can be ignored. The nice thing about git is that the .git/ directory is the only place it adds something to your project, unlike Subversion, which puts a .svn directory in every directory.

    The user is now ready to use git, with an eye towards contributing his changes back to Pete as fast as possible.

    Git Basics

    Our user makes some basic changes to the PHP files in their local Heard directory. They reason that if git keeps tracks of versions of files, it will need to create a new version containing these changes. Git tracks changes on an object level, not a file or project/directory level. That means it is really smart about where you changed something. See some of the reference material for a full explanation of how git understands changes. For our purposes, the beginner finds the

    git commit

    command. The documentation says that the commit command is used to take a snapshot of the code in the current state. That sounds perfect. But typing the command yields:

    $ git commit
    # On branch master
    # Changed but not updated:
    #   (use "git add ..." to update what will be committed)
    #   (use "git checkout -- ..." to discard changes in working directory)
    #
    #        modified:   config.php
    #        modified:   init.php
    #        modified:   tracks.php
    #
    no changes added to commit (use "git add" and/or "git commit -a")

    Nothing happened, as indicated by the message "no changes added to commit." Git has helpfully suggested some ways to commit at the bottom there. The first is to use the

    git add

    command, which sounds like a way to add files to a commit. The other is to pass in the -a argument to git commit, like this:

    git commit -a

    The -a is for all, so when we tell git to git commit -a, we're telling it to commit everything that changed, all at once. The user types that in and is dropped into.. a text editor?

    This step can be a little confusing for new users. In fact, that this is default behavior is, in my opinion, a huge roadblock to people to get up and running with git. On Mac OSX or Linux, this is likely to be vim, which is not the most user-friendly to new users.

    What is the text editor for? Git is asking for the user to write a commit message, that is, a description of what changed for the official history of this project. For something more user-friendly to write this commit message in, I suggest you type this arcane incantation from the wizards of old:

    git config core.editor "nano"

    The meaning of this spell is lost to the ages, but the nice thing is, it will drop you into the much more user-friendly nano editor, which list the CTRL- characters to save, quit, etc. along the bottom of the terminal.

    A good commit message will help later when trying to find what changed over the course of time. Git is already tracking which files changed and what changed in them, so the message is usually written at a more abstract level that says what the user was doing and thinking. There's plenty of good resources out there on the web about writing good commit messages, and even more about opinions about what should and shouldn't be in a commit message.

    This is where I want to break the narrative a little to explain the rest of the commands that our fictional beginner will need to contribute back to Pete's Heard project. Think of it as a blog post montage of lots of coding getting done.

    The first is simply another argument to add to the git commit command so that we don't get dropped into a text editor to write our commit message. Usually, commit messages are only one line, so it makes sense to write the commit message right there on the command line:

    $ git commit -am "Added the gRaphael library to be loaded, but haven't integrated it yet."
    [master 1a4014f] Added the gRaphael library to be loaded, but haven't integrated it yet.
     3 files changed, 3 insertions(+), 3 deletions(-)

    As you can see, that worked, and it accepted our commit message right there on the command line. Notice that the commit message is wrapped in double quotes: " " This is because the shell will try to interpret words on their own as commands, and we don't want that. So, to be safe, we wrap the whole thing in double quotes, so that the shell knows that this is a string to pass into the git command and not something to try and execute.

    What else does the output from git commit tell us? Well, we committed all three files at once. In other version control systems, you must commit all changes to files at once. This can get annoying. In git, you can choose which files you want to add to any given commit, and leave out anything else that changed. To do that, we use the git add command.

    [do some work]
    $ git add config.php
    $ git add init.php

    You'll notice there's no output from these commands. That's because nothing has changed yet. Those changes still need to be committed. It would probably be helpful at this point to have a look at what changed and what didn't. For that, we use the git status command.

    $ git status
    # On branch master
    # Your branch is ahead of 'origin/master' by 1 commit.
    #
    # Changes to be committed:
    #   (use "git reset HEAD ..." to unstage)
    #
    #        modified:   config.php
    #        modified:   init.php
    #
    # Changed but not updated:
    #   (use "git add ..." to update what will be committed)
    #   (use "git checkout -- ..." to discard changes in working directory)
    #
    #        modified:   tracks.php
    #

    As you can probably see, we're not going to commit all the changes like we did in the first commit. We're only going to commit the changes in the config.php and init.php files this time around, while tracks.php will be left out of the commit. Git status is a very useful command, and you will probably use it a lot to figure out the current state of your project and to see what should and shouldn't be in a commit. Since we don't want to commit all changes this time, we leave off the -a argument but keep the -m so we can specify a commit message:

    $ git commit -m "A little refactoring."
    [master 6dd5c59] A little refactoring.
     2 files changed, 2 insertions(+), 2 deletions(-)
    $ git status
    # On branch master
    # Your branch is ahead of 'origin/master' by 2 commits.
    #
    # Changed but not updated:
    #   (use "git add ..." to update what will be committed)
    #   (use "git checkout -- ..." to discard changes in working directory)
    #
    #        modified:   tracks.php
    #
    no changes added to commit (use "git add" and/or "git commit -a")

    Notice that the changes in tracks.php are still waiting for us when we perform another git status.

    Git log is a command used to see the history of a project.

    $ git log
    commit e47cd6eb917d2a68ec6d1197a38faa1a1ff5e564
    Author: Matt Gauger 
    Date:   Thu Dec 9 14:27:04 2010 -0600
    
        Some other places where it's nice to have newlines.
    
    commit fb2cc2b00bfd797cca355a4215b2c289e281e040
    Author: Matt Gauger 
    Date:   Thu Dec 9 14:26:23 2010 -0600
    
        Add a newline here.
    
    commit 4cce3dff9c8d03b7db1710f7addaa7d556921a44
    Author: raster 
    Date:   Sun Nov 14 11:38:50 2010 -0600
    
        Minor changes, still learning git
    
    [truncated for length]

    At this point you may be asking, how does our user upload their changes back to Github?

    The command required is: 

    $ git push

    And in its default form, it knows what to push and where: It defaults to Github when you use the git clone command as above. A more complicated form of git push will allow you to choose the branch and the server to push to, but for our beginner user that is only using the master branch and Github server, it is unnecessary to understand.

    Similarly, to get changes from the server, use the command:

    $ git fetch

    This is, again, some default behavior that knows to go talk to the Github server. It will pull down changes from the user's repo on Github, in this default manner, and it is important to note that this won't include the changes made by other Github users. This part can initially be confusing to people who are looking to keep up with a project's main development or other developer's contributions, and Github's documentation explains this stuff (and it is managed largely through the Github website) so I'll leave it beyond the scope of this blog post.

    The git fetch command is useful if you have two computers with SSH keys in Github, for example, and you commit and push from your desktop, but want to grab your most recent changes on your laptop.

    The other question you may be asking yourself at this point is: What happens if I screw up? What if you accidentally delete a file from your project, or you save something you didn't mean to save. In this case, you can restore the project to the state of the last commit. Git is, after all, storing all the states of the project, so you can roll it backwards as necessary. The command to reset a project back to its previously committed state is:

    $ git reset --hard HEAD

    There's a lot going on here to point out. The git reset part is obviously the command that we use to reset a project to a previous state. The state we're telling to to go back to is called HEAD, which is just a placeholder name for the last commit. There's lots of these placeholder names in git, and it's nice to learn the common ones. For the purposes of this blog post, we can ignore the --hard, and refer you to the reference materials and "man git-reset" on your shell for further explanation.

    You want to be careful with git reset, obviously. It will reset all the files in your project to the state they were in at the last commit. So all changes since the last commit will go away. This isn't always ideal. You could lose a lot of work this way. If you want to only reset one file, this is the way that I do it, and I imagine there are other ways in the very many different git commands:

     

    $ git checkout -- init.php
    $ git checkout HEAD init.php

    In this case we're taking the state of init.php back to the last commit, which again, is referenced with the placeholder name HEAD. 

    That's the most common commands that this beginner user will encounter and have to grasp in using Github and git. So now what? Well, remember that our user had the end goal of contributing back to Pete Prodoehl's Heard project. The way to do is to go back to our user's fork of Heard on Github, and use the Pull Request button. 

    Pull_request

    Which is highlighted in blue above.

    By submitting a Pull Request back to Pete for the changes the user has made, Pete can choose which commits to pull into his version of Heard, which is basically the official repo for the project at this time. By getting Pete to accept a Pull Request, our user has contributed back to Heard, which was the user's initial goal. It wasn't the easiest road to contributing back, but once developers learn these skills and they have set up both git and Github to their liking, it is actually quite fast, fun, and powerful to use Github to contribute to open source.

    Thanks for reading! Please leave comments on places where this could be improved or any other thoughts you have.

    Slides from my talk:

     

    Further reading:

    • Github has great documentation online at help.github.com. I highly suggest you start there.
    • Github will point you in the direction of the gitref.org page for a quick overview of Git.
    • Scott Chacon released his book, Pro Git, online for free. It is also available from Apress on Amazon: Pro Git. (Full disclosure: Amazon Associates link. That is, I earn a small commission on stuff sold through these links on my blog.)
    • The Pro Git blog is a good place to continue to pick up Git tricks and tips as you learn.
    • It hasn't been updated in a long time, but the git ready blog has taught me many tricks that I use with git.

    All other resources mentioned:

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Wed, 01 Dec 2010 13:55:00 -0800 What I'm doing in December http://blog.mattgauger.com/what-im-doing-in-december http://blog.mattgauger.com/what-im-doing-in-december

    Aside from being really busy at work, I'll be giving three talks at users groups in December. How did I end up agreeing to give three talks in one month? People heard me talking about some topic and they asked me to talk to their group on it. If asked, I'll usually agree. I'm trying to tie them together thematically to make it a three-parter (and encourage people to come to all three meetups) so I'm calling the series: 'Tis the Season to Write Web Apps, A Three Part Adventure.

     

    Development Tools: Git and Github (aka, 'Tis the Season to Write Web Apps Part 1)

    Web414

    7PM, December 9th, 2010 @ Bucketworks

    I've been asked to talk about Git and Github and give a basic intro on how to use it. I'll also talk about my developer workflow and technical team collaboration. I'd also like to point out that Ralph Holzmann will be talking about LABjs and yepnope.js after my talk. It should be a great night with lots of technical content!

     

     

    PHP vs Rails (aka, 'Tis the Season to Write Web Apps Part 2)

    Milwaukee PHP Users Group

    6PM, December 14th, 2010 @ Bucketworks

    This talk started as the idea of comparing how traditional LAMP servers differ from how application servers behave. I'll be covering Apache and phpmod, some information about nginx, and compare performance. A very basic web app will be used as an example and I'll introduce some tools used for benchmarking web applications. Note that the topic has seemingly mutated from "LAMP servers versus Application Servers" to PHP vs. Rails, possibly to draw out more folks by using good keywords ;)

     

    What's new and great in Rails 3! (aka, 'Tis the Season to Write Web Apps Part 3!)

    RubyMKE

    7PM, December 20th, 2010 @ Bucketworks

    I'll be talking about what's different in Rails 3 and what stays the same. A perfect follow-up to those that want to know about writing for an application server after the MKE PUG talk. I'll have a ported version of the basic web app from the MKEPUG talk.

     

    All code and slides will be available here and on my Github after the talks. I'll hopefully have time to put together summary blog posts afterwards, too.

    Also: Be sure to join us at MilwaukeeDevHouse5 on December 3rd, 2010, 5PM-midnight. The description from Web414:

     

    This will be the first MilwaukeeDevHouse with a purpose... In the past we just called it a "party with laptops" and invited you to come and work on whatever you wanted to. You can still do that, but we're also going to focus on ways to make BarCampMilwaukee (and Bucketworks) better. Call it "Hack the BarCamp!" or maybe "Hack the Bucket!"

     

     

    See you there!

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Sun, 31 Oct 2010 13:19:00 -0700 /Library/Ruby/Site/1.8/rubygems.rb:779:in `report_activate_error': Could not find RubyGem railties (>= 0) (Gem::LoadError) http://blog.mattgauger.com/libraryrubysite18rubygemsrb779in-reportactiva http://blog.mattgauger.com/libraryrubysite18rubygemsrb779in-reportactiva

    I tend to blog things that I want to remember, but couldn't find in one quick Google search.

    This is an error I got while starting the Rails Tutorial, because I was using an old system (I counted about 160 gems installed) and starting to use rvm for managing my Ruby installs, because the Rails Tutorial recommends it. I haven't had this kind of issue before, because rails, gem, and ruby commands have all just worked out-of-the-box for me since Mac OS X 10.5 was released.

    When I tried to create a new Rails app, I got the error in the title of the blog post:

    minimite:railstutorial.org mathiasx$ rails new first_app
    /Library/Ruby/Site/1.8/rubygems.rb:779:in `report_activate_error': Could not find RubyGem railties (>= 0) (Gem::LoadError)
            from /Library/Ruby/Site/1.8/rubygems.rb:214:in `activate'
            from /Library/Ruby/Site/1.8/rubygems.rb:1082:in `gem'
            from /usr/bin/rails:18
    minimite:railstutorial.org mathiasx$ rails -v
    /Library/Ruby/Site/1.8/rubygems.rb:779:in `report_activate_error': Could not find RubyGem railties (>= 0) (Gem::LoadError)
            from /Library/Ruby/Site/1.8/rubygems.rb:214:in `activate'
            from /Library/Ruby/Site/1.8/rubygems.rb:1082:in `gem'
            from /usr/bin/rails:18

    That didn't make sense. Where is the Rails command being run from?

    minimite:railstutorial.org mathiasx$ which ruby
    /Users/mathiasx/.rvm/rubies/ruby-1.9.2-p0/bin/ruby
    minimite:railstutorial.org mathiasx$ which gem
    /Users/mathiasx/.rvm/rubies/ruby-1.9.2-p0/bin/gem
    minimite:railstutorial.org mathiasx$ which rails
    /usr/bin/rails

    Aha. Obviously the previously-installed Rails gem, from before installing rvm, was an issue. So I figured I'd just clean it up.

    minimite:railstutorial.org mathiasx$ rvm list
    
    rvm rubies
    
       ruby-1.8.7-p302 [ i386 ]
    => ruby-1.9.2-p0 [ i386 ]
    
    minimite:railstutorial.org mathiasx$ rvm use 1.8.7
    Using /Users/mathiasx/.rvm/gems/ruby-1.8.7-p302
    minimite:railstutorial.org mathiasx$ sudo gem uninstall rails
    Remove executables:
            rails
    
    in addition to the gem? [Yn]  y
    Removing rails
    Successfully uninstalled rails-3.0.1
    minimite:railstutorial.org mathiasx$ which rails
    /usr/bin/rails

    But I hadn't been paying attention. I still had not removed the Rails executable, because I was calling the rvm version of Ruby 1.8.7 and not the system-level one. Knowing that Rails was in /usr/bin/rails, I assumed that the gem executable that managed it would also be in /usr/bin:

    minimite:railstutorial.org mathiasx$ sudo /usr/bin/gem uninstall rails
    Remove executables:
            rails
    
    in addition to the gem? [Yn]  y
    Removing rails
    
    You have requested to uninstall the gem:
            rails-3.0.0
    clearance-0.9.0.rc9 depends on [rails (~> 3.0.0)]
    factory_girl_rails-1.0 depends on [rails (>= 3.0.0.beta4)]
    suspenders-0.1.0.beta.4 depends on [rails (>= 3.0.0)]
    If you remove this gems, one or more dependencies will not be met.
    Continue with Uninstall? [Yn]  y
    Successfully uninstalled rails-3.0.0

    I'd finally removed the system-level Rails script and can switch back to using rvm for everything:

    minimite:railstutorial.org mathiasx$ rvm use 1.9.2
    Using /Users/mathiasx/.rvm/gems/ruby-1.9.2-p0
    minimite:railstutorial.org mathiasx$ which rails
    /Users/mathiasx/.rvm/gems/ruby-1.9.2-p0/bin/rails
    Using /Users/mathiasx/.rvm/gems/ruby-1.9.2-p0
    minimite:railstutorial.org mathiasx$ rails new first_app
          create  
          <-- Lots of output -->

    It works!

    Lesson learned: Always pay attention. The answer is probably sitting right in front of you.

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Sat, 16 Oct 2010 11:16:00 -0700 The Master's Word http://blog.mattgauger.com/the-masters-word http://blog.mattgauger.com/the-masters-word

    Last night, at the opening of Sector67 and during a discussion about human language, expression, and the limits thereof, I told a story I've read somewhere, but I cannot remember the source. My details on the story are quite fuzzy; I am quite sure it comes from an eastern oral tradition, but googling couldn't help me. Further, I embellished the details to fit in with a story about kung fu, but this story could equally be a Buddhist Koan or something else. Any tips to where it came from would be highly helpful. Without further ado, here's my version of the story:

    The Master had studied kung fu his entire life, and was widely regarded in the land as the best in the known world. He practiced alone in his mountaintop sanctuary for years, uninterrupted.

    A Challenger came, a young upstart who had defeated monks and warriors across the land with his kung fu. He was eager to defeat The Master and take his place as the world's best. As he was undefeated, The Challenger prepared on his own, studying defenses against every form and developing his own offensive technique that he believed could not be countered.

    Arriving upon the top of the mountain, the Challenger introduced himself to The Master, who remained silent. The Challenger announced his intentions of dueling with The Master and determining who was the best in the land.

    The Master appeared thoughtful for a second, then opened his mouth and uttered a single word. The Challenger fell dead on the spot. The Master had condensed an entire lifetime of learning, knowledge, and experience into a single word. He no longer required the movements of kung fu or the physical realm to defeat The Challenger.

    Editor's note: I imagine, in a Buddhist version of this story, the Master has meditated for years in his mountaintop retreat, and instead of killing The Challenger, The Master utters one word and The Challenger is enlightened.

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Wed, 13 Oct 2010 21:35:00 -0700 /Library/Ruby/Gems/1.8/gems/eventmachine-0.12.10/lib/eventmachine.rb:572:in `start_tcp_server': no acceptor (RuntimeError) http://blog.mattgauger.com/libraryrubygems18gemseventmachine-01210libeve http://blog.mattgauger.com/libraryrubygems18gemseventmachine-01210libeve

    Seeing this error when trying to run your Rack or Sinatra webapp?

    It's probably because you're already running something on the port you're trying to use. This happens quite a bit if you're using daemonized Rack apps that go off on their own after you close the controlling shell.

    Use this command to see what's happening on a port:

    $ lsof -i :4567
    COMMAND   PID     USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
    ruby    74716 mathiasx    5u  IPv4 0x073562a4      0t0  TCP *:tram (LISTEN)
    It'll help you see the PID of the process that's hogging that port. Just be careful not to kill anything that should be on that port!

     

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Tue, 28 Sep 2010 17:08:00 -0700 Importing old content http://blog.mattgauger.com/importing-old-content http://blog.mattgauger.com/importing-old-content

    I've got text archives of my blog posts going back to about 2008 2007, so I'm going to start importing those old blog posts into posterous and backdating them. Well, the blog posts worth pulling in. I haven't really ensured that the links contained in the posts work, and the link at the top of each to the original post may eventually stop working.

    Hopefully this mass import doesn't screw things up. Apologies if it does.

    Of course, I'm not pulling in any of the comments, like this comment on my old wordpress.com blog from Giles Bowkett way back in 2007:

     

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Tue, 28 Sep 2010 17:05:55 -0700 Currently Reading: Clean Code by Robert C. Martin http://blog.mattgauger.com/currently-reading-clean-code-by-robert-c-mart http://blog.mattgauger.com/currently-reading-clean-code-by-robert-c-mart While it comes off as a little repetitive after The Pragmatic Programmer and Code Complete, "Uncle Bob" has a few interesting things to say. I'll write another post with my notes after I've finished the book. The introductory on naming is dated, as most Pragmatic Programmers are no longer naming things with Hungarian notation or individual characters. Given the number of poor naming conventions I've seen in production and open source code though, I often wonder whether the made-up statistic about programmers not reading books holds true.

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Sat, 30 Jan 2010 10:11:00 -0800 Continuous Integration for the Lone Programmer http://blog.mattgauger.com/continuous-integration-for-the-lone-programme http://blog.mattgauger.com/continuous-integration-for-the-lone-programme

    (This post is part of my blog archiving project. This post appeared on blog.mattgauger.com on January 30, 2010.)

    There’s a laundry list of tools and practices in my head that I consider part of modern software engineering (version control, unit testing, code reviews, etc.) These aren’t necessarily required on every project. Continuous integration seems to be a practice that many prominent developers are using. But continuous integration servers aren’t very glamorous, and therefore don’t get a lot of discussion.

    If you’re working alone on a project, committing it to version control, and using unit testing, what does it matter whether you run the tests yourself or have a continuous integration server running them? True, there’s a level of immediate feedback with running the tests yourself. But unless you’re building all the various unit testing and integration testing frameworks into one rake task, you may forget to run them all. In the case where you do have a rake task, your CI server could be running that for you on every commit. A continuous integration server ensures that the tests get run, whether you remember or not.

    The other plus to this setup is that you can choose how and when the CI server interrupts you. You may be in a flow state and not want to be bothered by stopping to run the unit tests every five minutes when you know you’re not breaking them. That could be dangerous, though. If you zone out for a half day and come back to find all the tests failing, you’ll need to go back through the builds to see when and what commit first broke it. Luckily, the CI server should tell you that.

    I set up Integrity locally to run as my continuous integration system. Technically, Integrity could be hacked to build and test just about anything that gives a Unix return code, but I’m using it in its most common purpose: building Ruby projects that are hosted in git repos. While many developers are using GitHub, I’ve pointed Integrity at local git repos.

    I did consider setting up a Campfire chat room to receive build status messages in, but it seemed overkill to sit alone in a chatroom to be updated by Integrity. So, I enabled the email functionality, and now Integrity is configured to email me with build status. If I keep a Firefox tab open to the Integrity server and choose whether to look at my email or not, I have a fairly effective barrier to decide when to let myself be interrupted. Meanwhile, the builds continue.

    I’m hoping to optimize this and integrate it fully into my workflow, as TDD/BDD is a new thing to me and Integrity is already serving to reinforce writing good tests.

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Mon, 25 Jan 2010 12:00:00 -0800 How Does Wisconsin Get the Job Done? http://blog.mattgauger.com/how-does-wisconsin-get-the-job-done http://blog.mattgauger.com/how-does-wisconsin-get-the-job-done

    (This post is part of my blog archiving project. This post appeared on blog.mattgauger.com on January 25, 2010.)

    The title is the question I asked myself after reading through the latest interview at UsesThis.com. I’d thought about using the Creative Commons-licensed stylesheets of Usesthis.com (aka TheSetup) for a nicer About Me page than I currently had on this blog. After tweaking the template a little, I realized I could use Jekyll and apply this template to any content I wanted.

    Instead of just post my own answers, why not interview everyone I know in the tech community here in Wisconsin? So that’s exactly what I’m doing. In the first round of interviews, we hear from Phil GerbyshakAshe Dryden, and myself. The interviews can currently be viewed at http://blog.mattgauger.com/thesetup/

    There’s more on the way, and I’ll be announcing new posts through my Twitter and on this blog. Oh, and please feel free to comment using the new Disqus commenting system!

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Thu, 14 Jan 2010 12:00:00 -0800 Web414 January 2010 http://blog.mattgauger.com/web414-january-2010 http://blog.mattgauger.com/web414-january-2010

    (This post is part of my blog archiving project. This post appeared on blog.mattgauger.com on January 14, 2010.)

    Web414 is a monthly technology meetup here in Milwaukee, which is responsible forBarCampMilwaukeeMKE Devhouse, Milwaukee’s coworking meetups, photowalks, and many of our other events in Milwaukee.

    Bucketworks is the usual host of Web414, but they’ve had some issues finding a new physical location in the past year. December was the first Web414 in their new location (fingers crossed!) near 5th & National. Bucketworks seems to be on track to open for business later this month at that location, but they didn’t have an internet connection + wifi in time for the January 2010 Web414.

    Kevin Ciesielski (Kevron on Twitter) hosted this month’s Web414 and moderated a panel on radio. His panelists were Ryan Schleicher of WMSETarik Moody of 88.9 Radio Milwaukee, Jim Conigliaro ofJournal Communications, and James Brust of online radio station Limbiq Frequencies. The panel discussed the technical difficulties of streaming radio on the web, and the issues surrounding licensing music for broadcast. Creative Commons licensing came up as a possible solution to the licensing issue. Unfortunately, the discussion didn’t include any musicians (vocal ones, at least) and I would have liked to hear what artists think about Creative Commons versus what broadcasters think.

    At first, one might wonder why this topic was chosen for Web414. The panelists were not as involved (or prepared to talk about) the technical side of streaming radio online. In fact, I heard a few people whispering in the back questioning the relevance to to Web414 during the meeting.

    But I’m going to go ahead and argue that the topic is entirely relevant to Web414. As a group, Web414 is exploring both the online realm and how to make a living working online. But Web414 is also concerned with the creation and publishing of content. That content could be writing, photography, code, art, interior design, music, etc. that just happens to live online. We’ve all staked our careers on the awesome capabilities of the web and the fact that we can make a living on the web. That’s why I think it is relevant to have a panel of radio folks or an interior designer or a singer-songwriter as the focus of a Web414 meeting.

    I may come off as a curmudgeon, but I think Web414 has already covered technical topics & tools in detail and doesn’t need to go that route anymore. Often, these topics appeal to only a small subset of attendees, or the 1 hour time limit is too short to adequately cover the topic. An hour intro to Drupal or Joomla or even a web site like Flickr is barely enough time to cover the basics and will probably only appeal to people who are already interested in Drupal or Joomla or Flickr. When I spoke at Web414 on version control, I felt that I’d barely scratched the surface of the topic and my talk failed (my fault, I’ll admit) to interest the people it was aimed at: those not already using version control. Technical topics seem better served by a whole unconference event, like the very successful Drupal Camp Wisconsin which I’ve had the pleasure of attending.

    So what topics would I personally like to see at Web414 in the future? I think we need to tap into our attendees and find interesting individuals to interview. I’m curious to hear what they do, how they do it, and how they pay the bills every month. I’m curious to hear what tools they use to stay productive and how they focus. And if we can draw in some interesting folks from Milwaukee and the surrounding area to interview along the same lines, I’d be interested. I’m not asking for a Lifehacker meet-up. I just think that the topic can now safely shift from specific technologies and websites and onto how to make ourselves better professionals.

    I think we need to allow for Web414 to change, too. In the past year, we had The Web414 Showhosted by Gabe Wollenburg and Pete Prodoehl. They took Web414 in the direction of a late-night TV talk show, which was good, because Web414 was beginning to feel like an Twitter Anonymous member meeting before that change. We may need someone to shake things up again, though. Things change so fast on the web (and generally impact us so little) that I question whether we need a “this week on the web” news segment. The tools and technologies that people are using and making a living off of is such a huge list now that it would be an injustice to try and cover what is happening with everything. Similarly, the happenings of web bloggers and web personalities really don’t have any relevance to us as a group anymore, if they ever did. (John C. Dvorak and Kevin Rose come to mind.) I’d like to suggest instead that we try to cover local Wisconsin developments in the tech sector: new companies moving into town, new initiatives by the state or local governments in using the web (if they ever chose to) etc. Perhaps instead of covering “web news” we could devote that time to allowing meeting attendees to brag about neat projects they’re working on or have been involved in, even though we’ve discouraged this practice in the intros in the past. I’d like to stay plugged in to what local folks are doing and be able to congratulate them for their successes and their failures.

    Milwaukee is noticeably lacking for particular technology users groups (such as Linux User Groups (LUGS), programming language user groups, etc), or they’re not as successful as Web414. I rarely hear about other groups in Milwaukee that I should check out. So Web414 does help to fill that niche where users groups don’t exist. But maybe Web414 can be a catalyst to letting people meet and spin off their own groups. Having a new permanent location would certainly help, if Bucketworks is game to open up their space in the future for other groups. I’m looking forward to seeing what happens with all these groups and awesome people (who I’m glad to call my friends) in the new year.

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Thu, 07 Jan 2010 12:00:00 -0800 Pulled Thoughts http://blog.mattgauger.com/pulled-thoughts http://blog.mattgauger.com/pulled-thoughts

    (This post is part of my blog archiving project. This post appeared on blog.mattgauger.com on January 7, 2010.)

    Below are several bits and pieces of my previous blog post which didn’t ultimately get included. I thought that there were some neat thoughts in here, so I included them, without rewriting to add context. Enjoy.


    Research in artificial intelligence can trace its roots back to the father of the universal computer, Alan Turing. He famously concocted the Turing Test, whereby a computer might be able to prove itself sentient. But as we’ve found, being able to a fool a human and perhaps know how to respond in human language does not make a sentient computer.


    While there are several approaches to artificial intelligence, the two relevant disciplines I’m going to discuss are top-down design and bottom-up design. Bottom-up can better be called behaviorism, or the emergent behavior approach. (note: these are my own classifications, not necessarily the academic definition, and blatantly stolen from Steve Grand’s explanations in his book.) Emergence is the topic of several interesting books that I’ve read over the years.


    Grand suggests that a ‘cyberspace’ be created and a first-order of complexity be coded into it to jumpstart artificial life, rather than trying to model and perfect an a-life creature with no environment or need for survival. Artificial life would be a second order of complexity that would emerge from the simulation. (He asks, what does a translation program care about its survival? Can we really reward it for better translation or punish it and threaten its survival for messing up?)


    Traditional software engineering is largely monolithic and still waterfall-based. Object orientation and various Agile/XP paradigms have changed that, but have not succeeded in breaking the monolithic concept. APIs and protocols are still brittle and lack the ability to adapt. I’ve yet to work out all the implications, but a method of software engineering based on these concepts of adaptation and feedback loops could be very powerful.


    I’ll be curious to monitor the progress of Jeff Hawkins and others’ research with the HTM model. I think that they may have the best model for working on a general artificial intelligence, even if it does not ultimately lead to one. Neuroscience is still a field where there is a lot left to learn on many levels, and hopefully a feedback loop is established in which the field of artificial intelligence continues to benefit from neuroscience research. ;)


    Hopefully some day Steve Grand will also get the recognition he deserves for the contribution the Creatures game made to a-life. Perhaps his work will inspire a different type of video game opponent AI that attempts to survive in its simulated world rather than just play against the human, but I have not seen that kind of complexity given to video game AI yet.


    End signal.

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Tue, 05 Jan 2010 12:00:00 -0800 Feedback Loops and Emergent Behavior http://blog.mattgauger.com/feedback-loops-and-emergent-behavior http://blog.mattgauger.com/feedback-loops-and-emergent-behavior

    (This post is part of my blog archiving project. This post appeared on blog.mattgauger.com on January 5, 2010.)

    This post started out as a review of two books. My friend Zac Witte introduced me to the work of Jeff Hawkins, previously of Palm and now working at a company called Numenta, which is working on a method of creating artificial intelligence. Hawkins wrote a book called On Intelligence in 2005 detailing his research into artificial intelligence up to that point. Zac recommended the book while we were hacking on code at a coffee shop here in Milwaukee.

    I countered by recommending the work of Steve Grand, who is responsible for one of my childhood videogame addictions: Creatures. Creatures was an artificial life simulator that was deceptively simple and childlike. Yet behind the scenes, complex biological processes were being simulated and multi-lobed brains were allowing the Norns, the Creatures of the game, to think. At least, think in a rudimentary, simulated way.

    Steve Grand wrote a book called Creation: Life and How to Make It detailing his experience in coding the game. It quickly runs through several thought experiments in how one might simulate physics, matter, and chemical reactions. (And indeed, what these simulations say about the real world.) Grand likes to link various disciplines together, and the book easily jumps from transistors and electrical engineering to neurons to chemical reactions and on to more abstract concepts. Grand’s work can be said to be of the field of artificial life, or A-life, and not necessarily artificial intelligence.

    Emergent behavior theory suggests that complex behavior emerges from simple behavior. Or rather, that the whole is smarter than the sum of its parts. Think of an ant hill, which does not really have a leader yet manages to survive and adapt through simple actions of the ants. Emergent behavior found its popularity among the MIT Mobile Robot Lab, among other places. Simple behaviors telling a robot how to react to stimuli, for example, to back up its right wheel when the front left bumper is pressed or vice-versa, can produce seemingly intelligent behavior.

    Jeff Hawkins began to study AI by reading as many scientific articles as possible. But, he was frustrated by the seeming lack of progress and unwillingness of the AI field to study real neuroscience. Hawkins wanted to study the human brain and use that for inspiration into how to create a general artificial intelligence. Traditional academic approaches to artificial intelligence at that point completely ignored neuroscience. Hawkins does not want to fully simulate the brain at some chemical level, either. Instead, Hawkins studied the neocortex, in his view the most important key to understanding the human brain. His research led him to an architecture he calls Hierarchical Temporal Memory, or HTM, based on how the brain processes patterns and fragments across time rather than whole memories instantaneously.

    Hawkins discusses some of the shortcomings of traditional neural network research. Most neural networks, from the 70’s to the present, were simply three stages of neurons: an input stage, a “black box” stage, and an output stage. Neural networks were trained with sample data, in which connections between neurons could strengthen or weaken. But after training, the neurons’ connections are “locked” and no further training occurs. Hawkins likens three stage neural network research to reverse engineering the transistors in a modern computer and being able to build simple amplifier circuits, or perhaps transistor radios. There is interesting behavior in an amplifier circuit, but it will never be a digital computer.

    So why are these two books together in one review? Grand is an artifical life video game creator, and not at all interested in the same kind of artificial intelligence that Hawkins hopes to create. Their research seems to be opposed, or at least completely different.

    The concept that these two differing authors agree on is the importance of feedback loops. Those traditional three stage neural networks rarely included simulating feedback loops in the neural connection, while the human brain’s neocortex is largely feedback loops. Further, the number of connections coming in from the senses to the brain is far outweighed by the number of connections going back out to the sensory organs, in a nearly 10-to-1 ratio. This is extraordinary if you think that the brain simply processes incoming data passively. It is actively responding and anticipating sensory data.

    You remember music in bits and and fragments rather than whole songs. There is a time element to these memories. You can’t remember the whole song all at once, or hear every note at the same time. The same can be said for all memories. Hawkins points out that being able to predict the world led to the brain being organized this way. After all, prediction is a powerful survival skill.

    Grand writes:

    Living beings are high-order persistent phenomena, which endure through intelligent interaction with their environment. This intelligence is a product of multiple layers of feedback. An organism is therefore a localized network of feedback loops that ensures its own continuation.

    We can find feedback loops around us everywhere in nature. One of my favorite examples comes from the book Sync. Fireflies in Thailand will swarm in tall grass, flashing randomly. But they synchronize with each flash, until the whole swarm flashes in unison. How do they do it? There is no leader or conductor telling the fireflies when to flash. They change the rate of their flashing slightly, faster or slower, until they all match and the flashing syncs. Surprising complexity and cooperation can therefore occur from simple, basic behavior.

    One of the places where a feedback loop exists in technology is in the TCP/IP protocol. In a simplified view, one could say that the rate of packets being sent is regulated based on signal loss. The machines at both ends of a network connection don’t know anything about the connection between them or how good it is. They simply use the degradation of the signal - whether packets make it through and are responded to - to modulate whether to send more packets or the same packet over. This feedback loop has a speed regulating effect. The feedback loop ensures that the message will get delivered, even over a bad connection.

    Feedback loops and emergent behavior are both fields of research that I’m actively interested in learning more about. These books have fueled my thoughts for further exploration of both concepts. While feedback loops and emergent behavior may not have applications in all endeavors, they can be powerful solutions to the right problem.

    The research of both authors is interesting and their books are highly readable. They both provide interesting thinking on the brain and the natural world, and I’d like to follow up with more books in these areas. Both books are relatively short are definitely recommended reads. Too many ‘pop science’ books seem to fall to the side of including too little real science, or paraphrasing studies that don’t really have a neuroscience background. I’ve had that issue with recent books on the human brain and learning marketed towards computer programmers: much of it was based on nonscientific surveys or speculation, which was highly disappointing.

     

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger
    Mon, 28 Dec 2009 12:00:00 -0800 Purpose http://blog.mattgauger.com/purpose http://blog.mattgauger.com/purpose

    (This post is part of my blog archiving project. This post appeared on http://blog.mattgauger.com/2009/12/28/purpose/ on December 28, 2009.)

    Every blog has to have a purpose. For awhile, I had a blog hosted on Wordpress.com, The Byte Codex. I had told myself that it was my coding blog, and that all insights I gained in coding would end up there. Also, I’d blog about tech events I attended.

    Unfortunately, I wasn’t coding enough and consistently at a level to produce world-changing “insights” on a regular basis. I got really wrapped up in trying to find something I could claim expertise on, and then blog about. But I wasn’t an expert on anything and wasn’t creating anything. The frustration and self-censorship about what I told myself I was supposed to be posting crippled my posting momentum. Further, the Midwest wasn’t providing many tech events for me to blog about, and the recaps all were more hazy memories surrounded by other people’s Creative Commons-licensed pictures of the event. (I usually am having a blast and forget to take notes or my own photos.)

    All of my previous blogs had ‘rules’ in my head about what they were for and what could or couldn’t be posted on them. All of them failed. There’s something telling here. I think there’s plenty of reasons to have a specialized blog for different topics, possibly even trying to keep your life or your work separated out. But for me, I’m going to stick with a nice mix of personal anecdotes, book reviews, bike stuff (did I mention bikes yet on this blog?) and of course, little coding projects. I don’t want to wall myself in with rules that those are the only things that can get posted here, either. I have to take a deep breath, put away my inner quality control and publish everything.

    A blog can have a purpose, but it shouldn’t be so narrowly defined that it never gets updated. After all, a blog with new posts is better than an insightful blog that has gone stagnant, in my book.


    Appendix: A little history:

    In the past, I’ve had several blogs:

    Luckily, those blogs are not too terribly embarrassing to share.

     

    Permalink | Leave a comment  »

    ]]>
    http://files.posterous.com/user_profile_pics/772477/matt_avatar_resized.jpg http://posterous.com/users/36zEVLVG8beh Matt Gauger Matt Matt Gauger