Monday, November 22, 2010

Tag-it 0.3.1 is released!

If you've been a consistent reader, you know that last month I released a new gem called "tag-it" to interface with RFID receivers and the tags that come into range with them. Today, there's a new version with a new feature.

In version 0.2.x, there was 1 primary class for continually monitoring a port for tag events. This doesn't do everything I wanted though, because in some cases I really just needed to know what tags were in range at one precise instant. The long-running class really wasn't a good fit, so there's a new class available called TagIt::TagSnapshot which has a "shoot!" method that returns an array of the tag-names currently found:

  require "tag_it"
  port = SerialPort.new("/dev/tty.yourport",{:baud=>9600})
  snapshot = TagIt::TagSnapshot.new(port)
  tags = snapshot.shoot!
  # => ["1nri","1okD","1nrP"]
Get the latest:

  gem install tag-it

Tuesday, November 16, 2010

json (_pure) ruins my morning

wrong argument type JSON::Pure::Generator::State (expected Data)

This is what I saw staring back at me from my console this morning when I checked out a project and ran my specs. Specs that had been passing just fine yesterday. The only thing I could think of was that I had added a couple new gems to my gem file, but since I hadn't used them yet surely they couldn't be breaking my test suite?

Well, if you've been a coder for any length of time, by now you should know that the likelihood of a given event contributing to your code failure is inversely proportional to your initial index of suspicion of it's relation.

Fortunately, I didn't have to search long. Googling for "wrong argument type JSON::Pure::Generator::State" quickly turned up this blog post on prettystatemachine that explains the problem. Those gems I'd added? One had "json_pure" as a dependency, so I'll include my own brief version for reference:

ActiveSupport and json_pure both hook into the "to_json" method. ActiveSupport defines to_json for many simple types, but expects fixnum's "to_json" to be handled by Object. json_pure is intercepting that call and not getting the data it wants. Defining "to_json" on fixnum seems to solve the problem.

Hence, I've created an initializer in my rails app called "./initializers/json_patch.rb" and put the following code in it:


class Fixnum
  def to_json(options = nil)
    to_s
  end
end

Specs pass. I would thank "prettystatemachine" by name, but I can't find any reference to the author of the blog. Whoever you are, thanks man.

Saturday, November 13, 2010

Hello node

I've been playing a bit with node.js recently, but have had trouble getting my friends to try it out. They hate javascript, can't see how this framework is any different, won't even give it a look, and further more evented programming sucks.

Well, everyone is entitled to their opinion, but you can't really have a valid opinion without the information. Node.js and other event driven models (EventMachine in ruby, etc) are going to continue to be a huge deal as more applications require more realtime information to be pushed between client and server, let's at least know a little about the tools that are probably carrying the future on their actively-under-development shoulders.

In this spirit, I've put together a very simple "hello world" application in Express (web framework for node.js), available on my github profile here: Hello Node

You see how nice I am? You don't even have to write your own hello world, I just did it for you, all you have to do is check out the code and read through all 4 files therein to get a feeling for why this new tool really isn't all that unfamiliar compared to whatever web framework you're working with now. No fan-boy over-hyped blog post about it's infinite scalability, no drooling and sobbing over how wonderful it is, just a few blocks of harmless code that wants to be your friend. Still hate everything about it? Fine, but at least you'll have some ground to stand on from legitimately having taken a look.

Testing Heroku's SMS addon with Cucumber

(UPDATE: All code on this page is also available as a gist here: GIST)

I love Heroku's add-ons.

I love Cucumber testing.

But I sometimes hate putting the two together.  How do you test the infrastructure you don't know much about?  I've been confronted with this recently with the "moonshado-sms" addon, which is a super-simple way to hook your application up to a cheap sms gateway.  My integration tests were difficult, though.  How do I check that everything got sent appropriately?  That the SMS went to the right person, with the right number, and the right message?

I stumbled a bit, but came up with something that I think is pretty clever, and I'm going to share it here in case you have the same insatiable desire to see a series of green dots before deploying that I do.  In my env.rb file (for cucumber), at the bottom, I include some monkey patching of Moonshado's API:



module Moonshado
  class Sms
    cattr_accessor :sent_messages
   
    def deliver_sms
      raise MoonshadoSMSException.new("Invalid message") unless is_message_valid?(@message)

      data = {:sms => {:device_address => format_number(@number), :message => @message.to_s}}

      self.class.sent_messages ||= []
      self.class.sent_messages << data
      response = RestClient::Response.create('{"stat":"ok","id":"sms_id_mock"}', "", {})

      parse(response.to_s)
    rescue MoonshadoSMSException => exception
      raise exception
    end
  end
end

Now mix in some clever step defenitions with "sms_steps.rb" in your cucumber "step_definitions" folder:

When /^the sms message "([^"]*)" is sent to "([^"]*)"$/ do |number, message|
  Moonshado::Sms.new(message,number).deliver_sms
end

Then /^there should be an SMS sent to "([^"]*)" saying "([^"]*)"$/ do |number, sms_text|
  messages = Moonshado::Sms.sent_messages
  messages = Moonshado::Sms.sent_messages.select{|data| 
    data[:sms][:device_address] == number and data[:sms][:message] == sms_text
  }
  messages.size.should == 1
  messages.each{|msg| Moonshado::Sms.sent_messages.delete(msg)}
end

Then /^there should be no SMS messages sent$/ do 
  if Moonshado::Sms.sent_messages
    Moonshado::Sms.sent_messages.size.should == 0
  end
end

Take and edit for your own purposes, and may your code always be well tested.

(PS: All code on this page is also available as a gist here: GIST)

Changing Gears

Sometimes opportunities come into your life that seem too good to pass up. That happened to me this week when a conversation with the "higher-ups" at 12spokes Web Development turned into an offer.


Circumstances are such that this is a good time for me to make a move like that, so I was happy to accept, and for the foreseeable future that's where I'll be contributing the bulk of my Ruby on Rails skills. I've got a good vibe from this company, and am really looking forward to branching out onto bigger projects, so keep watching for any knowledge gems I pick up as I come up to speed on the current projects being worked on at this shop.

And by the way, if you're looking for a web development shop to build your next application....well, I know a guy. :)

Monday, November 8, 2010

Vim, Day 2

As I mentioned in a previous post, I recently started trying to use Vim instead of textmate as my default editor, with mixed results.

Are some of the command shortcuts awesome? Yes. I love "dd" for deleting a full line, and "o" or "O" for inserting a new line above or below where I am. But that doesn't totally make up for a loss of direction when it comes to moving between files; that's what I DIDN'T love.

Fortunately, one of my friends forwarded me this blog post by Yehuda Katz, where he gives a great summary of his experience in switching into Vim incrementally, but which also (most importantly to me) mentioned the "NERDTree" plugin.

If you don't know about it (I didn't) it gives you a "tree" interface to the directory you specify (I'm using my project home directory) and lets you use a mouse interface or a series of handy shortcuts to navigate. There's nothing else holding me back.

Now I'm sold. Powerful text editing, workable project drawer, I'm a Vim advocate from today forward.

Sunday, November 7, 2010

R you programming?

My wife is in school again getting her masters, and one of the classes she's having to take is statistics. An interesting side effect of this is that she's having to do something that she never thought she would: Programming! Yes, her class is using SPSS, but at home she's starting to work with the "R" programming language, and I'm frankly fascinated.

I'm so excited about sharing something technical with my spouse for the first time, that I'm downloading R onto my laptop myself to learn along with her, and I've bought "R in a Nutshell" from the O'Reilly book series to help me along the way. In this post, I'll be cataloguing some of my first impressions as I play with this new (to me) language.

1) R is interpreted, has a REPL, and so reminds me of when I first started learning Ruby or LISP.

2) R uses vectors a lot, which is expected for a language designed for statistical analysis. Although initially I was thinking of them like an Array, in truth they're different and in some cases a little more powerful than arrays in other programming languages. Vectors provide advanced indexing (integers, ranges, mapped selecting functions) and vector arithmetic both in a concise format.

3) functions in R are just objects. This provides for an interesting source reading technique:
> double_func = function(x,y,z){ c(x*2,y*2,z*2)}
> double_func(2,4,6)
[1] 4 8 12
> double_func
function(x,y,z){ c(x*2,y*2,z*2)}

4) R also has a class for arrays (which is defined as multidimensional vectors), and although I've dealt with multidimensional arrays before, they feel totally different in this syntax:
> a = array(data=c(1:100),dim=c(2,10,3,2))
> a
, , 1, 1

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    1    3    5    7    9   11   13   15   17    19
[2,]    2    4    6    8   10   12   14   16   18    20

, , 2, 1

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]   21   23   25   27   29   31   33   35   37    39
[2,]   22   24   26   28   30   32   34   36   38    40

, , 3, 1

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]   41   43   45   47   49   51   53   55   57    59
[2,]   42   44   46   48   50   52   54   56   58    60

, , 1, 2

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]   61   63   65   67   69   71   73   75   77    79
[2,]   62   64   66   68   70   72   74   76   78    80

, , 2, 2

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]   81   83   85   87   89   91   93   95   97    99
[2,]   82   84   86   88   90   92   94   96   98   100

, , 3, 2

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    1    3    5    7    9   11   13   15   17    19
[2,]    2    4    6    8   10   12   14   16   18    20

5) "lists" in R are a little different in that they can have named components and can hold different object types. Building a list in R almost feels like building a struct in C++ or Ruby:
> car = list(make="Honda",model="CRV",mileage=1258)
> car
$make
[1] "Honda"

$model
[1] "CRV"

$mileage
[1] 1258

> car$make
[1] "Honda"
> car$model
[1] "CRV"

6) Everything in R is an object, and a "class" is basically a certain type of function definition. In this way, the language feels reminiscent of javascript, where there isn't really an alternate sytax for defining global functions and object classes.

That's all for one day, don't want to cram in too much at one time. But as an overall impression, I'm getting a feeling for why the language is so valued for statistics. Data is very easy to build and manipulate en masse, and I'm sure that although I haven't gotten there yet, there are probably many built in functions for analysis to help along the way. Subscribe to my RSS feed if you want to get further updates as I dig deeper into the R language in weeks to come.

Friday, November 5, 2010

Embedding Cramp in a Rails App, Part II

After my last post on getting "Hello World" running on Cramp alongside a full rails application, I thought I'd continue to catalogue my progress on actually getting a websockets action running and doing a real data push back to the client.

First things first, the blog post by Pratik that introduces the concept is invaluable: http://m.onkey.org/2010/1/15/websockets-made-easy-with-cramp.

