The Nuclear Squid Musings on stuff and other things.

EuRuKo 2010, Day 2

For comments, additional notes, corrections, etc. contact @cypher.

Mislav Marohnić - Getting and loading code: current state of packaging & best practices

Loading code is simple

require loads stuff from the load path

once the file is located, it is loaded and executed

then gets added to loaded file to prevent it from being loaded twice

Rubygems hijacks require, and changes its behavior to support loading different versions of gems

Many gems use weird and unnecessary load/require practices

“‘require rubygems’ is a code smell… no it’s always just wrong” - @rtomayko

Going manual:

  • package your code in a .zip
  • email it/upload to a server
  • people download & extract code
  • add lib dir to $LOAD_PATH
  • they require your file and run their code

How to $LOAD_PATH

ruby -I “path/to/lib” myapp.rb

Initial $LOAD_PATH

Rubygems does the same thing as manual, just automated

Anatomy of a gem:

  • metadata
  • data

Alternatives:

  • Geminstaller
  • Bundler, rvm
  • rip
  • rpg
  • Coral

rip & rpg are the interesting ones

Allow you to install gems without Rubygems

rpg designed to be fast

works completely without Rubygems

Coral can’t do gems, installs everything from GitHub

Loading libs:

$ CORAL=hub@v1.2.0 irb -I~/Projects/Coral/lib -r coral

best practices:

  • don’t require 'rubygems'
  • library code in “lib”, executable code in “bin” (more: “Ruby Packaging Standard” spec)
  • have a gemspec
  • follow SemVer versioning policy

development mode:

  • ruby irb with irb -I lib
  • run executables with RUBYLIB=lib bin/stuff
  • run tests with ruby -I lib:test test/stuff/feature_test.rb

never get stuck

remember: it’s just code

Florian Gilcher - Character encoding in Ruby 1.9

Slides

The Tower of Babel Compatibility Kit (TBCK)

On Encoding:

  • Americans: I don’t want to know
  • Japanese: How can you not know?!
  • Europeans: Unicode solves everything

Unicode/UTF-8 solves the problem for the western world

Ruby 1.9 solves this problem by (potentially) support all encodings

String is the biggest change in 1.9

  • not Enumerable anymore
  • list of characters, not bytes
  • has attached Encoding
  • Strings in multiple encodings can exist in same environment

String provides a way to convert between encodings using #encode and #encode!

Fails if the conversion is not possible

Strings of different encodings can be concatenated just fine if their encoding is compatible

Regular Expressions haves encodings as well, but can’t change it

IO Objects have two special encodings:

  • external_encoding is the encoding of the input or output stream
  • internal_encoding is the encoding you want to use internally

String literals have the encoding of the source file they are in

Ruby assumes US-ASCII unless otherwise specified

#{- encoding=utf-8 -}
puts "Hello Wörld"

Enoding of IO Streams can be set using the mode string

File.open("test.txt", "r:US-ASCII") do |f|
  # …
end

Internal and external Encoding can be set to defaults using Encoding.internal_encoding and Encoding.external_encoding

Also possible via cmd line switch: -Eex[:in]

What if you need to use String as a byte string?

Encoding.find('binary')

Two cases where you want to use binary:

  • IO stream encoding is not known beforehand and must be determined
  • reading input bytewise

String#force_encoding

If you are absolutely sure that the string has a diff encoding than it is flagged with, you can change it without conversion

think twice before doing this!

leads to hard to track down bugs

The three steps guide to complex IO in Ruby 1.9

  • Read input, determine encoding
  • Force encoding to the encoding the input is provided in
  • Encode it to interal_encoding

encode is also able to do error handling

Usage for Europeans

  • RUBYOPTS='-wKU' gives you best Unicode support for 1.8 and 1.9
  • Check IO libs wether they return sane strings
  • …if not, complain to maintainer

Tips for library developers:

  • Use US-ASCII, offload other stuff to localization files
  • Expect UTF-8 and compatible encodings as input, provide output accordingly
  • IO libs should be albe to read UTF-8, ISO-* and Windows-Encodings
  • Docs are king
  • Consider failing if default_internal doesn’t match your expectations

Pitfalls

  • Just because two strings look the same, but don’t have to be (Unicode diacritic characters (?))
  • Wrong console encoding (esp. Windows systems)
  • Inability to guess source encoding
  • source is already broken (e.g. database or database drivers)

Elise Huard - Evaluating quality of Rails codebase

Important when doing e.g. acquisitions

Maintenance for Freelancers

Where to start?

Try the app, see if it is buggy or slow

