Tue, 08 Jun 2010 22:16:24 GMT

RailsConf 2010 - Baltimore

20100606_RailsConf_View.jpg

Here we go again RailsConf 2010 has started. The keynotes will be streamed online at http://railsconf.com and the slides of the presentation will also be posted there. I’ll provide more links once they become available.

This is the view from my hotel which is 5 minutes from the convention center where RailsConf is going on.

20100607_RailsConf_View_From_Hotel.jpg
20100607_RailsConf_Submarine.jpg

Acceptance Testing with Cucumber

I’m now following the Acceptance Testing with Cucumber tutorial. You can find the app we built, a kanban manager, on github.

Cucumber is executable documentation. Gurken is the DSL used to write your documentation in the form of

Scenario:
  Given
  When
  Then

The app has different git branches for each stage of the application. Checkout the move-card-passing branch for the most complete functionality. It contains great examples of feature test.


master f294f72 patch number
remotes/origin/HEAD → origin/master
remotes/origin/first-feature-failing 475eb7e words
remotes/origin/first-feature-passing e4ea67a gemfile
remotes/origin/latest eacd855 Merge
remotes/origin/master f294f72 patch number
remotes/origin/more-features-failing aa2d97b new failing features
remotes/origin/more-features-passing 03b6b44 added lane ordering
remotes/origin/move-card-failing 02fa766 add move_card feature

  • remotes/origin/move-card-passing 8c1d751 move cards from one lane to another

BUILDING AN API WITH RAILS

A great discussion on building APIs using Ruby and Rails:


Thu, 18 Mar 2010 12:20:16 GMT

Sneak peek of Usage Report for Amazon Web Services???????

I have been working on a tool to visualize your Amazon Web Services usage logs for EC2, RDS, SQS, S3, SDB (and soon CF). There will be a limited free version and a full version that has the dashboard and the drill down for each of the services. This tool is still in development but my todo list is getting shorter...so you can have a sneak peek here:

Sneak peek of Usage Report for Amazon Web Services??????? from daniel wanja.


Fri, 12 Mar 2010 12:43:49 GMT

MWRC 2010 - Notes from Day 1.

Jake Parsell took some really great notes using Google Wave. I know the videos will be available shortly but in the mean time if you want to figure out what you may want to watch you can find out more details below:

MWRC


Giles Bowkett - making some music with ruby Archaeopteryx

- Giles Bowkett: Archaeopteryx: A Ruby MIDI Generator

- learn probability matrix

- google is easy if you understand prob matrix

- google spell check in 21 lines of python

- wonder how easy OCR would seem in this context?

- don't understand python community.... why are there not more dick jokes about pythons?

- how is there not a web framework called trouser snake?

- oh yeah... better talk about lambdas


James Golick - Cooking with Chef - @jamesgolick github.com/jamesgolick

- Chef: Quick and Tasty Ruby Powered Server Configuration

- sysadmin work is boring

- too many config languages

- amazed if anyone can get nagios working on a consistent basis

- ues recipes to install packages

- recipes written in ruby

- create services -> status, restart, reload, etc.

- templates to create config files

- erb

- notifies restart if config changes

- autoreload on save very handy for things like dynamic lists of ips that change when you start a new EC2 instance

- makes setting up stuff like haproxy and heartbeat easier

- security

- easy to include iptables

- always turn off password ssh logins - easier to remember when part of your cookbook

- look into chef server and chef client


Joe Damato - RVM

- RVM: Ruby Version Manager - RVM Ruby Version Manager - Documentation

- RVM gemset - different gemsets for the same ruby version per project

- create rvmrc to switch env automatically when you cd into a project directory

- export gemsets?

- should you use gemsets or just bundler


Loren Segal - Documentation with YARD

- YARD 0.5.3 - The Longest

- Yet Another Ruby Documentor

- Talk about documentation in general

- Documentation to help you think about your API

- What makes documentation good?

- consistency -> pick a style and stick with it

- correct -> it can be wrong and should be audited

- coherent

- YARD

- meta-data

- @param [Symbol] req_type :get or :post

