Suppose I have a some kind of object that represents a person, and they have a date of birth:

@user = User.create(
:birthday => Date.parse('01-01-1901')
)

How do you find out of today is their birthday?

You could compare :birthday with Date.today, but that would fail since the years will be different.

You could use the Date Class method ‘yday’, which returns the day of the year, and compare them but that will fail after any leap year has passed.

You could get :birthday’s year (@user.birthday.year), then convert :birthday to a string and replace ’1901′ with the current year, run that back through Date.parse and then compare it with Date.today… but that seems like a lot of slow steps.

There’s an easier way though, since we don’t actually care about the year at all.

Instead, compare just the month and the day:

@user.birthday.day == Date.today.day && @user.birthday.month == Date.today.month

That will compare just on the month and day and ignore the year. But that’s two comparison and two instantiations of the Date class, and we can do better:


def same_day?(date)
today = Date.today
"#{date.mday} #{date.mon}" == "#{today.mday} #{today.mon}"
end

same_day?(@user.birthday)

There you go. You may ask why not use “strftime” to format the string and compare that? Because that can be really slow on some systems.

Paperclip is a fantastic plugin for working with uploads from a user, but sometimes you need to manipulate the attachments outside of a web-browser-upload environment.

I needed to do that the other week and it was a complete pain, but I figured it out. The docs for paperclip mention that you can do

a.attachment = b.attachment

.. but that’s only useful if you want to move an attachment between two object and the attachment already exists. But what if you want to create the attachment from scratch? Paperclip::Attachment.assignment only works for re-assigning attachments that already are created.

After some poking around I found that the way (one way, anyway) is to make the object (where Paperclip has an attachment) think it’s being hit by a web browser:


data = method_that_reads_an_image_file_contents

tmpfile = Tempfile.new('temp')
file = File.new(tmpfile.path, 'w')
file.puts data
file.close

object.create(
:attachment => tmpfile
)

You can do similar for updating an existing object:

object.update_attributes(:attachment => tmpfile)

That worked almost perfectly, until I realized that the attachments were all being stored in Paperclip with the ‘application/octet-stream’ mime-type, which is a killer because the users web browser will, say, ask the user to download an image instead of just displaying it on screen.

And it’s no use just updating the ‘attachment_file_type’ column with the right mime type, either smart guy.

Instead I found I needed to do some hackery — Paperclip divines the file type partly by the file extension and the built-in Tempfile library in ruby does not allow you to set the extension of your tempfile. And with no extension set, Paperclip was using the default “octet-stream”.

In the end I had to resort to this:


def write_to_tmpfile(data,mime=nil)
tmpfile = Tempfile.new('tmp_'+rand(10).to_s)
file = File.new(tmpfile.path, 'w')
file.puts data
file.close

if mime
ext = mime.slice(mime.index('/')+1, mime.size)
File.rename tmpfile.path, "#{tmpfile.path}.#{ext}"
File.new("#{tmpfile.path}.#{ext}", 'r')
else
tmpfile
end
end

event.update_attributes(:attachment => write_to_tempfile(file_data))

The ‘write_to_tmpfile’ does the ugly work of renaming the temp file created by Tempfile to be the same as the file being inserted, and that in turn allows Paperclip to properly set the mime time.

Every Apple Macbook and Macbook Pro and some of the last Powerbooks have shipped with something called the “Sudden Motion Sensor” which is basically a chip that detects when your laptop is about to crash, literally: It’s a chip that can sense sudden changes in orientation or velocity and then trigger the heads on the hard disk to “park” (move to a safe area) as rapidly as possible to prevent then from crashing in to the disk surface and destroying data — or the drive.

In basic terms it means when your laptop falls off your desk, this chip ensures the data on the disk is preserved even though the rest of the machine may be a total write-off.

The chip itself is a gyroscope+accelerometer package that can do a lot more than just see when you’re about to have a large repair bill — you can tap in to it to see how your laptop is oriented in space and any motion it is currently undergoing.

TEACHING YOUR CODE WHICH WAY IS UP

Formerly, the easiest way to tap in to the feed from the SMS hardware was to read the output of a command-line program called “AMSTracker“. It’s still a great program but using it (reading it’s output like a filehandle) is very un-Ruby-like.

The Rubyista option is my new gem sudden_motion_sensor, available now on rubygems.org. It packages some Objective-C code from Fazibear into a ruby gem you can use with minimal effort. Simply:

sudo gem install sudden_motion_sensor
..to start using it.

It reads from the SMS and returns the X and Y orientation of the computer along with acceleration (gravity actually) as a vertical axis Z. That means you you can tell the angle your Macbook is presently at and how fast it’s moving.