Rails version should be relatively recent

Check if plugins that are still alive (when was last commit, watchers on GitHub, etc.)

Run tests

Start with routes.rb

Routes are the first entry point into the app

Use railroad to get Models + their relationships as diagram

“Only two hard things in computer science: Cache invalidation and naming things” - Phil Karlton

names might not make sense to you in the beginning, but they should make sense to someone in the problem domain

Metrics: Know thine tools

When you get numbers, you should question them, e.g. where do they come from

LOC are not very expressive or useful

Use RubyParser and ParseTree to generate metrics, e.g. based on Symbolic Expressions (Sexps)

Flog: “The pain your code is in”

measures code complexity

Metrics:

  • Very good methods < 20
  • All right: < 50

Flay: Detect similar code

Saikuro: Cyclomatic Complexity

Doesn’t use Ruby Parser, uses Ruby-Lex

Every keyword is interpreted into a state, which is then used to compute metrics

Good: Methods < 5

Roodi: Ruby Object Oriented Design Inferometer

Extensible

Reek: More OO-specific checks

rails_best_practices

Churn: Tells you which files have been changed most often

RCov: Executes tests, tracks the executed lines, reports test coverage

Good: 100% coverage

But 100% coverage doesn’t mean you actually have tests covering the code

Heckle: Mutates code, sees if tests fail

metric_fu: runs all/most of these tools for you, presents nice overview

Check out the good stuff

What metrics don’t tell you:

  • Performance
  • Wether it is readable

Matz - Keynote with Q&A about Ruby

“Meet the Rubyists”

This time, his suitcase was on time, but he missed his flight

Ruby Confs:

  • EuRuKo in Europe
  • RubyConf in US
  • RubyKaigi in Japan

Other regional confs

Ruby Community is growing internationally

1993: 1 user
1995: 100 users
2000: 10.000 (Pickaxe released)
2005: 100.000 (Rails released)

Rails not first web framework, but much simpler & faster dev than before

2008: 1.000.000 (Gartner estimate)
2010: ?
2013: 4.000.000 (Gartner projection)

Community is growing quickly, lots of new people coming in

MINSWAN is greatest asset

Ruby community is known as being nice

Ruby may not be fastest, simplest or easiest, but we are nice

Something to be proud of

We have to keep the community nice

enlighten newcomers

What is nice?

def nice
  brave &&
  passionate &&
  honest &&
  respective
end

Brave:

  • New technology is a risk
  • Conservative people hate new tech
  • But we love new tech
  • We are brave

“From Java to Ruby” - book about adoption of a new technology

We are passionate

Hackers need to be passionate about tech (The Passionate Programmer)

We love Ruby

People who love Ruby are called Rubyists

Why do we love Ruby?

  • We are hackers
  • Hackers love freedom
  • Hackers love power
  • Ruby gives them

We are honest, fair, don’t tell lies, don’t distort reality

We respect others

“Although Ruby is my favorite language, I love all languages on the earth” (even PHP)

Other languages:

  • envy them sometimes (features, libraries)
  • learn from them
  • steal ideas from them

Perl 6 has some stuff from Ruby

We respect other tools, languages, tech

We have great community

Most important factor

Lots of other OSS cannot have their community

we are very lucky

Once you have great community, most other problems become less important

We just need to survive

Many OSS projects don’t survive long, get abandoned

OSS community is like a shark, have to keep moving to survive

If we keep moving forward, other problems will vanish

Ridiculous to choose language based on micro benchmark, but that’s life

Ruby 1.9 is much faster, we can be even faster (JIT, optimization)

JRuby, Rubinius showing great promise

Ruby might be bad at threading (GIL, no multi-core boost)

We keep moving forward: MVM (Multiple VMs in a process), UNIX processes, better distributed frameworks, or event-driven frameworks

Ruby might not scale (memory consumption, slow interpreter, monkey patching)

We keep moving forward: Better GC, less memory consumption, better performance, scoping monkey patching (Ruby 2.0 issue)

Ruby might have other problems - but we keep moving forward

We don’t have to worry, matz promises to move forward

Move forward together

Places to work on:

  • Debug
  • VM
  • Libraries
  • Frameworks
  • Applications/Tools
  • Documentation

We have very limited resources, esp. in ruby-core

Please work together

Q/A session

Q: Elaborate on Monkey Patching in Ruby 2.0
A: Replacing e.g. basic operators has huge side effects, so restrict monkey patches to a restrictive scope/namespace so they don’t affect other code. Also add method combination/hook to make alias_method_chain obsolete