- ....

- yard-respec

- shows rspec specs alongside method docs

- yard-sinatra

- shows your routes for api



Michael Jackson - Rack for web developers

- Rack: a Ruby Webserver Interface

- Read the Spec

- blah, blah, blah

- rack is cool in that it allows web frameworks to communicate with web servers, but not sure you care that much unless making a web framework


Yehuda Katz - Modularity - Lessons learned from Rails 3

- Try to become modular too soon and you will be wrong

- Become modular once lack of modularity is hurting you, then decouple

- Constants -> Globals

- router.url_for in rails 3

- easier to track down where instance variables came from than Globals

- eliminate things that are global

- tests are the canary in the coal mine

- instead of hard coding contants, pass things around

- be subspicious of Contant.foo

- stop caring about object allocations

- object allocations are essentially free

- Render

- Controller -> ViewPathSet -> ViewPath -> Template (on file system)

- Used to assume actual file path

- hard to cache

- Template.new takes a path

- Now

- Caller -> LookupContext -> ViewPaths -> PathResolver-> Resolver -> Template

- Template.new takes a source

- Could overide PathResolver to pull from database or S3 or something

- could be useful in making a CMS system with Rails

- Use Modules

- don't put methods you want people to be able to override in a class, make a module

- then you cna call super

- Use ActiveSupport::Concern


Paul Sadauskas - HTTP

- read the spec :-)

- prevent the requests that you don't have to answer

- Persistent Connections - so you don't have to create a new TCP connection for every request --- keepalive=onC

- Caching

- how do you decide when something is stale?



Jeff Casimir - Ruby Processing

- dynamically generate images in ruby app

- uses jruby

- first built to create verticle column headers

- Distributed Programming with Ruby -> to learn how to send jobs to ruby processing from rails

- Beanstalkd -> simple fast background processing -> brew install beanstalkd???


Thu, 11 Mar 2010 23:53:46 GMT

MWRC 2010 - Day 1 Live Video

Moutains Pano + fingers

The conference is about to start in 30 minutes, the room starts to buzz. The confreaks guys have their camera and video recording equipment all setup. So you will be able to catch up the conference online soon. Somehow I really like single track conferences and the sessions seem really great and will be fast passed, 30 to 45 minutes. Check out the schedule. So I will sit back and enjoy the show.

Follow it live on Justin TV!!

Watch live video from Mountain West Ruby Conference on Justin.tv

Salt Lake City is definitively a beautiful city, surrounded by it’s mountains…

Library

Library


Fri, 04 Sep 2009 07:31:00 GMT

RMagick (from source) on Snow Leopard

After the release of 10.5, I published an article about building RMagick from source on Leopard. I won’t rehash the why, you can read the original article for that. My clean install necessitated updating the RMagick script, so here’s what worked for me to install from source on Snow Leopard! For the impatient, here’s the download link: rmagick-build.sh

First, we start with installing wget, as it seems to be a bit more clever than curl about dealing with mirrors, etc. Then, we compile and install each prerequisite package. Finally, we install the gem.

All the links in the script worked for me, but, depending on your location, network, conditions, etc, your mileage may vary. Enjoy!

#!/bin/sh

# install wget, which is cleverer than curl
curl -O http://ftp.gnu.org/gnu/wget/wget-1.11.tar.gz
tar zxvf wget-1.11.tar.gz 
cd wget-1.11
./configure --prefix=/usr/local
make
sudo make install
cd /usr/local/src

# prerequisite packages
wget http://nongnu.askapache.com/freetype/freetype-2.3.9.tar.gz
tar zxvf freetype-2.3.9.tar.gz
cd freetype-2.3.9
./configure --prefix=/usr/local
make
sudo make install
cd /usr/local/src

wget http://superb-west.dl.sourceforge.net/sourceforge/libpng/libpng-1.2.39.tar.gz
tar zxvf libpng-1.2.39.tar.gz
cd libpng-1.2.39
./configure --prefix=/usr/local
make
sudo make install
cd /usr/local/src

wget ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz
tar xzvf jpegsrc.v6b.tar.gz
cd jpeg-6b
ln -s `which glibtool` ./libtool
export MACOSX_DEPLOYMENT_TARGET=10.6
./configure --enable-shared --prefix=/usr/local
make
sudo make install
cd /usr/local/src

wget ftp://ftp.remotesensing.org/libtiff/tiff-3.9.1.tar.gz
tar xzvf tiff-3.9.1.tar.gz
cd tiff-3.9.1
./configure --prefix=/usr/local
make
sudo make install
cd /usr/local/src

wget http://superb-west.dl.sourceforge.net/sourceforge/wvware/libwmf-0.2.8.4.tar.gz
tar xzvf libwmf-0.2.8.4.tar.gz
cd libwmf-0.2.8.4
make clean
./configure
make
sudo make install
cd /usr/local/src

wget http://www.littlecms.com/lcms-1.17.tar.gz
tar xzvf lcms-1.17.tar.gz
cd lcms-1.17
make clean
./configure
make
sudo make install
cd /usr/local/src

wget ftp://mirror.cs.wisc.edu/pub/mirrors/ghost/GPL/gs870/ghostscript-8.70.tar.gz
tar zxvf ghostscript-8.70.tar.gz
cd ghostscript-8.70
./configure  --prefix=/usr/local
make
sudo make install
cd /usr/local/src

wget ftp://mirror.cs.wisc.edu/pub/mirrors/ghost/GPL/gs860/ghostscript-fonts-std-8.11.tar.gz
tar zxvf ghostscript-fonts-std-8.11.tar.gz
sudo mv fonts /usr/local/share/ghostscript

# Image Magick
wget ftp://ftp.fifi.org/pub/ImageMagick/ImageMagick.tar.gz
tar xzvf ImageMagick.tar.gz
cd `ls | grep ImageMagick-`
export CPPFLAGS=-I/usr/local/include
export LDFLAGS=-L/usr/local/lib
./configure --prefix=/usr/local --disable-static --with-modules --without-perl --without-magick-plus-plus --with-quantum-depth=8 --with-gs-font-dir=/usr/local/share/ghostscript/fonts --disable-openmp
make
sudo make install
cd /usr/local/src

# RMagick
sudo gem install rmagick

UPDATE There is a bug with libgomp that breaks the convert utility (See comments below). the --disable-openmp configure option has been added to the script to fix this.

UPDATE 2 A new patchlevel of ImageMagick has been released that supersedes the original one referenced in this script, and the original has been removed from the server. Thanks to Sebastian for this update that will grab the latest release.


Sun, 15 Mar 2009 08:50:00 GMT

MWRC - Thanks you, that what awesome!

We are at the airport on the way back to Denver from the MountainWest RubyConf. This was the best conference I went to in years. Fast passed talk with just incredible material and every presenter was just excellent. So to the organizers and presenters....Thank you! I'll be back! This was the Official Meme: Check out some of the comments from the last few hours or check all tweets regarding #mwrc.

Fri, 13 Mar 2009 21:17:07 GMT

MWRC - Moutain West Ruby Conference is about to start.

20090313_mwrc_attrium.jpg

The Confreaks guys did setup their cameras, sound and lights, so you will certainly be able to see all the talks in a few weeks.

The conference takes place in Salt Lake City, the scenery is impressive as the city is surrounded by high mountains…even for someone living in Denver. The picture above was taken just before the conference starts and shows the atrium we gonna spend the next two days in. The talks looks really cool and tonight the Engine Yard’s Hackfest 2.0 in suite next to mine at the Hilton Salt Lake City Center.


Thu, 12 Mar 2009 05:23:53 GMT

Advanced Ruby - Day 3

20090311_avancedruby.jpg

The first two days of the training were really excellent. Great pace, clear explanations and samples, very technical, Chad and Dave really rock at Ruby.

Making Domain-Specific Languages

We start with a discussion on DSL versus an API.

Meat-and-Potato DSLs

  • Block based API.
  • Directly manipulating domain model classes
  • Defining classes and methods
  • Manually typing repetitive, low-level code

Example is Rake. Rake is a dependency oriented programming language.

Eexample from Dhaka (a paraser generator)

for_pattern("\n") do
 create_token("newline")
end

method_missing Trick

require 'pp'

class CommandListener
  def initialize
    @commands = []
  end
    
  def method_missing(*args)
    @commands << args
    self
  end
end

listener = CommandListener.new

listener.instance_eval do
  this object accepts whatever you type and stores it
end
pp listener

outputs:

#<CommandListener:0x80264
 @commands=
  [[:you, CommandListener],
   [:whatever, #<CommandListener:0x80264 ...>],
   [:accepts, #<CommandListener:0x80264 ...>],
   [:object, #<CommandListener:0x80264 ...>],
   [:this, #<CommandListener:0x80264 ...>],
   [:it],
   [:stores, #<CommandListener:0x80264 ...>]]>
listener = CommandListener.new
listener.instance_eval do
  this.object.accepts.whatever.commands.and.stores.it
end  

pp listener

outputs:

#<CommandListener:0x712b4
 @commands=
  [[:this],
   [:object],
   [:accepts],
   [:whatever],
   [:commands],
   [:and],
   [:stores],
   [:it]]>

Note any keyword can be used with method_missing…E.g. freeze is not a missing method.

Now by using a BlankSlate object we can avoid this issue:

class BlankSlate
  instance_methods.each do |method|
    undef_method(method) unless method =~ /^__/ || method == 'instance_eval'
   end
end

We can now create a command listener that can use any commands:

require 'pp'

class CommandListener < BlankSlate
  def initialize
    @commands = []
  end

  def method_missing(*args)
    @commands << args unless [:inspect, :to_s].include? args.first 
    self
  end
  
  def pretty_print(pp)
    pp.output.write @commands.inspect
  end
    
end

listener = CommandListener.new

listener.instance_eval do
  You can even type freeze!
end
pp listener

And we get the following output:

[[:freeze!], [:type, #<CommandListener:0x7ee28>], [:even, #<CommandListener:0x7ee28>], [:can, #<CommandListener:0x7ee28>], [:You, #<CommandListener:0x7ee28>]]

On the same principals we just create a morse encoder, and of course Dave had to show off and interface with the speech function of OSX and another version that interfaces with the MIDI controller.

Exotic Control Flow

Creating a loop with continuations

def start_loop
  callcc{|c|c }
end

def end_loop(c)
  c.call(c)
end


i = 0
again = start_loop

  puts i
  i += 1

end_loop(again) unless i > 5

Moving on…

We voted on what to cover next as we won’t have time to cover every thing…and the winners are:

* Concurrency                  ..................
* Debugging/Profiling          ................
* JRuby                        ......
* Ruby Extras                  ...........
* Distributed Programming      ......................

Distributed Programming

DRb

Marshaling

>> h = {:x => 1}
>> Marshal.dump(h)
=> “\004\b{\006:\006xi\006”
>> Marshal.load(_)
=> {:x=>1}

DRB Server

require 'drb/drb'
require 'ostruct'

DRb.start_service("druby://localhost:4321", OpenStruct.new)
DRb.thread.join

DRb Client

require ‘drb’

DRB.start_service
o = DRbOject.new_with_url("druby:''localhost:4321")
o.last_accessed = Time.now
o.some_other_arbitrary_method = "Set this on the open struct"

By default Pass-by-value, but can be Pass-by-reference can be enabled by including DRbUndumped.

  • Rinda
  • Ring

That’s all Folk! …my hands/brain where running tired during the last hour :-)

That was an incredible 3 days thanks to Chad and Dave. So if you want to dive deeper in Ruby, the Advanced Ruby is the best way to get there!

Enjoy!
Daniel


Tue, 10 Mar 2009 23:31:49 GMT

Starting an intense Ruby week.

It starts with three days at the Advanced Ruby training followed by two days at the Mountain West Ruby Conference. On Tuesday evening, I'll be giving a talk at the Rocky Mountain Adobe Users Group. I'll be blogging about these events here...so stay tuned.

Tue, 10 Mar 2009 07:40:00 GMT

Advanced Ruby - Day 2

I just missed the first half hour of the training due to a long commute due to a little snow in Denver. Chad completed the design discussion on Inheritance .vs. Composition, using mixins and modules.
 
1.class.ancestors
=> [Fixnum, Integer, Numeric, Comparable, Object, Kernel, BasicObject]

1.class.instance_methods(false)
=> [:to_s, :-@, :+, :-, :*, :/, :div, :%, :modulo, :divmod, :fdiv, :**, :abs, :magnitude, :==, :<=>, :>, :>=, :<, :<=, :~, :&, :|, :^, :[], :<<, :>>, :to_f, :size, :zero?, :odd?, :even?, :succ]

m = 1.method(:inspect)
=> #<Method: Fixnum(Kernel)#inspect>
We are moving on to performance.

...make it fast.

Rails doesn't scale and Ruby is slow. This said Ruby is arguably the slowest of the scripting languages with a naive implementation. But for 99% of the work we do, it's fast enough...Now let's talk about that last 1%. Premature optimization is the root of all evil - Donald Knuth.

Benchmarking

In 1.9
require 'benchmark'
puts Benchmark.measure {(1..1000000).map{|num| ""+num.to_s}}
  0.940000   0.050000   0.990000 (  1.001714)
In 1.8
puts Benchmark.measure {(1..1000000).map{|num| ""+num.to_s}}
  1.800000   0.050000   1.850000 (  1.850319)
Yea, 1.9 is twice as fast. Now to compare approaches, here using map or inject...which one is the fastest:
require 'benchmark'
Benchmark.bm do |b|
  b.report("map") {(1..1000000).map{|num| ""+num.to_s}}
  b.report("inject") {(1..1000000).inject(""){|accum, num| ""+num.to_s}}
end
      user     system      total        real
map  1.970000   0.070000   2.040000 (  2.077786)
inject  1.910000   0.010000   1.920000 (  1.978541)

Don't Use Ruby

* C (or OCAML?) extensions * Sockets * DL * Don't use Ruby at all DL is "Pure Ruby" way of calling native code form shared libraries.
require 'dl/import'
require 'dl/struct'

memoization

def fib(n)
 @k||={}
 n<=2 ? 1 : (@k[n-1]||=fib(n-1))+(@k[n-2]||=fib(n-2))
end

puts fib(200)
280571172992510140037611932413038677189525

Program exited with code #0 after 0.02 seconds
Now the same code as above without the cluttering
def fib(n)
  if n <= 2 
      1
  else
     fib(n-1) + fib(n-2)
  end
end

alias :pre_memoized_fib :fib

def fib(n)
  @cache ||= {}
  @cache[n] ||= pre_memoized_fib(n)
end

The Ruby Object Model

Now we move onto the essence of an Object in Ruby. * self is the "current object" * self always as a value * two things change self: 1) method calls 2) class or module definition
class << str   # << opens up the singleton class. Arrows seem to go wrong way.
  p self  # ghost class: <Class:#<String:0x1d0ec>> - class of the class String
  def speak
    puts "miaow"
  end
end

puts str.speak

class Dave
  class << self   # puts the methods into the singleton class and becomes class methods
    def do_something      
    end
  end
end

class Person < Struct.new(:name, :age)
  def greet
      puts "Hello #{self.name}"
  end
end

f = Person.new("Chad", 28)
module Logger
  def log(msg)
    puts msg
  end
end

class Album
  include Logger
end


Album.ancestors # => [Album, Logger, Object, Kernel]
# Note that Logger becomes ancestor of Album...It's insert a generated class named after the module that shares the method table.
Module can extend an object:
module Speak
  def hello
     puts "hello"
  end
end

str = "cat"
str.extend Speak

puts str.hello

Metaprogramming

After the break we will be diving into metaprogramming. I saw his talk at the Advanced Rails Studio a while back and took some notes then. I will therefore sit back, relax, and code along his examples.

Library Organization