HIDDEN TREASURES
       of
      RUBY


  @MrJaba - iprug - 6th Dec 2011
Whistlestop tour through the lesser
known/obscure features of Ruby
Ruby has a
   HUGE
standard library
Have you heard of?
       Struct

       OpenStruct

       OptionParser

       Abbrev

       Benchmark

       Find

       English
Did you know about?
       String#squeeze

       String#count

       String#tr

       Kernel#Array

       Kernel#trace_var
This is just for FUN
Core Ruby
STRING
                      #squeeze


 “Uh oh the cat sat on the keeeeeeeeeee”.squeeze
=>
“Uh oh the cat sat on the ke”

 “oh craaaapppp my aaappp keys are bloody
           broken”.squeeze(“ap”)
=>
 “oh crap my ap keys are bloody broken”
STRING
          #count

“FINISHED FILES ARE THE RE-
SULT OF YEARS OF SCIENTIF-
IC STUDY COMBINED WITH
THE EXPERIENCE OF YEARS.”

 How many F’s are there?
STRING
                           #count


“FINISHED FILES ARE THE RE-
SULT OF YEARS OF SCIENTIF-
IC STUDY COMBINED WITH
THE EXPERIENCE OF YEARS.”.count(“F”)

=>
6
STRING
                      #count


“how many woods would a wood chuck chuck if a
wood chuck could chuck wood?”.count(“a-z”, “^u”)

=>
52
“DYTSMH”
.tr(“DYTSMH”, “STRING”)

   “STRING”
     .tr(“R-T”, “F”)

   “FFFING”
KERNEL
                    #Array

                       yesthat’sacapitalletter


     Array(1..3) + Array(args[:thing])
=
 [1,2,3, “Thing”]