Q: Ruby 2.0 - when?
A: Still Vaporware, no promises about release date

Q: alias_method_chain - what about method signatures?
A: Ruby 2.0 will support keyword args, should mitigate problem

Q: Would you add static typing to ruby if you could start over?
A: Really hate to type data types. Haskell does great stuff, but don’t want to do that

Q: Other languages you encourage people to learn/look at?
A: Languages that use other paradigms, so learn functional lang like Haskell, Clojure, Erlang. Prolog is also very different and interesting to learn.

Q: Alternative implementation that you like the most or see most potential
A: Rubinius has greatest potential, since it’s mostly written in Ruby itself, inviting experimentation and easy rewriting. Mixed feeling about other implementations. MacRuby is great, has LLVM as backend, C Ruby have similar plan for backend, but MacRuby is basically a fork that does dev faster. But diversity is a good thing, moves things forward.

Q: What new features would you like to borrow from other languages for 2.0?
A: Monkey Patching stuff inspired by CLOS. Many ideas to steal. Have to design in a compatible way with existing Ruby system. Pattern matching, actors, STM, would be possible.

Q: alias_method_chain - when you include stuff in a class, new methods are put in between superclass and the actual class. Extend doesn’t work that way, so can’t use super to call original method. Solution for 2.0?
A: Have module stuff before stuff in the class, have something like prepend

Scott Chacon - Gittin’ down to the plumbing

(Note: This talk is the same he gave at Scottish Ruby Conference 2010)

What Git is at the lowest possible level

Two levels of commands - plumbing and porcelain

porcelain is the stuff users see

plumbing is the lower-level stuff

Plumbing is not necessarily SCM-related

What is Git really?

Simple key/value content storage system

Directory snapshot storage system

History of directory snapshots system

put is hash-object

get is cat-file

(lots of low-level git commands here, watch the video)

Git storage is completely different from every other SCM, which all use file-based delta storage

Git is a synchable database of directory snapshots

Fits more scenarios other than source control

Example: Content Distribution System

Better & more efficient than rsync

Tomasz Stachewicz - Putting the static back into Ruby

‘static’ can mean:

  • static code analysis
  • static typing

focus on static code analysis

We do static code analysis when reading code

But computers are faster at it

Also great for answering “What should I refactor?”

use ParseTree, turns Ruby code into Sexps

Sexps were like the XML of the 70s

Example: Use ParseTree to find & remove unused methods

Problem with flog: simple/naive metrics are easy to cheat

just split stuff into methods

Should start with reek for static code analysis

fun idea: Use these tools on their own code base

Sven Fuchs - Anatomy of Ruby i18n

I18n 0.4 is out

generic key-value backend, so you can use e.g. Redis as backend

I18n is about designing software so it can be adopted to various locales

L10n is the process of translating the software

Scope:

  • Looking up translations
  • Formats of numbers, dates, times, currency
  • Timezones
  • etc.

I18n only cares about first two

  • Interpolation
  • Pluralization
  • Defaults
  • Namespace

Scenarios:

  • Single language
  • Multiple languages
  • Different storage types
  • Model/Data translations
  • Lots of special requirements

Simplest thing that could possibly work

I18n::Simple backend

Usually enough, but sometimes you want more:

  • Cache
  • Fallbacks: Fall back to other translation if chosen locale isn’t available
  • Pluralizations: Simple algorithm in western languages, but e.g. czech has one, few, and many pluralization forms
  • Gettext
  • Metadata

Other backends: Chain, ActiveRecord

Advanced features:

  • Translation procs
  • Interpolation procs
  • Translation symlinks

Prefer composition over inheritance

https://gist.github.com/244944 vs. https://gist.github.com/247648

Marcin Kulik - Building web frameworks with Rack

While the world doesn’t need another web framework, but it’s so easy you should at least try

gain understanding how other web frameworks, rack, HTTP work

Also fun

Existing frameworks all use MVC (more or less)

Let’s build our own

Available Rack middleware:

  • Use bundler for gem dependency management
  • Routing: Usher
  • Controller: Should be a full Rack App, use rack-contrib and rack-flash for extras
  • Tilt for templates
  • DataMapper for ORM
  • Warden for authentication
  • rack-test for testing
  • Console: racksh

CodeRack - Rack Middleware repository

Nicolás Sanguinetti - Continuous Integration and why you need it

CI is a methodology

Integrate frequently, ideally a few times per day

Fix any integration problem ASAP

CI gives instant feedback

CI allows you to deploy anytime with confidence that everything works

Spend less time figuring out what went wrong

Less bugs

Better estimations, since CI means you basically deploy continuously

Just Do It

No software or service required, it’s just a practice

Core of CI is commit often, and merge frequently

But automation makes stuff easier

Even a shellscript will do

But no need to reinvent the wheel

Hudson:

  • Built with Java
  • Easy to set up
  • Lots of Plugins
  • Multiple SCMs supported
  • Multiple Projects
  • History of builds

Works, sometimes takes a lot of config

CI Joe:

  • Simple and tiny
  • Single project
  • Married to Git
  • Easy to hack on
  • Easy to set up
  • No history

Great, tiny, works like a charm, but limited

Integrity:

  • Simple and small
  • Multiple projects
  • Supports Git out of the box, other SCMs soon
  • Easy to hack, set up
  • History of builds

Try all of them

Neil Straford and Jason Goecke - Tropo.com - Voice, IM and SMS enable your application

Slides

Code examples

Moho & Tropo replace Asterisk for Adhearsion

Make it easier to scale

Moho: Asynchronous, Multi-Channel, common concepts baked in

Tropo: Cloud Service & Open Source, unified communications API

Simple (only 15 commands)

Synchronous

Speech Recognition & Synthesis

Transcription

Single API for SMS, Twitter, etc.

Tropo Scripting

Each supported language gets a “Shim”

Demo

Play Simon Game: Skype +99000936 9991442790 (Speak in english or enter touch tones)

Lightning Talks

iKey Kung Fu

One Keyboard to rule them all

Each app has its own key combination

No more alt-tab

Instant switch between applications

Single Application mode - all other app windows are hidden

Only limit is number of fingers

MacRuby

RubyCocoa is a bridge between Ruby and Objective-C

Messaging is slow, because it’s a bridge

Two object spaces

Green threads vs. native threads

MacRuby: Object => NSObject

Uses LLVM to JIT and AOT

One runtime, object space, shared infrastructure, real threads

Access to Grand Central Dispatch

BareTest

https://github.com/apeiros/baretest

ViewModel

Thin wrapper above models

Meant to replace helper methods which are just there for specific model instances

- song = view_model_for @song
%h1= song.title

Responders are a new feature from Rails 3

Loader

Dynamically reload data without restarting server

Code

Rewriting IRB

IRB is probably oldest ruby program in use

Fragile, hard to change, unmaintainable

DietRB is complete rewrite

Use Ripper to parse Ruby code instead of self-rolled Lexer + Parser

Has completion, history and colorization extensions

Spec descriptions

Already in MacRuby

Needs more eyes to scrutinize

$ gem install dietrb

DietRB on GitHub Slides

Agile Project Management with Cucumber FM

(Exactly What It Says On The Tin)

Rails 3 documentation for Mac OS X Dictionary Services

Access Rails 3 docs through Dictionary.app

Simply type keyword

Also works in Spotlight

Also available for Rails 2, Ruby 1.8, jQuery, etc.

Git dictionary

jQuery dictionary

Rails, Ruby, YUI, etc.

Rod, Polish Rails Guides

Rod: Read only data(base)

  • Opposite of RDBMS - denormalize data
  • Opposite of document database
  • written in C
  • with Ruby interface, mimicking AR
  • why? natural language dictionaries

Polish Rails Guides (GitHub)

NoSQL Summer

Worldwide project around NoSQL

Hub

$ brew install hub
$ alias git=hub

Wrapper for Git for easier interaction with GitHub

Open Network graph:

$ git browse -- network

Fetch stuff from forks

$ git fetch mislav,cehoffman

Add a feature

$ git merge mislav/some-feature

Cherry picka URL pasted from browser

$ git cherry-pick https://github.com/defunkt/hub/commit/3a8d7a

Fork:

$ git fork

Copy compare URL to clipboard:

$ git compare -u | pbcopy

DataMapper 1.0.0.rc3

More than an ORM

~210 contributors

~40 (No)SQL adapters and ~120 plugins

Supports many Ruby platforms

One of Zombies

Simple 2D game

Based on Gosu

Strategy game -> kill everything game

Save the innocent -> no end

One Of Zombies

Template Induction

Useful for screen scraping

Creating templates (e.g. SOAP load generators)

Port from Python version: Templatemaker

Caveat: Really slow

Doesn’t actually work

RTemplatemaker

Get to the point already

Don’t split methods on the same level of abstraction

ey-integrity

Deploy CI server to Engine Yard cloud

ey-integrity

Long polling with Event Machine

(not held due to time constraints)

Slides