Slide 1

Slide 1 text

Chris Arcand
 chrisarcand chrisarcand www.chrisarcand.com A Comprehensive Degree of Ruby 2.3

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Let’s talk Ruby!

Slide 5

Slide 5 text

Ruby 0.95 (first public release!) - December 21st, 1995 Ruby 2.3.0 (latest release) - December 25th, 2015 Ruby is 20 years old!

Slide 6

Slide 6 text

The I-clicked-the-link-on-Hacker-News-or-Twitter summary: •“#dig!” •“Frozen string literalz! I can haz performance?”* •“Hash comparisons!” •“OMGOMGOMG THE SAFE NAVIGATION OPERATOR!!!” •“The did_you_mean gem!” •“OMG did you see there’s a safe navigation operator?” * Careful, here

Slide 7

Slide 7 text

Today: • Everything from the previous slide, in detail • Some methods: • Array#bsearch_index • Enumerable#grep_v • Hash#fetch_values • Hash#to_proc • Module#deprecate_constant • Numeric#positive? && #negative • and more… • New Squiggly Heredoc syntax • A few performance improvements (ie CGI#escapeHTML) • A few removals (Bye bye, Rake!; $SAFE removals)

Slide 8

Slide 8 text

Lots to cover! View the full changelog at https://github.com/ruby/ruby/blob/v2_3_0/ChangeLog Since Ruby 2.2.0: 2946 files changed 104057 insertions(+) 59478 deletions(-)

Slide 9

Slide 9 text

✨ Removals ✨

Slide 10

Slide 10 text

So long, Rake! (sorta) [Feature #11025] Rake is removed from the standard library (kind of) Part of a larger effort to gemify all the things:
 https://bugs.ruby-lang.org/issues/5481

Slide 11

Slide 11 text

Be $SAFE! [Feature #5455] $SAFE=2 and $SAFE=3 are obsolete. If $SAFE is set to >=2, an ArgumentError is raised.

Slide 12

Slide 12 text

–Some person sitting in this room right now 
 “Uhhh…cool story bro…”

Slide 13

Slide 13 text

“WTH is $SAFE?” All external data is dangerous. Don't let it close to interfaces that can modify your system.

Slide 14

Slide 14 text

“WTH is $SAFE?” The variable $SAFE determines Ruby's level of paranoia

Slide 15

Slide 15 text

“WTH is $SAFE?” The variable $SAFE determines Ruby's level of paranoia

Slide 16

Slide 16 text

Language changes ✨ ✨

Slide 17

Slide 17 text

ArgumentError: wrong number of arguments (2 for 1)

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

Improved ArgumentError message [Feature #9025] >> some_method("foo", "bar") ArgumentError: wrong number of arguments (2 for 1)

Slide 20

Slide 20 text

Improved ArgumentError message [Feature #9025] 
 1 for 0? 2 for 3? STAHP! >> some_method("foo", "bar") ArgumentError: wrong number of arguments (2 for 1) >> some_method("foo", "bar") ArgumentError: wrong number of arguments (given 2, expected 1)

Slide 21

Slide 21 text

did_you_mean ? [Feature #11252] The did_you_mean gem by Yuki Nishijima is included in Ruby 2.3’s bundled_gems

Slide 22

Slide 22 text

>> methosd # => NameError: undefined local variable or method `methosd' for main:Object # Did you mean? methods # method

Slide 23

Slide 23 text

>> OBject # => NameError: uninitialized constant OBject # Did you mean? Object

Slide 24

Slide 24 text

>> full_name = "Yuki Nishijima" >> full_name.starts_with?("Y") # => NoMethodError: undefined method `starts_with?' for "Yuki Nishijima":String # Did you mean? start_with?

Slide 25

Slide 25 text

Heredoc: <<- class FancyHello def self.hello puts <<-README.inspect Hello World! README end end FancyHello.hello # => ???

Slide 26

Slide 26 text

" Hello\n World!\n" Note that the while the closing identifier may be indented, the content is always treated as if it is flush left. If you indent the content those spaces will appear in the output. From syntax documentation:

Slide 27

Slide 27 text

class FancyHello def self.hello puts <<-README.inspect Hello World! README end end FancyHello.hello
 # => "Hello\n World!\n"

Slide 28

Slide 28 text

Rails implements it’s own method to avoid this

Slide 29

Slide 29 text

“Squiggly Heredoc”: <<~ [Feature #9098] As proposed by Avdi Grimm This syntax strips indent from the quoted string:

Slide 30

Slide 30 text

…Ok…fine. The Safe Navigation Operator ✨ ✨ That’s it! See you in Ruby 2.4!

Slide 31

Slide 31 text

Safe Navigation Operator [Feature #11537] “&.” can be used to ‘safely navigate’ a chain of methods even as something in the chain returns ‘nil’

Slide 32

Slide 32 text

• Common in Ruby:
 if user && user.address && user.address.valid? • ActiveSupport implements #try:
 user.try(:address).try(:valid?) • Ruby 2.3’s new operator:
 user&.address&.valid?

Slide 33

Slide 33 text

• Common in Ruby:
 if user && user.address && user.address.valid? • ActiveSupport implements #try:
 user.try(:address).try(:valid?) • Ruby 2.3’s new operator:
 user&.address&.valid? Coalesces ‘false’ Does not coalesce ‘false’
 More like #try! of ActiveSupport Be warned: These aren’t exactly the same thing:

Slide 34

Slide 34 text

Interesting tidbit… From Georgi Mitrev (@gmitrev) nil&.nil? 


Slide 35

Slide 35 text

Interesting tidbit… nil&.nil? # => nil
 From Georgi Mitrev (@gmitrev)

Slide 36

Slide 36 text

Interesting tidbit… nil&.nil? # => nil
 nil?.nil? # => false nil.nil? # => true From Georgi Mitrev (@gmitrev)

Slide 37

Slide 37 text

Frozen String Literal options [Features #11473, #11725] Ruby 2.1: “str”.freeze was optimized
 to reduce object allocation • # frozen_string_literal: true 
 at the top of each file (magic comment or pragma) • --enable-frozen-string-literal
 flag on the command line (ALL string literals by default!)

Slide 38

Slide 38 text

string = “I LOVE this talk!”
 puts string.gsub!(“LOVE, “HATE”) ./thoughts.rb `ruby thoughts.rb` # => “I HATE this talk!”

Slide 39

Slide 39 text

./thoughts.rb `ruby --enable-frozen-string-literal thoughts.rb` thoughts.rb:2:in `gsub!': can't modify frozen String (RuntimeError) from thoughts.rb:2:in `' string = “I LOVE this talk!”
 puts string.gsub!(“LOVE, “HATE”)

Slide 40

Slide 40 text

• Immutability -> Performance! • Immutability -> Thread safetyer • Literal value === Literal value (same object)

Slide 41

Slide 41 text

• Potentially numerous compatibility issues in the RubyGems ecosystem • In the Ruby world, most programs have dozens or hundreds of third party dependencies • Dare we say: Is this Python 3 all over again? • Is it really that much faster? (only literals!) ✋

Slide 42

Slide 42 text

TLDR: Pay attention

Slide 43

Slide 43 text

✨ Core Class Changes ✨

Slide 44

Slide 44 text

This is annoying: params[:order] && params[:order][:shipping_info] && params[:order][:shipping_info][:country]

Slide 45

Slide 45 text

params[:order][:shipping_info][:country] rescue nil This is slow and stupid:

Slide 46

Slide 46 text

params.fetch(:order, {}) .fetch(:shipping_info, {}) .fetch(:country, nil) This is mega annoying:

Slide 47

Slide 47 text

#dig [Feature #11643, 11688]

Slide 48

Slide 48 text

#dig [Feature #11643, 11688] Array, Hash, and Struct all have a #dig method

Slide 49

Slide 49 text

{ a: 1, b: 2 }.include?({ a: 1 })

Slide 50

Slide 50 text

{ a: 1, b: 2 }.include?({ a: 1 }) # => false ☹

Slide 51

Slide 51 text

{ a: 1, b: 2 }.include?(:a) # => true Hash#include? is an alias of #has_key?

Slide 52

Slide 52 text

Hash Comparison Methods [Feature #10984] Hash#<=, Hash#<, Hash#>=, Hash#> A really helpful table from Olivier Lacan (who originally proposed hash comparisons)

Slide 53

Slide 53 text

In RSpec: expect({ a: “billy”, b: “bob” }) .to include({ b: “bob” }) expect({ a: “billy”, b: “bob” } > { b: “bob” }) .to be_truthy { a: “billy”, b: “bob” } > { b: “bob” } # => true

Slide 54

Slide 54 text

✨ Performance ✨

Slide 55

Slide 55 text

• CGI::escapeHTML optimized (aka: Completely rewritten) • Array#select!, Array#keep_if, Array#reject!, and Array#delete_if no longer changes the receiver array instantly every time the block is called. [Feature #10714] Performance is now linear • Misc Ruby virtual machine improvements

Slide 56

Slide 56 text

CGI::escapeHTML optimized ~7x faster worst case ~3x faster best case (heavy replacements) (no replacements)

Slide 57

Slide 57 text

⚠ ERB template rendering in Rails uses this method So…? Among many things, Great benchmark done by Alexander Dymo here:
 http://ruby-performance-book.com/blog/2016/02/is-ruby-2-3-faster-rails-erb-template-rendering-performance.html ~4x speedup for Rails template rendering

Slide 58

Slide 58 text

Experimental Features ✨ ✨ (There’s only one…)

Slide 59

Slide 59 text

RubyVM::InstructionSequence

Slide 60

Slide 60 text

RubyVM::InstructionSequence

Slide 61

Slide 61 text

Ruby 2.3 adds #to_binary, #load_from_binary as an experimental feature:

Slide 62

Slide 62 text

This is experimentation for providing "machine dependent" binary files. • Faster bootstrap time for big applications(?) • Reduced memory consumption(?)

Slide 63

Slide 63 text

Nothing new A simple precompiled file cache: • Python: .pyc and .pyo files • Java: .class files • C/C++: .o files • Ruby: Rubinius uses .rbc files! ¯\_(ϑ)_/¯

Slide 64

Slide 64 text

In brief… • Enumerable#grep_v - inverse version of Enumerable#grep [Feature #11049] • Hash#fetch_values - stricter version of Hash#values_at [Feature #10017] • Module#deprecate_constant - gives deprecations on any constant [Feature #11398] • Numeric#positive? and Numeric#negative? - Like Rails! [Feature #11151] • String#+@ and String#-@ - to make mutable/frozen string literals [Feature #11782] • Array#bsearch_index - complement to Array#bsearch [Feature #10730] • Thread#name, Thread#name= - Thread names! [Feature #11251] • Hash#to_proc - Can use a Hash to iterate over an Enumerable [Feature #11653] • ObjectSpace methods added, #count_symbols, etc… [Feature ???lol??]

Slide 65

Slide 65 text

Ruby 2.3 Summary • The true beginning of what’s to come in Ruby 3 (Frozen string literal pragma, CLI options) • Some great user experience improvements (did_you_mean, ArgumentError message, better Heredoc, etc) • A few very useful methods/syntax (#dig, hash comparisons, #grep_v, #bsearch_index, Numeric#postive?/negative?, etc) • Internal house cleaning (Rake is a gem, $SAFE levels removed, etc) • Minor performance increases (CGI.escapeHTML and VM improvements)

Slide 66

Slide 66 text

No content

Slide 67

Slide 67 text

Questions? 
 chrisarcand chrisarcand www.chrisarcand.com While I'm not working in the open source community that might be supporting your project, I could be working directly on it for you! I'm available as a part-time contractor to help your project flourish. See me afterward or visit http://chrisarcand.com/forhire/