You are on page 1of 42

The Ruby Idiom

Ben Hughes
@rubiety
http://benhugh.es

Friday, April 22, 2011


Friday, April 22, 2011
“Ruby is
designed to make
programmers happy”
- Matz

Friday, April 22, 2011


Aesthetic Elegance
Very Idiomatic
Loose Syntax
Extremely Dynamic
Expressive

Friday, April 22, 2011


Blocks

Friday, April 22, 2011


people.each do |person|
puts person.name
end

1.upto(10) do |i|
puts "Counting #{i}"
end

5.times { puts "Hello" }

Friday, April 22, 2011


open "people.txt" do |file|
file.each_line do |line|
puts line.split(",").first
end
end

Friday, April 22, 2011


users.select {|u| u.age >= 21}.map(&:name).sort

Friday, April 22, 2011


class Person
end

Person.class # => Class

nil.class # => NilClass


true.class # => TrueClass

Friday, April 22, 2011


Open Classes

Friday, April 22, 2011


class String
def blank?
self == ""
end
end

Friday, April 22, 2011


class Numeric
def seconds
self
end

def minutes
self * 60
end 12.hours.from_now

def hours
self * 3600 2.minutes + 30.seconds
end

def from_now
Time.now + self
end
end
Friday, April 22, 2011
# Yes, Be Evil:
class Numeric
def +(another)
self - another
end
end

4 + 2 # => 2
Friday, April 22, 2011
Executable Declarations

zsh$
Friday, April 22, 2011
class Person
def name
@name
end

if Superpowers.enabled?
def give_superpowers
@ability = "Fly"
end
end
end
Friday, April 22, 2011
class Model
def self.acts_as_tree
define_method :parent do
find(parent_id)
end

define_method :children do
where(:parent_id => self.id)
end
end
end

class Category < Model


acts_as_tree @category.parent
end @category.children

Friday, April 22, 2011


Module Mix-ins

Friday, April 22, 2011


module Jazz
class Chord
end

class Scale
end
end

Jazz::Chord.new
Jazz::Scale.new
Friday, April 22, 2011
module FilePersistence
def load_from(path)
end
end

class MusicCollection
include Enumerable
include FilePersistence
end

@collection = FileCollection.new
@collection.load_from "songs"
@collection.each do |song|
song.play
end
Friday, April 22, 2011
Isn’t too much freedom a
bad thing?

Friday, April 22, 2011


In Theory? Yes.

In Practice?
It’s not as bad as you
would think...

Friday, April 22, 2011


Greater Good vs. Greater Evil

Solution
Space (Good)

Evil

Friday, April 22, 2011


Greater Good vs. Greater Evil

Solution Space (Good)

Pitfalls
(Evil)

Friday, April 22, 2011


Overlapping Safety

Safety/
Confidence
from Static
Typing

Friday, April 22, 2011


Overlapping Safety

SafetySafety/Confidence
from from
Static Typing Test Suite

Friday, April 22, 2011


Domain-Specific Languages

• Sub-Languages of Ruby for particular purposes


• High-Level Abstractions
• Captures Knowledge in an Extremely Readable Way

Friday, April 22, 2011


Markaby::Builder.new.html do
head { title "Boats.com" }
body do
h1 "Boats.com has great deals"
ul.specials do
li "$49 for a canoe"
li "$39 for a raft"
li "$29 for a huge boat"
end
end
end

Friday, April 22, 2011


<html>
<head><title>Boats.com</title></head>
<body>
<h1>Boats.com has great deals</h1>
<ul class="specials">
<li>$49 for a canoe</li>
<li>$39 for a raft</li>
<li>$29 for a huge boat</li>
</ul>
</body>
</html>

Friday, April 22, 2011


class Payment
state_machine :state, :initial => :new do
event :authorize do
transition :new => :authorized
end

event :capture do
transition :authorized => :captured
end