So when I use the demo code:

require 'rubygems'
require 'sudden_motion_sensor'

loop do
x,y,z = SuddenMotionSensor.values
puts "X: #{x}, Y: #{y}, Z: #{z}"
sleep 0.1
end

..I get back three signed integers:

* X: -255 to +255 as the left-to-right angle.
* Y: -255 to +255 as the front-to-back angle.
* Z: current gravity along the vertical (90 degree X) axis

The values for X and Y read “0″ when they are flat across that plane, be it right-size-up or upside-down and count up to 255 at 90-degrees on one side and -255 on the other.

As for Z, on my machine it seems to sit at around 265 when stationary, but I can make it go as high as 400 or as low as 100 if I move the laptop up and down quickly.

WHAT DO I WITH IT?

Lots of things! The canonical example is the great “smackbook” toy or tools like Seismac .

For the rubyist, you can have all kinds of fun. A basic toy is this:

#!/usr/bin/env ruby

require 'rubygems'
require 'sudden_motion_sensor'

x_threshold = 10

px = 0; py = 0; pz = 0
loop do
x,y,z = SuddenMotionSensor.values

if (x.to_i > (px.to_i + x_threshold.to_i).to_i)
system("say Stop it. &")
end

px = x; py = y; pz = z
sleep(0.1)
end

..which, when the SMS sensor value of X changes more than x_threshold in a single sample causes the program to tell you to knock it off because you’re obviously hitting your poor laptop!

But we can be more creative than that.

Did you have an Etch-a-Sketch(TM) when you were a kid? Neither did I, but I was envious of everyone who did. And I’m still bitter about it, so here is some code that makes up for my years of terrible childhood repression.

This code taps in to the sensor and draws lines on the screen based on the X/Y Tilt of the laptop and the colour is based on the Z axis. It uses the ‘Gosu’ game engine for screen drawing. Install it with

sudo gem install gosu

#!/usr/bin/env ruby
require 'rubygems'
require 'sudden_motion_sensor'
require 'gosu'
include Gosu

class GameWindow < Gosu::Window
def initialize
@window_x = 1024; @window_y = 768
@x_scale = ((@window_x/254)/2).ceil; @y_scale = ((@window_y/254)/2).ceil

@draw_dots=true
@dotsize = 2
@draw_lines=true

super(@window_x, @window_y, false)
self.caption = "Sketch-n-etch"

@center_x = (@window_x/2).ceil
@center_y = (@window_y/2).ceil

@positions = []
end

def update
x,y,z = SuddenMotionSensor.values
@cursor_x = @center_x+(x*@x_scale)
@cursor_y = @center_y-(y*@y_scale)
@cursor_z = z

@positions.shift if @positions.size > 100
@positions << {:x => @cursor_x, :y => @cursor_y, :color => Color.new(0xFF0088FF + rand(z.abs ** 2))}
end

def draw
@positions.each_with_index do |p, i|
if @draw_dots
self.draw_line(p[:x]-@dotsize, p[:y]-@dotsize, p[:color], p[:x]-@dotsize, p[:y]+@dotsize, p[:color])
self.draw_line(p[:x]-@dotsize, p[:y]+@dotsize, p[:color], p[:x]+@dotsize, p[:y]+@dotsize, p[:color])
self.draw_line(p[:x]+@dotsize, p[:y]+@dotsize, p[:color], p[:x]+@dotsize, p[:y]-@dotsize, p[:color])
self.draw_line(p[:x]+@dotsize, p[:y]-@dotsize, p[:color], p[:x]-@dotsize, p[:y]-@dotsize, p[:color])
end
if @draw_lines
self.draw_line(p[:x], p[:y], p[:color], @positions[i-1][:x], @positions[i-1][:y], p[:color]) unless i==0
end
end
end

def button_down(id)
if id == Gosu::Button::KbEscape
close
end
end
end

window = GameWindow.new
window.show

Screenshot:

That’s basically all there is to tell.

Caching is great and memcache, despite other alternatives being available, is still great too. You can accelerate and app, shard your data, whatever.

It’s a black box in a way, though, too. It can be difficult in a production or pre-production environment whether or not your cache is actually being used. I had that problem today and having never used memcached under Rails before (perl, yes) I wanted to be sure that things were happening under the covers the way I wanted them to.

Testing that your app is writing to the cache is easy. Memcache doesn’t believe in binary protocols, it uses text and you so you can communicate with it in text. The memcache server itself will respond to command you give it from a raw socket or even telnet. Simply telnet into the servers’ bound IP and port:
# telnet localhost 11211
And you should be given nothing but a blank prompt. But from there you can do basic commands like
stats
Which will print you out some basic stats. Their details are better discussed in better blogs so I won’t bother here. What I’m more interested in is seeing if the data I want to be written IS being written.

So, I find the cache key Rails is using in a place like this for example:

Rails.cache.write('Some_Key_23', value, :expires => 1.hour)
..and I enter that key name into the telnet prompt I have open to my memcached server
get Some_Key_23
If that key is NOT on the server all I get back is “END”, but if there is data written to that I will get something more like
VALUE Some_Key_23 0 8
Hello!
END

If I wanted to delete that key I could then issue
delete Some_Key_23
And the value would be deleted and I could check if it gets recreated again with the ‘get’ command.

I can even WRITE data to a key with telnet, but NOTE, it’s pretty hard to do by hand because the Rails default cache handler is going to write data to the cache as a data object (e.g. a String, Hash, Array, etc) and you’d have to write hex to the terminal to get the same effect. Not fun.

Instead, I wrote up a small rails command line app to handle it for me called ‘memcacher’:

#!/usr/bin/env ruby
require 'rubygems'
require 'trollop'

opts = Trollop.options do
opt :key, "key name", :type => :string, :required => true
opt :write, "data to write to key", :type => :string, :required => false
opt :environment, "Rails Environment", :default => "development", :type => :string
opt :inspect, "read data with .inspect or write with eval {}", :default => false, :type => :boolean
end

RAILS_ENV = opts[:environment]
require File.dirname(__FILE__) + '/../config/environment'

if opts[:write]
if opts[:inspect]
Rails.cache.write(opts[:key], eval(opts[:write]), :expires => 1.hour)
else
Rails.cache.write(opts[:key], opts[:write], :expires => 1.hour)
end
else
if opts[:inspect]
puts Rails.cache.read(opts[:key]).inspect
else
puts Rails.cache.read(opts[:key])
end
end


This way I can use a more sensible tool to read data, see what type it is or even WRITE it.
# memcacher -k Some_Key_23
Hello!
# memcacher -k Some_Key_23 -i
“Hello!”
# memcacher -k Some_Array_23 -i
["Hey there!"]
# memcacher -k Some_Array_23 -i -w “[['Yo Dawg'], ['I heard you like arrays'], ['so we put arrays in your arrays']]”
# memcacher -k Some_Array_23 -i
[["Yo Dawg"], ["I heard you like arrays"], ["so we put arrays in your arrays"]]

So, what good is it to be able to change the contents of a cached object? Well, if you want to do some visual testing on your caching you can wait for a cache key to be generated, redefine it with your new data and reload the page to see: if the data you manually write to the cache gets displayed you know your app is caching properly, otherwise it’s not and the data is being pulled from somewhere else.

It’s no secret that MWRC received a record number of presentation proposals this year and schedule is going to be excellent. However, you may be interested in knowing some of the talks that wererejected: at great personal risk I slipped passed the heavily armoured Elite Rubyista Guards and rifled through the dumpster at the secret MWRC bunker (located at the bottom of Bingham Canyon Copper Mine) to find a list of the talks you *wont* be attending this year:

In no particular order:

  • “9 ways to segfault your system with eval()”
  • “-1 things you should never do with the Integer class”
  • “Regular Expressions and other forms of cruel and unusual punishment”
  • “Scaling Rails: a one-man comedy show”
  • “To understand metaprogramming you must first understand metaprogramming”
  • “‘Marshal.dump’ and 16 other potty-jokes in ruby”
  • “IronRuby: yes, we’re serious, I swear, stop laughing”
  • “Advanced Recursion” (cancelled: stack level too deep)
  • “Spec’ing your specs, an OCD guide to software testing” (followed by the “spec’ing your spec specs” lightning talk)
  • “‘Write it yourself’, a 0-line web framework”


require File.dirname(__FILE__) + '/../spec_helper'
describe "RickAstly" do
before(:each) do
@rick = RickAstley.new
@rick.stub!(:rickrolled).and_return(true)
end

it "should never give you up" do
@rick.give_you_up?.should be_false
end

it "should never let you down" do
@rick.let_down(mock_model(You)).should == 'never'
end

it "should never run around and hurt you" do
@rick.run_around.andand.hurt_you.should be_nil
end

it "should never make you cry" do
@rick.make_cry(:person => 'you').should have(0).things
end

it "should never say goodbye" do
lambda { @rick.say(GOODBYE) }.should raise_error(RickAstley::InvalidStringError)
end

it "should never tell a lie and hurt you" do
@rick.tell.should_not respond_to(:lie)
end
end