Following the directions there, I created an initializer (config/initializers/cramp_server.rb for cramp and included the following:
Cramp::Websocket.backend = :thin

Notice that this isn't quite the same as the blog post, because I'm using edge cramp, and it's been refactored to remove the "Controller" module.

Anyway, rebooting the server everything still worked, so the next step was to rebuild my controller as a websockets aware rack application.

class ChatAction < Cramp::Websocket
  on_data :received_data

  def received_data(data)
    render "Got your #{data}"
  end
end

Which did indeed startup and respond to data requests from the client with an echo. Nice!

However, in order to support IE users, it would be necessary to use flash sockets, and although it's not that hard to do, I'm already getting uncomfortable with the number of things that are new to me in this app. So, as a responsible design decision, I'm planning on just using Cramp for long-polling for the time being until better websockets support is available across all the major browsers.

Thanks Pratik for such a cool framework!

Embedding Cramp in a Rails App

So I have an application that would work great with websockets because I don't want to be doing client polling. Rails doesn't deal with this right now, but Cramp does (cramp is a young web framework built on top of EventMachine). I know, I know, Node.js right? But I've already deployed on Heroku and they aren't taking new participants for their Node.js beta, so I'm going to have to make it work.

Now, Cramp is indeed a Rack-based framework (mostly, sometimes not compliant), so theoretically I should be able to do this, and if it works out you'll have this post to help you along the way (using Rails 3.0, BTW).

First, I added Cramp to my gemfile (gem "cramp") and tried to bundle install it. Failure. The current cramp gem depends on arel (= 0.3.3), and Rails 3 of course need arel 1.1.0.

To fix that, I tried loading edge cramp into my app by using the git repo in my gemfile:
gem "cramp",:git=>'git://github.com/lifo/cramp.git'

So far so good, at least the bundle installed correctly.

Before going any farther, I also added "thin" to my gemfile to use as my webserver in development, because in the Cramp documentation they point out that Cramp only works with Thin or Rainbows!.

Now, to get a cramp application running. I saw a great Screencast by Ryan Bates about Routing with Rack, so that's the approach I'm going to take using the "Hello World" example from this blogpost (IMPORTANT: Edge cramp does not use "Cramp::Controller::Action" anymore like in that blog post, Action is directly under Cramp now). To clarify, I'm dropping the following class into the lib directory:

class ChatAction < Cramp::Action
  on_start :send_hello_world

  def send_hello_world
    render "Hello World"
    finish
  end
end
And then tried to route a path to it (routes.rb):
MyApp::Application.routes.draw do
  match "/chat"=>ChatAction
end
Starting up the server, I got a failure due to an uninitialized constant (It doesn't know about my ChatAction yet). I had to think about the right place to load it, because I haven't really traced the rails startup sequence before. Looking in "application.rb", Bundler loads all it's gems after loading up rails, so I decided to drop in my requirement right after that (load all bundler gems, than load my Cramp application, then start with the rails app config):
require File.expand_path('../boot', __FILE__)

require 'rails/all'

Bundler.require(:default, Rails.env) if defined?(Bundler)
require "lib/chat_action"

module MyApp
  class Application < Rails::Application
    config.autoload_paths += %W( #{config.root}/extras )
    
    config.encoding = "utf-8"

    config.filter_parameters += [:password]
  end
end
That seemed to work; at least everything booted without any more errors when I did this from the application home directory:
rails server thin

and when I traveled to "localhost:3000/chat", I saw my "Hello World" render as expected.

So there you have it, how to get a cramp application running in your Rails 3 application (in the patented "Stumble your way through" methodology). Now to actually make it do something useful!

Thursday, November 4, 2010

Vim at last

I've been using TextMate for a long time, and I love it. Starting my career in Visual Studio, the monster of all IDEs, I've gradually simplified over the years one small step at a time; First by moving to Eclipse, Than XCode, to netbeans, finally to TextMate, which I've been using for 3 years now. However, over that time period I've watched friends of mine blaze away in their code with their mystical mouse-less ways on editors like EMACS and VIM. Today I decided to dive in and try it out myself.

Setup

Downloading the Mac OS X binary for MacVim from the google group is not really in the spirit of the game (if I was feeling hardcore today I'd compile it from the source on github repo), but it sure is fast for setup. Uncompress, move the .app file into the Applications directory, and away you go (you can also move the "mvim" script that comes along with the download into a folder that's on your Path so you can open it from the command line any time; I did). Of course, that's also when I realized that the console version of Vim comes standard on my Mac. Oh well, use which ever you prefer.

Learning

The first thing I notice is that nothing makes sense. I can't seem to click anything. Than I remember that you aren't really supposed to be trying to click on things if VIM is your editor of choice, because it's keyboard focused. Realizing I'm not going to figure this out myself, I opt for running "vimtutor" at the console which gives you a concise walkthrough on how to operate inside this strange program.

Results

...Time passes...

Ok, so now I can move text around in VIM pretty comfortably, and when editing a single file, I'm pretty solid. I'm happy with how short the commands are to do things that require a lot of highlighting and click-dragging in modern editors (delete a full line, jump a few words down the line, etc). What I'm NOT comfortable with yet is jumping around to different files in a project, and the syntax highlighting is still unfamiliar to me. However, the only way to GET used to it is to use it, so although it's going to hurt for the first couple days I'm sure, I think I have enough solid ground under my feet to make a go of it.(EDIT: rails.vim makes a big difference for me)

Stay tuned for updates on whether I find out that this really improves my coding or not.

Wednesday, November 3, 2010

The options Hash, a classic ruby pattern

If you use rails, or any of a thousand other ruby gems, you're familiar with using methods like this:


phone = SweetPhone.new
if caller.is_my_friend?
  phone.ring!(:volume=>6,:ringtone=>:smooth_jazz)
elsif caller.is_my_boss?
  phone.ring!(:volume=>11,:ringtone=>:totally_obnoxious)
else
  phone.ring!
end

yes, the conditional could be constructed to just build the hash and only call the method in one place, I know; that's not today's point. What I'm emphasizing is the fact that this "ring" method can just be called by itself, or with any of a series of options. It's nice, because you have intelligent defaults, and easy configuration if necessary.

The problem I see, is that even though this is the simplest of the basic ruby patterns that you see every day, and even though we're all more than happy to use these APIs in third-party libraries, I still run across code every now and then in home-brewed applications that looks like this:


class LamePhone
  def ring!(volume,ringtone,vibrate,max_rings,caller_id)
    #...
    #implementation
    #...
  end
end

and 80% of the code that calls these long-paramed functions uses the SAME SET OF PARAMETERS.

If you've been programming for a while, this isn't news to you, so disregard this post, but if you're new to ruby or software in general, take note: repeating yourself is a bad sign. If you're sending the same message from 50 places in your code, and 40 of them use the same function list, it may be time to set some intelligent defaults. To fix this anti-pattern, the options hash works beautifully:


class SweetPhone
  def ring!(options = {})
    adjust_volume(options[:volume] || 6)
    ringtone = pick_ringtone_from_category(options[:ringtone] || :all)
    sound_the_ringer!(ringtone)
  end
end