before_transition any => :authorize, :do => :authorize_card


before_transition any => :capture, :do => :capture_card
end
end

@payment = Payment.new
@payment.state # => "new"
@payment.authorize!
@payment.capture!

@payment.captured? # => true


Friday, April 22, 2011
class Article < ActiveRecord::Base
has_many :comments

scope :published, where(published: true)

validates :title, :presence => true


validates :content, :length => { minimum: 50 }
end

class Comment < ActiveRecord::Base


belongs_to :article

validates :name, :email, :comment, :presence => true

def approve!
update_attribute :approved, true
end
end

Friday, April 22, 2011


class User < ActiveRecord::Base
has_attached_file :avatar, styles: {
medium: "300x300>",
thumb: "100x100>"
}
end

<% form_for(@user) do |f| %>


<%= f.file_field :avatar %>
<% end %>

@user.avatar.url(:medium)

Friday, April 22, 2011


Chord['Ebmaj7'].notes
Chord['maj7'].in_key_of('Eb').notes
# => ['Eb', 'G', 'Bb', 'D']

Scale['Whole Tone'].notes
# => ['C', 'D', 'E', 'F#', 'G#', 'Bb']

Scale['Major'].in_key_of('Eb').modes['Dorian'].notes
# => ['F', 'G', 'Ab', 'Bb', 'C', 'D', 'Eb']

Scale['Major']['Dorian'].chords.symbols
# => ['min7', 'min6']

Chord['Amin7'].modes.names
# => ['A Dorian']

Friday, April 22, 2011


every 3.hours do
command "/usr/bin/my_great_command"
end

every 1.day, :at => ['4:30 am', '10:30 am'] do


runner "MyModel.task_to_run"
end

every :hour do
runner "SomeModel.ladeeda"
end

every :sunday, :at => '12pm' do


runner "Task.do_something_great"
end

Friday, April 22, 2011


Person.joins { articles.comments }.where {{
articles.comments => (
id.in([1,2,3]) | body.matches('First post!%')
)
}}.to_sql

=> SELECT "people".* FROM "people"


INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
INNER JOIN "comments" ON
"comments"."article_id" = "articles"."id"
WHERE (("comments"."id" IN (1, 2, 3)
OR "comments"."body" LIKE 'First post!%'))

Friday, April 22, 2011


C mmunity

Friday, April 22, 2011


Cohesive & Active
Common Style/Idiom
Focuses on Quality
Passionate About Tools
Testing Your Software

Friday, April 22, 2011


Test Your
Damn Software

Friday, April 22, 2011


describe User do
before do
@user = User.create(:login => "joe", :password => "pw")
end

it "should be invalid without username" do


@user.username = ""
@user.should_not be_valid
@user.should have(1).error_on(:username)
end

it "should destroy" do
expect { @user.destroy }.to change { User.count }.by(-1)
end
end

Friday, April 22, 2011


describe Key do
it "should default to C" do
Key.default.name.should == "C"
end

it "should expose 12 primary keys" do


Key.should have(12).primaries
end

it "should treat Eb and D# as enharmonic" do


Key['Eb'].should be_enharmonic_with(Key['D#'])
end
end

Friday, April 22, 2011


It’s a great time to learn Ruby
• Rails 3 recently released - very solid!
• Ruby 1.9 - Runs on a proper VM and very fast
• Bundler / RVM for Ruby and Gem dependencies
• Other Rubies maturing:
JRuby, MacRuby, Rubinius
• Deployment easy with mod_rails or Heroku
• Strong community with resources/help
Friday, April 22, 2011
“Ruby fits my brain
like a glove”
- David Heinemeier Hansson

“Power with clarity


and choice”
- Glenn Vanderburg
Friday, April 22, 2011
Resources
• http://tryruby.org
• http://rubykoans.com
• http://sdruby.org

Ben Hughes
@rubiety
http://benhugh.es
Friday, April 22, 2011