thing.to_a
=
NoMethodError: undefined method `to_a' for
thing:String
KERNEL
                                   #at_exit


     at_exit { p ObjectSpace.count_objects }
=
{:TOTAL=31479, :FREE=4687, :T_OBJECT=1442, :T_CLASS=859, :T_MODULE=32, :T_FLOAT=7,
:T_STRING=18190, :T_REGEXP=168, :T_ARRAY=3657, :T_HASH=134, :T_STRUCT=1, :T_BIGNUM=2,
:T_FILE=6, :T_DATA=1210, :T_MATCH=100, :T_COMPLEX=1, :T_NODE=949, :T_ICLASS=34}



at_exit {
 loop do
   p “unkillable code!”
 end }
KERNEL
                                                         #set_trace_func
class Cheese
 def eat
   p “om nom nom”
 end
end

set_trace_func proc {|event, file, line, id, binding, classname|
  p “#{event}, #{file}, #{line}, #{id}, #{binding}, #{classname}”
}

=
c-return, cheese.rb, 9, set_trace_func, #Binding:0x007fe11b84e488, Kernel
line, cheese.rb, 11, , #Binding:0x007fe11b84e1e0, 
c-call, cheese.rb, 11, new, #Binding:0x007fe11b84dfb0, Class
c-call, cheese.rb, 11, initialize, #Binding:0x007fe11b84dc90, BasicObject
c-return, cheese.rb, 11, initialize, #Binding:0x007fe11b84da38, BasicObject
c-return, cheese.rb, 11, new, #Binding:0x007fe11b84d808, Class
line, cheese.rb, 12, , #Binding:0x007fe11b84d5d8, 
call, cheese.rb, 2, eat, #Binding:0x007fe11b84d3a8, Cheese
line, cheese.rb, 3, eat, #Binding:0x007fe11b84d150, Cheese
c-call, cheese.rb, 3, p, #Binding:0x007fe11b84cef8, Kernel
c-call, cheese.rb, 3, inspect, #Binding:0x007fe11b84ccc8, String
c-return, cheese.rb, 3, inspect, #Binding:0x007fe11b84ca48, String
om nom nom
c-return, cheese.rb, 3, p, #Binding:0x007fe11b84c7f0, Kernel
return, cheese.rb, 4, eat, #Binding:0x007fe11b84c5c0, Cheese
Struct

Point = Struct.new :x, :y do
 def distance(point)
  Math.sqrt((point.x - self.x) ** 2 +
  (point.y - self.y) ** 2)
 end
end
Why?   Struct

Quickly define a class with a few known fields

            Automatic Hash key

Mitigate risk of spelling errors on field names
Ruby
STANDARD
 LIBRARY
113 Packages
OptionParser
                                 require ‘optparse’
options = {}
parser = OptionParser.new

parser.on(-i, --ipswich, description of IP) {|val| options[:ipswich] = val }
parser.on(-r=ARG, --ruby, Mandatory Argument) {|val| options[:ruby] = val }
parser.on(-u=[ARG], --user, Optional Argument) {|val| options[:user] = val }
parser.on(-g=ARG, --group, Integer, Type cast Argument) {|val| options[:group] = val }

unmatched = parser.parse(ARGV)

puts parser.to_s

puts options are #{options.inspect}
puts unmatched are #{unmatched.inspect}
Abbrev
                   require ‘abbrev’

 Abbrev::abbrev(['Whatever'])

{Whateve=Whatever, Whatev=Whateve
Whate=Whatever, What=Whatever,
Wha=Whatever, Wh=Whatever,
W=Whatever, Whatever=Whatever}


        Thereisno“whatevs”inthere!
Benchmark
                          require ‘benchmark’

   puts Benchmark.measure { calculate_meaning_of_life }
   =
   0.42 0.42 0.42 ( 4.2)

                                            ElapsedRealTime
UserCPU              Sum
              SystemCPU
   Benchmark.bmbm do |x|
    x.report(sort!) { array.dup.sort! }
    x.report(sort) { array.dup.sort }
   end
   =
          user   system  total   real
   sort! 12.959000 0.010000 12.969000 ( 13.793000)
   sort 12.007000 0.000000 12.007000 ( 12.791000)
English
                                  require ‘English’
$ERROR_INFO            $!                  $DEFAULT_OUTPUT             $

$ERROR_POSITION             $@             $DEFAULT_INPUT             $

$FS           $;                           $PID             $$

$FIELD_SEPARATOR            $;             $PROCESS_ID            $$

$OFS              $,                       $CHILD_STATUS              $?

$OUTPUT_FIELD_SEPARATOR $,                 $LAST_MATCH_INFO                $~

$RS               $/                       $IGNORECASE            $=

$INPUT_RECORD_SEPARATOR $/                 $ARGV             $*

$ORS              $                       $MATCH                $

$OUTPUT_RECORD_SEPARATOR $                $PREMATCH              $`

$INPUT_LINE_NUMBER           $.            $POSTMATCH             $'

$NR               $.                       $LAST_PAREN_MATCH               $+

$LAST_READ_LINE         $_
Find
               require ‘find’

Find.find(“/Users/ET”) do |path|
 puts path
 Find.prune if path =~ /hell/
end
=                                Geddit?
/Users/ET/phone
/Users/ET/home
Profiler__
                                require ‘profiler’

Profiler__::start_profile
complicated_method_call
Profiler__::stop_profile
Profiler__::print_profile($stdout)



 % cumulative   self      self   total
time seconds    seconds calls ms/call ms/call name
0.00  0.00      0.00    1   0.00   0.00 Integer#times
0.00  0.00      0.00    1   0.00   0.00 Object#complicated_method_call
0.00  0.01      0.00    1   0.00 10.00 #toplevel
RSS
                       require ‘rss/2.0’



response = open(http://feeds.feedburner.com/MrjabasAdventures).read
rss = RSS::Parser.parse(response, false)
rss.items.each do |item|
 p item.title
end
MiniTest
          require ‘minitest/autorun’
        describe Cheese do
         before do
          @cheddar = Cheese.new(“cheddar”)
         end

         describe when enquiring about smelliness do
          it must respond with a stink factor do
            @cheddar.smelliness?.must_equal 0.9
          end
         end
        end




                Provides:
Specs Mocking Stubbing Runners Benchmarks
Thank you to
everyone involved in
       Ruby!

Hidden treasures of Ruby

  • 1.
    HIDDEN TREASURES of RUBY @MrJaba - iprug - 6th Dec 2011
  • 2.
    Whistlestop tour throughthe lesser known/obscure features of Ruby
  • 3.
    Ruby has a HUGE standard library
  • 4.
    Have you heardof? Struct OpenStruct OptionParser Abbrev Benchmark Find English
  • 5.
    Did you knowabout? String#squeeze String#count String#tr Kernel#Array Kernel#trace_var
  • 6.
    This is justfor FUN
  • 7.
  • 8.
    STRING #squeeze “Uh oh the cat sat on the keeeeeeeeeee”.squeeze => “Uh oh the cat sat on the ke” “oh craaaapppp my aaappp keys are bloody broken”.squeeze(“ap”) => “oh crap my ap keys are bloody broken”
  • 9.
    STRING #count “FINISHED FILES ARE THE RE- SULT OF YEARS OF SCIENTIF- IC STUDY COMBINED WITH THE EXPERIENCE OF YEARS.” How many F’s are there?
  • 10.
    STRING #count “FINISHED FILES ARE THE RE- SULT OF YEARS OF SCIENTIF- IC STUDY COMBINED WITH THE EXPERIENCE OF YEARS.”.count(“F”) => 6
  • 11.
    STRING #count “how many woods would a wood chuck chuck if a wood chuck could chuck wood?”.count(“a-z”, “^u”) => 52
  • 12.
    “DYTSMH” .tr(“DYTSMH”, “STRING”) “STRING” .tr(“R-T”, “F”) “FFFING”
  • 13.
    KERNEL #Array yesthat’sacapitalletter Array(1..3) + Array(args[:thing]) = [1,2,3, “Thing”] thing.to_a = NoMethodError: undefined method `to_a' for thing:String
  • 14.
    KERNEL #at_exit at_exit { p ObjectSpace.count_objects } = {:TOTAL=31479, :FREE=4687, :T_OBJECT=1442, :T_CLASS=859, :T_MODULE=32, :T_FLOAT=7, :T_STRING=18190, :T_REGEXP=168, :T_ARRAY=3657, :T_HASH=134, :T_STRUCT=1, :T_BIGNUM=2, :T_FILE=6, :T_DATA=1210, :T_MATCH=100, :T_COMPLEX=1, :T_NODE=949, :T_ICLASS=34} at_exit { loop do p “unkillable code!” end }
  • 15.
    KERNEL #set_trace_func class Cheese def eat p “om nom nom” end end set_trace_func proc {|event, file, line, id, binding, classname| p “#{event}, #{file}, #{line}, #{id}, #{binding}, #{classname}” } = c-return, cheese.rb, 9, set_trace_func, #Binding:0x007fe11b84e488, Kernel line, cheese.rb, 11, , #Binding:0x007fe11b84e1e0, c-call, cheese.rb, 11, new, #Binding:0x007fe11b84dfb0, Class c-call, cheese.rb, 11, initialize, #Binding:0x007fe11b84dc90, BasicObject c-return, cheese.rb, 11, initialize, #Binding:0x007fe11b84da38, BasicObject c-return, cheese.rb, 11, new, #Binding:0x007fe11b84d808, Class line, cheese.rb, 12, , #Binding:0x007fe11b84d5d8, call, cheese.rb, 2, eat, #Binding:0x007fe11b84d3a8, Cheese line, cheese.rb, 3, eat, #Binding:0x007fe11b84d150, Cheese c-call, cheese.rb, 3, p, #Binding:0x007fe11b84cef8, Kernel c-call, cheese.rb, 3, inspect, #Binding:0x007fe11b84ccc8, String c-return, cheese.rb, 3, inspect, #Binding:0x007fe11b84ca48, String om nom nom c-return, cheese.rb, 3, p, #Binding:0x007fe11b84c7f0, Kernel return, cheese.rb, 4, eat, #Binding:0x007fe11b84c5c0, Cheese
  • 16.
    Struct Point = Struct.new:x, :y do def distance(point) Math.sqrt((point.x - self.x) ** 2 + (point.y - self.y) ** 2) end end
  • 17.
    Why? Struct Quickly define a class with a few known fields Automatic Hash key Mitigate risk of spelling errors on field names
  • 18.
  • 19.
  • 20.
    OptionParser require ‘optparse’ options = {} parser = OptionParser.new parser.on(-i, --ipswich, description of IP) {|val| options[:ipswich] = val } parser.on(-r=ARG, --ruby, Mandatory Argument) {|val| options[:ruby] = val } parser.on(-u=[ARG], --user, Optional Argument) {|val| options[:user] = val } parser.on(-g=ARG, --group, Integer, Type cast Argument) {|val| options[:group] = val } unmatched = parser.parse(ARGV) puts parser.to_s puts options are #{options.inspect} puts unmatched are #{unmatched.inspect}
  • 21.
    Abbrev require ‘abbrev’ Abbrev::abbrev(['Whatever']) {Whateve=Whatever, Whatev=Whateve Whate=Whatever, What=Whatever, Wha=Whatever, Wh=Whatever, W=Whatever, Whatever=Whatever} Thereisno“whatevs”inthere!
  • 22.
    Benchmark require ‘benchmark’ puts Benchmark.measure { calculate_meaning_of_life } = 0.42 0.42 0.42 ( 4.2) ElapsedRealTime UserCPU Sum SystemCPU Benchmark.bmbm do |x| x.report(sort!) { array.dup.sort! } x.report(sort) { array.dup.sort } end = user system total real sort! 12.959000 0.010000 12.969000 ( 13.793000) sort 12.007000 0.000000 12.007000 ( 12.791000)
  • 23.
    English require ‘English’ $ERROR_INFO $! $DEFAULT_OUTPUT $ $ERROR_POSITION $@ $DEFAULT_INPUT $ $FS $; $PID $$ $FIELD_SEPARATOR $; $PROCESS_ID $$ $OFS $, $CHILD_STATUS $? $OUTPUT_FIELD_SEPARATOR $, $LAST_MATCH_INFO $~ $RS $/ $IGNORECASE $= $INPUT_RECORD_SEPARATOR $/ $ARGV $* $ORS $ $MATCH $ $OUTPUT_RECORD_SEPARATOR $ $PREMATCH $` $INPUT_LINE_NUMBER $. $POSTMATCH $' $NR $. $LAST_PAREN_MATCH $+ $LAST_READ_LINE $_
  • 24.
    Find require ‘find’ Find.find(“/Users/ET”) do |path| puts path Find.prune if path =~ /hell/ end = Geddit? /Users/ET/phone /Users/ET/home
  • 25.
    Profiler__ require ‘profiler’ Profiler__::start_profile complicated_method_call Profiler__::stop_profile Profiler__::print_profile($stdout) % cumulative self self total time seconds seconds calls ms/call ms/call name 0.00 0.00 0.00 1 0.00 0.00 Integer#times 0.00 0.00 0.00 1 0.00 0.00 Object#complicated_method_call 0.00 0.01 0.00 1 0.00 10.00 #toplevel
  • 26.
    RSS require ‘rss/2.0’ response = open(http://feeds.feedburner.com/MrjabasAdventures).read rss = RSS::Parser.parse(response, false) rss.items.each do |item| p item.title end
  • 27.
    MiniTest require ‘minitest/autorun’ describe Cheese do before do @cheddar = Cheese.new(“cheddar”) end describe when enquiring about smelliness do it must respond with a stink factor do @cheddar.smelliness?.must_equal 0.9 end end end Provides: Specs Mocking Stubbing Runners Benchmarks
  • 28.
    Thank you to everyoneinvolved in Ruby!