beneath the surface: regular expressions in ruby
DESCRIPTION
Many of us approach regular expressions with a certain fear and trepidation, using them only when absolutely necessary. We can get by when we need to use them, but we hesitate to dive any deeper into their cryptic world. Ruby has so much more to offer us. This talk showcases the incredible power of Ruby and the Oniguruma regex library Ruby runs on. It takes you on a journey beneath the surface, exploring the beauty, elegance, and power of regular expressions. You will discover the flexible, dynamic, and eloquent ways to harness this beauty and power in your own code.TRANSCRIPT
![Page 1: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/1.jpg)
Photo By Mr. Christopher ThomasCreative Commons Attribution-ShareALike 2.0 Generic License
Beneath the Surface
Embracing the True Power of Regular Expressions in Ruby
@nellshamrell
![Page 2: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/2.jpg)
^4[0-9]{12}(?:[0-9]{3})?$
Source: regular-expressions.info
![Page 3: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/3.jpg)
We fear what we do not understand
![Page 4: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/4.jpg)
![Page 5: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/5.jpg)
Regular Expressions
+ Ruby
Photo By ShayanCreative Commons Attribution-ShareALike 2.0 Generic License
![Page 6: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/6.jpg)
Regex Matching in Ruby
RubyMethods
Onigmo
![Page 7: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/7.jpg)
Onigmo
![Page 8: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/8.jpg)
Oniguruma
OnigmoFork
![Page 9: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/9.jpg)
Onigmo
Reads Regex
![Page 10: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/10.jpg)
Onigmo
Reads Regex
AbstractSyntax
Tree
ParsesInto
![Page 11: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/11.jpg)
Onigmo
Reads Regex
AbstractSyntax
Tree
Series ofInstructions
ParsesInto
CompilesInto
![Page 12: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/12.jpg)
Finite State Machines
Photo By Felipe SkroskiCreative Commons Attribution Generic 2.0
![Page 13: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/13.jpg)
A Finite State Machine Shows How
Something Works
![Page 14: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/14.jpg)
Annie the Dog
![Page 15: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/15.jpg)
In the House
Out of House
Annie the Dog
![Page 16: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/16.jpg)
In the House
Out of House
Annie the Dog
Door
![Page 17: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/17.jpg)
In the House
Out of House
Annie the Dog
Door
Door
![Page 18: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/18.jpg)
Finite
State
Machine
![Page 19: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/19.jpg)
Finite
State
Machine
![Page 20: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/20.jpg)
Finite
State
Machine
![Page 21: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/21.jpg)
Multiple States
![Page 22: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/22.jpg)
/force/
![Page 23: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/23.jpg)
re = /force/string = “Use the force”re.match(string)
![Page 24: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/24.jpg)
f o r c e
/force/
“Use the force”
Path Doesn’t Match
![Page 25: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/25.jpg)
f o r c e
/force/
“Use the force”
Still Doesn’t Match
![Page 26: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/26.jpg)
f o r c e
/force/
“Use the force”
Path Matches!
(Fast Forward)
![Page 27: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/27.jpg)
f o r c e
/force/
“Use the force”
![Page 28: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/28.jpg)
f o r c e
/force/
“Use the force”
![Page 29: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/29.jpg)
f o r c e
/force/
“Use the force”
![Page 30: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/30.jpg)
f o r c e
/force/
“Use the force”
![Page 31: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/31.jpg)
f o r c e
/force/
“Use the force”
We Have A Match!
![Page 32: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/32.jpg)
re = /force/string = “Use the force”re.match(string)=> #<MatchData “force”>
![Page 33: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/33.jpg)
Alternation
Photo By ShayanCreative Commons Attribution Generic 2.0
![Page 34: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/34.jpg)
/Y(olk|oda)/
Pipe
![Page 35: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/35.jpg)
re = /Y(olk|oda)/string = “Yoda”re.match(string)
![Page 36: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/36.jpg)
Y oo
l k
d a
/Y(olk|oda)/
“Yoda”
![Page 37: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/37.jpg)
Y oo
l k
d a
/Y(olk|oda)/
Which To Choose?
“Yoda”
![Page 38: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/38.jpg)
Y oo
l k
d a
/Y(olk|oda)/
“Yoda”Saves To Backtrack
Stack
![Page 39: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/39.jpg)
Y oo
l k
d a
/Y(olk|oda)/
“Yoda”Uh Oh, No Match
![Page 40: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/40.jpg)
Y oo
l k
d a
/Y(olk|oda)/
“Yoda”Backtracks To Here
![Page 41: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/41.jpg)
Y oo
l k
d a
/Y(olk|oda)/
“Yoda”
![Page 42: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/42.jpg)
Y oo
l k
d a
/Y(olk|oda)/
“Yoda”
![Page 43: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/43.jpg)
Y oo
l k
d a
/Y(olk|oda)/
“Yoda”
We Have A Match!
![Page 44: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/44.jpg)
re = /Y(olk|oda)/string = “Yoda”re.match(string)=> #<MatchData “Yoda”>
![Page 45: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/45.jpg)
Photo By Fancy HorseCreative Commons Attribution Generic 2.0
Quantifiers
![Page 46: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/46.jpg)
/No+/
PlusQuantifier
![Page 47: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/47.jpg)
re = /No+/string = “Noooo”re.match(string)
![Page 48: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/48.jpg)
N o
o
/No+/
“Noooo”
![Page 49: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/49.jpg)
N o
o
/No+/
“Noooo”
![Page 50: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/50.jpg)
N o
o
/No+/
“Noooo”
Return Match? Or Keep Looping?
![Page 51: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/51.jpg)
N o
o
/No+/
“Noooo”
Greedy Quantifier
KeepsLooping
![Page 52: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/52.jpg)
Greedy quantifiers match as much as possible
![Page 53: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/53.jpg)
Greedy quantifiers use maximum effort for
maximum return
![Page 54: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/54.jpg)
N o
o
/No+/
“Noooo”
![Page 55: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/55.jpg)
N o
o
/No+/
“Noooo”
![Page 56: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/56.jpg)
N o
o
/No+/
“Noooo”
We Have A Match!
![Page 57: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/57.jpg)
re = /No+/string = “Noooo”re.match(string)=> #<MatchData “Noooo”>
![Page 58: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/58.jpg)
Lazy Quantifiers
![Page 59: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/59.jpg)
Lazy quantifiers match as little as possible
![Page 60: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/60.jpg)
Lazy quantifiers use minimum effort for
minimum return
![Page 61: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/61.jpg)
/No+?/
Makes Quantifier
Lazy
![Page 62: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/62.jpg)
re = /No+?/string = “Noooo”re.match(string)
![Page 63: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/63.jpg)
N o
o“Noooo”
/No+?/
![Page 64: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/64.jpg)
N o
o“Noooo”
/No+?/
![Page 65: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/65.jpg)
N o
o“Noooo”
/No+?/
Return Match? Or Keep Looping?
![Page 66: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/66.jpg)
N o
o“Noooo”
/No+?/
We Have A Match!
![Page 67: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/67.jpg)
re = /No+?/string = “Noooo”re.match(string)=> #<MatchData “No”>
![Page 68: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/68.jpg)
Greedy quantifiers are greedy but reasonable
![Page 69: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/69.jpg)
/.*moon/
StarQuantifier
![Page 70: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/70.jpg)
re = /.*moon/string = “That’s no moon”re.match(string)
![Page 71: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/71.jpg)
. m o o n
./.*moon/
“That’s no moon”
![Page 72: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/72.jpg)
. m o o n
.
“That’s no moon”
/.*moon/
![Page 73: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/73.jpg)
. m o o n
.
“That’s no moon”
Loops
/.*moon/
![Page 74: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/74.jpg)
. m o o n
. Which To Match?
(Fast Forward)
“That’s no moon”
/.*moon/
![Page 75: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/75.jpg)
. m o o n
.
“That’s no moon”
Keeps Looping
/.*moon/
![Page 76: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/76.jpg)
. m o o n
.
“That’s no moon”
Keeps Looping
/.*moon/
![Page 77: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/77.jpg)
. m o o n
.
“That’s no moon”
Keeps Looping
/.*moon/
![Page 78: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/78.jpg)
. m o o n
“That’s no moon”No More
Characters?
./.*moon/
![Page 79: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/79.jpg)
. m o o n
“That’s no moon”
Backtrack or Fail?./.*moon/
![Page 80: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/80.jpg)
. m o o n
“That’s no moon”Backtracks
./.*moon/
![Page 81: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/81.jpg)
. m o o n
“That’s no moon”Backtracks
./.*moon/
![Page 82: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/82.jpg)
. m o o n
“That’s no moon”Backtracks
./.*moon/
![Page 83: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/83.jpg)
. m o o n
“That’s no moon”Backtracks
Huzzah!./.*moon/
![Page 84: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/84.jpg)
. m o o n
“That’s no moon”
./.*moon/
![Page 85: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/85.jpg)
. m o o n
“That’s no moon”
./.*moon/
![Page 86: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/86.jpg)
. m o o n
“That’s no moon”
./.*moon/
![Page 87: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/87.jpg)
. m o o n
“That’s no moon”
. We Have A Match!
/.*moon/
![Page 88: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/88.jpg)
re = /.*moon/string = “That’s no moon”re.match(string)=> #<MatchData “That’s no moon”>
![Page 89: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/89.jpg)
Backtracking = Slow
![Page 90: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/90.jpg)
/No+w+/
![Page 91: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/91.jpg)
re = /No+w+/string = “Noooo”re.match(string)
![Page 92: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/92.jpg)
N o
o“Noooo”
/No+w+/
w
w
![Page 93: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/93.jpg)
N o
o“Noooo”
/No+w+/
w
w
![Page 94: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/94.jpg)
N o
o“Noooo”
/No+w+/
w
wLoops
![Page 95: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/95.jpg)
N o
o“Noooo”
/No+w+/
w
wLoops
![Page 96: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/96.jpg)
N o
o“Noooo”
/No+w+/
w
wLoops
![Page 97: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/97.jpg)
N o
o“Noooo”
/No+w+/
w
w
Uh Oh
![Page 98: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/98.jpg)
N o
o“Noooo”
/No+w+/
w
w
Uh Oh
Backtrack or Fail?
![Page 99: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/99.jpg)
N o
o“Noooo”
/No+w+/
w
wBacktracks
![Page 100: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/100.jpg)
N o
o“Noooo”
/No+w+/
w
wBacktracks
![Page 101: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/101.jpg)
N o
o“Noooo”
/No+w+/
w
wBacktracks
![Page 102: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/102.jpg)
N o
o“Noooo”
/No+w+/
w
w
Match FAILS
![Page 103: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/103.jpg)
Possessive Quantifers
![Page 104: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/104.jpg)
Possessive quantifiers do not backtrack
![Page 105: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/105.jpg)
Makes Quantifier Possessive
/No++w+/
![Page 106: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/106.jpg)
N o
o“Noooo”
w
w
/No++w+/
![Page 107: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/107.jpg)
N o
o“Noooo”
w
w
/No++w+/
![Page 108: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/108.jpg)
N o
o“Noooo”
w
wLoops
/No++w+/
![Page 109: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/109.jpg)
N o
o“Noooo”
w
wLoops
/No++w+/
![Page 110: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/110.jpg)
N o
o“Noooo”
w
wLoops
/No++w+/
![Page 111: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/111.jpg)
N o
o“Noooo”
w
w
/No++w+/
![Page 112: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/112.jpg)
N o
o“Noooo”
w
wLoops
Uh Oh
Backtrack or Fail?
/No++w+/
![Page 113: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/113.jpg)
N o
o“Noooo”
w
w
Match FAILS
/No++w+/
![Page 114: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/114.jpg)
Possessive quantifiers fail faster by
controlling backtracking
![Page 115: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/115.jpg)
![Page 116: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/116.jpg)
Tying It All Together
Photo By Keith RamosCreative Commons Attribution 2.0 Generic
![Page 117: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/117.jpg)
![Page 118: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/118.jpg)
snake_case to CamelCase
![Page 119: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/119.jpg)
Find first letter of string and capitalize it
snake_case to CamelCase
![Page 120: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/120.jpg)
Find first letter of string and capitalize it
Find any character that follows an underscore and capitalize it
snake_case to CamelCase
![Page 121: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/121.jpg)
Find first letter of string and capitalize it
Find any character that follows an underscore and capitalize it
Remove underscores
snake_case to CamelCase
![Page 122: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/122.jpg)
Find first letter of string and capitalize it
snake_case to CamelCase
![Page 123: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/123.jpg)
it ʺ″capitalizes the first letterʺ″ do
end
result = @case_converter.upcase_chars(ʺ″methodʺ″)
result.should == ʺ″Methodʺ″
case_converter_spec.rb
before(:each) do
end@case_converter = CaseConverter.new
![Page 124: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/124.jpg)
it ʺ″capitalizes the first letterʺ″ do
end
result = @case_converter.upcase_chars(ʺ″methodʺ″)
result.should == ʺ″Methodʺ″
case_converter_spec.rb
before(:each) do
end@case_converter = CaseConverter.new
![Page 125: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/125.jpg)
it ʺ″capitalizes the first letterʺ″ do
end
result = @case_converter.upcase_chars(ʺ″methodʺ″)
result.should == ʺ″Methodʺ″
case_converter_spec.rb
before(:each) do
end@case_converter = CaseConverter.new
![Page 126: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/126.jpg)
/ /^
Anchors Match To
Beginning Of String
![Page 127: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/127.jpg)
/ /\ w^
Matches Any Word
Character
![Page 128: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/128.jpg)
case_converter.rb
def upcase_chars(string)
end
re = / /\w^string.gsub(re){|char| char.upcase}
![Page 129: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/129.jpg)
case_converter.rb
def upcase_chars(string)
end
re = / /\w^string.gsub(re){|char| char.upcase}
![Page 130: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/130.jpg)
case_converter.rb
def upcase_chars(string)
end
re = / /\w^string.gsub(re){|char| char.upcase}
Spec Passes!
![Page 131: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/131.jpg)
it ʺ″capitalizes the first letterʺ″ do
end
result = @case_converter
result.should == ʺ″_Methodʺ″
case_converter_spec.rb
.upcase_chars(ʺ″_methodʺ″)
![Page 132: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/132.jpg)
it ʺ″capitalizes the first letterʺ″ do
end
result = @case_converter
result.should == ʺ″_Methodʺ″
case_converter_spec.rb
.upcase_chars(ʺ″_methodʺ″)
![Page 133: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/133.jpg)
it ʺ″capitalizes the first letterʺ″ do
end
result = @case_converter
result.should == ʺ″_Methodʺ″
case_converter_spec.rb
.upcase_chars(ʺ″_methodʺ″)
Spec Fails!
![Page 134: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/134.jpg)
Expected: ʺ″_Methodʺ″Got: ʺ″_methodʺ″
Spec Failure:
![Page 135: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/135.jpg)
Problem:Matches Letters AND Underscores
\ w^/ /
![Page 136: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/136.jpg)
/ /[a-z]^
Matches Only
Lowercase Letters
![Page 137: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/137.jpg)
/ /[a-z]^[^a-z]
Matches everything
BUT lowercase letters
![Page 138: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/138.jpg)
/ /[a-z][̂^a-z]?
Makes Character
Class Optional
![Page 139: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/139.jpg)
case_converter.rb
def upcase_chars(string)
end
re = string.gsub(re){|char| char.upcase}
/ /[a-z]^[^a-z]?
![Page 140: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/140.jpg)
case_converter.rb
def upcase_chars(string)
endstring.gsub(re){|char| char.upcase}
Spec Passes!
re = / /[a-z]^[^a-z]?
![Page 141: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/141.jpg)
Find any character that follows an underscore and capitalize it
snake_case to CamelCase
![Page 142: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/142.jpg)
it ʺ″capitalizes letters after an underscoreʺ″ do
end
result = @case_converter
result.should == ʺ″Some_Methodʺ″
case_converter_spec.rb
.upcase_chars(ʺ″some_methodʺ″)
![Page 143: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/143.jpg)
it ʺ″capitalizes letters after an underscoreʺ″ do
end
result = @case_converter
result.should == ʺ″Some_Methodʺ″
case_converter_spec.rb
.upcase_chars(ʺ″some_methodʺ″)
![Page 144: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/144.jpg)
/ /[a-z]^[^a-z]?
![Page 145: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/145.jpg)
Pipe For Alternation
| [a-z]/ /[a-z]^[^a-z]?
![Page 146: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/146.jpg)
Look Behind
(?<=_)| [a-z]/ /[a-z]^[^a-z]?
![Page 147: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/147.jpg)
case_converter.rb
def upcase_chars(string)
end
re = string.gsub(re){|char| char.upcase}
| [a-z](?<=_)/ /[a-z]^[^a-z]?
![Page 148: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/148.jpg)
case_converter.rb
def upcase_chars(string)
end
re = string.gsub(re){|char| char.upcase}
| [a-z](?<=_)/ /[a-z]^[^a-z]?
Spec Passes!
![Page 149: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/149.jpg)
Remove underscores
snake_case to CamelCase
![Page 150: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/150.jpg)
it ʺ″removes underscoresʺ″ do
end
result = @case_converter
result.should == ʺ″somemethodʺ″
case_converter_spec.rb
.rmv_underscores(ʺ″some_methodʺ″)
![Page 151: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/151.jpg)
it ʺ″removes underscoresʺ″ do
end
result = @case_converter
result.should == ʺ″somemethodʺ″
case_converter_spec.rb
.rmv_underscores(ʺ″some_methodʺ″)
![Page 152: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/152.jpg)
it ʺ″removes underscoresʺ″ do
end
result = @case_converter
result.should == ʺ″somemethodʺ″
case_converter_spec.rb
.rmv_underscores(ʺ″some_methodʺ″)
![Page 153: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/153.jpg)
MatchesAn
Underscore
/ /_
![Page 154: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/154.jpg)
case_converter.rb
def rmv_underscores(string)
end
re = string.gsub(re, “”)
/ /_
![Page 155: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/155.jpg)
case_converter.rb
def rmv_underscores(string)
endstring.gsub(re, “”)re = / /_
![Page 156: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/156.jpg)
case_converter.rb
def rmv_underscores(string)
endstring.gsub(re, “”)
Spec Passes!
re = / /_
![Page 157: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/157.jpg)
Combine results of two methods
snake_case to CamelCase
![Page 158: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/158.jpg)
it ʺ″converts snake_case to CamelCaseʺ″ do
end
result = @case_converter
result.should == ʺ″SomeMethodʺ″
case_converter_spec.rb
.snake_to_camel(ʺ″some_methodʺ″)
![Page 159: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/159.jpg)
it ʺ″converts snake_case to CamelCaseʺ″ do
end
result = @case_converter
result.should == ʺ″SomeMethodʺ″
case_converter_spec.rb
.snake_to_camel(ʺ″some_methodʺ″)
![Page 160: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/160.jpg)
it ʺ″converts snake_case to CamelCaseʺ″ do
end
result = @case_converter
result.should == ʺ″SomeMethodʺ″
case_converter_spec.rb
.snake_to_camel(ʺ″some_methodʺ″)
![Page 161: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/161.jpg)
case_converter.rb
def snake_to_camel(string)
endupcase_chars(string)
![Page 162: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/162.jpg)
case_converter.rb
def snake_to_camel(string)
endupcase_chars(string)rmv_underscores( )
![Page 163: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/163.jpg)
case_converter.rb
def snake_to_camel(string)
endupcase_chars(string)rmv_underscores( )
Spec Passes!
![Page 164: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/164.jpg)
Code is available here:https://github.com/nellshamrell/snake_to_camel_case
![Page 165: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/165.jpg)
Conclusion
Photo By Steve JurvetsonCreative Commons Attribution Generic 2.0
![Page 166: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/166.jpg)
Develop regular expressions in small pieces
![Page 167: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/167.jpg)
![Page 168: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/168.jpg)
If you write code, you can write regular expressions
![Page 169: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/169.jpg)
Move beyond the fear
![Page 170: Beneath the Surface: Regular Expressions in Ruby](https://reader038.vdocuments.site/reader038/viewer/2022110310/559ebd101a28ab712a8b473f/html5/thumbnails/170.jpg)
Photo By Leonardo PallottaCreative Commons Attribution Generic 2.0
Nell ShamrellSoftware Development Engineer
Blue Box Inc
@nellshamrell
https://gist.github.com/nellshamrell/6031738
Resources: