SlideShare uma empresa Scribd logo
1 de 82
Baixar para ler offline
(Nothing says “playful” like a broken printing press from the 1840s.)
playfulness at work
             a real serious message™ with Ruby as the medium


                                    Ian Dees / @undees




Hi, I’m Ian. I’m here to talk about playfulness at work, and how that relates to Ruby.
1. playfulness in the workplace...

           2. ...or the way playfulness works?




“Playfulness at Work”—does that mean “bringing play into the workplace” or “the way playfulness
works?”
yes



Both, actually. I’ll get into the strange arc of this talk in a moment.
first, a word of thanks



But first, I’ve got two groups of people to thank.
our organizers




              Ben Bleything                                     Shane Becker


First, to our organizers Ben and Shane, thank you for putting this whole thing together.
our hosts


                         Seattle.rb

Second, to our host city and its Rubyists, thank you for having us here and for making so much
great software.
Seriously—these folks have made tons of useful software: just look at it all!
their stuff will help your stuff

              flog
              flay
              heckle
              ... and much more!




I’ll just highlight a couple of seattle.rb libraries here.... flog and flay report trouble spots in your
code: methods that are too long or too similar; that kind of thing. heckle inserts bugs into your
code and makes sure each bug results in a failing test case. If you’ve never run these before, catch
me in the hallway later and I’ll embarrass myself by running them on my own code for you.
Okay, on to the topic at hand. I make oscilloscopes. There’s something gratifying about making
something physical that lets you see into an invisible world.... But what does that have to do with
Ruby?
why this talk?



In other words, why this talk? Well, it turns out that even in a big organization like the one where I
work, there are scattered pockets of Ruby resistance against the C++ empire.
why Ruby?



Why is that? Aren’t we supposed to be writing embedded software here? Close. As Rich Kilmer
reminded us yesterday, what we’re supposed to do is create something that solves a problem for
someone. That might mean embedded code, a web front end for some engineering data, a one-off
shell script, a document, or nothing at all.
(“Nothing at all... nothing at all....”)
Anyway.... On those days when we need to munge some data or glue a couple of programs
together, Ruby comes to the rescue.
why bother?



There’s always a temptation is to follow the path of least acceleration and just do what the
organization thinks it wants to do. Fighting that temptation keeps our creative impulses sharp—
paradoxically resulting in our doing a better job than if we’d just done what was asked or expected
of us.
why this talk?

             why bother?

             why Ruby?

             why?

             why?

             why?


So, all these questions seem like they’re leading somewhere.
_why



Does anyone remember why the lucky stiff’s 2004 essay, “Wearing Ruby Slippers to Work?”
It was about sneaking Ruby into work through the back door, using it to get little scripting tasks
done.
what’s changed?
                 we can walk in through the front door now!




Stealth was the only option back then. We had to prove ourselves with any unknown technology.
And now... Ruby is in the top twenty languages, according to that chart we saw yesterday. We’ve got
a little more leeway to storm the workplace and use Ruby when it suits the task at hand.
1. dealing with crusty data
         formats and protocols
                                  ...in a lighthearted way




I’d like to talk about a few of these kinds of those situations now, mainly as an excuse to bring up
some Ruby libraries you may find useful.
2. scripting other
      people's software
        ...whether they know it or not




...
3. sharing your code
        with co-workers
        ...without annoying them too much




...
4. deploying your
             software
      ...to honest-to-goodness paying customers!




...
*



Ready?
1. dealing with crusty data
         formats and protocols
                                  ...in a lighthearted way




First, data parsing. I work at a bigco, where we’ve seen ad hoc data formats come and go. For
example, you might hear, “That file full of test logs we just sort of started cutting and pasting into…
can you figure out how many times the Foo subsystem called into the Bar module?” The goal: get
the answer quickly with your sanity intact.
introducing my own
                    ad hoc format...



Just to get a taste of how easy it is to wrangle arbitrary data in Ruby, I’ll introduce a toy format and
then show a few lines of code to parse it.
TaskParchment
                             (with apologies to TaskPaper)


             - Invent my own crufty data format
                  - Start with a good format @done
                  - Ruin it @badidea @done
             - ???
             - Profit!



The format will be based on TaskPaper, which seems to be a reasonable format for to-do lists.
Except I’m going to take everything cool out of it, so we can meaningfully talk about it in a few
slides. So, it’s like TaskPaper, but thinner: ergo, TaskParchment.
kschiess’s Parslet DSL
                          https://github.com/kschiess/parslet




We’ll use the Parslet library for picking apart the data. It’s based on the idea of Parsing Expression
Grammars—regular expressions attached to bits of code. Sounds like a hack, but there’s actually a
solid theoretical foundation for it.
describe TaskParchment::Parser do
     before { @parser = TaskParchment::Parser.new }

       it 'parses a task' do
         input    = "- Task @taggedn"
         expected = {:desc=>"Task ", :tags=>[{:tag => "tagged"}]}

         @parser.task_line.parse(input).must_equal expected
       end

     # ...
   end




The first stage of parsing is to get the text into some kind of in-memory representation of a tree.
Parslet’s representation is a conglomeration of hashes and arrays. Here’s a first taste. Notice we’re
using minitest (built into Ruby 1.9.2) to do our testing. We can invoke a single parsing rule at a time
—in this case the yet-to-be-written “task_line” rule. This is a big help for testing.
require 'parslet'

                    module TaskParchment
                      class Parser < Parslet::Parser
                        # Example:
                        #
                        # - This is a task @tag
                        #
                        rule(:task_line)   {
                          begin_task              >>
                            description.as(:desc) >>
                            tags.maybe            >>
                            newline
                        }

                        # ...
                      end
                    end
Here’s the implementation of that rule. See how fluidly Parslet reads: a single line of a task consists
of punctuation, followed by a description, possibly some tags, and finally a newline. Each of these
components is itself a rule. Let’s define those next.
rule(:begin_task)             {   str('- ') }
                    rule(:description)            {   desc_char.repeat(1) }
                    rule(:desc_char)              {   match('[^@n]') }
                    rule(:newline)                {   str("n") }




These are the the basic building blocks of a task. Notice that we can match exact strings or regular
expressions.
rule(:tags) { tag.repeat(1).as(:tags) }

                       rule(:tag) {
                         begin_tag                   >>
                         tag_char.repeat(1).as(:tag) >>
                         space.maybe
                       }




Here’s how we define tags for a task. Notice the “as(:tag)” marker. This is a signal to Parslet to
discard all the other stuff (spaces and punctuation) and just keep the tag name in the final in-
memory tree.
rule(:begin_tag)             { str('@') }
                      rule(:tag_char)              { match('[^@ n]') }
                      rule(:space)                 { str(' ') }




Here are the last few pieces of punctuation we haven’t defined yet.
$ ruby test_task_parchment.rb
       Loaded suite test_task_parchment
       Started
       .
       Finished in 0.001903 seconds.

       1 tests, 1 assertions, 0 failures, 0 errors, 0 skips

       Test run options: --seed 23512




Now our tests pass.
whew!



Let’s take a breath for a sec, before jumping into tasks that contain subtasks.
it 'parses a terrible plan into a tree' do
            input = <<HERE
       - Invent my own crufty data format
         - Start with a good format @done
         - Ruin it @badidea @done
       - ???
       - Profit!
       HERE




             # ...




          end

Here’s the original TaskParchment string we wanted to parse.
it 'parses a terrible plan into a tree' do
            # ...

            expected =
              [{:desc=>"Invent my own crufty data format",
                 :subtasks=>
                 [{:desc=>"Start with a good format ",
                    :tags=>[{:tag=>"done"}],
                    :subtasks=>[]},
                  {:desc=>"Ruin it ",
                    :tags=>[{:tag=>"badidea"}, {:tag=>"done"}],
                    :subtasks=>[]}]},
               {:desc=>"???", :subtasks=>[]},
               {:desc=>"Profit!", :subtasks=>[]}]

           # ...
          end

Here’s the in-memory representation we want.
it 'parses a terrible plan into a tree' do




              # ...




            @parser.parse(input).must_equal expected
          end

And here’s the test assertion.
def task_line_indented_at(indent)
                    space.repeat(indent, indent) >> task_line
                  end

                  def task_indented_at(indent)
                    parser   = task_line_indented_at(indent)
                    parser >>= task_indented_at(indent + 2).
                      repeat(0).as(:subtasks) unless indent > 20
                    parser
                  end

                  rule(:list) { task_indented_at(0).repeat(0) }
                  root(:list)




Believe it or not, we can do this with just a couple more parser rules. We’ll define these as functions
that take an indentation parameter. We’ll cap the indentation at 20 to prevent an infinite regression
in our parser (quite easy to do in PEG parsers). That “root” bit at the bottom gives the starting rule
for parsing an entire document.
$ ruby test_task_parchment.rb
         Loaded suite test_task_parchment
         Started
         ..
         Finished in 0.009532 seconds.

         2 tests, 2 assertions, 0 failures, 0 errors, 0 skips

         Test run options: --seed 63924




Two passing tests.
yay!



From here, Parslet has other tools for transforming those raw arrays and hashes into your own Ruby
classes. But let’s prepare to jump to another topic now. The lesson here is that we could have rolled
our own parser and had less fun (not to mention poorer syntax error reporting). Instead, we used
Ruby as an excuse for experimenting with a peculiar parsing technique.
2. scripting other
                     people's software
                            ...whether they know it or not




Next up: scripting. One day, you may be asked to write a data converter for a nasty binary format
that’s undocumented, unsupported, and has no developer hooks in the only software that knows
how to read it. You might try to reverse-engineer their API, or you might get nasty and just drive
their software through the user interface.
something silly



Rather than shame the vendor of this particular piece of software, I’d rather just go off in a different
direction and do something silly with FFI in Ruby. We’re going to write a script that renders a black-
and-white picture in the least efficient way possible: by clicking it pixel-by-pixel with the mouse.
chunky_png
                  https://github.com/wvanbergen/chunky_png




First, we need to crack open the picture and find the dark pixels. To do this, we’ll use the excellent
chunky_png, a pure-Ruby PNG decoder.
require 'chunky_png'

               image   = ChunkyPNG::Image.from_file filename
               shadows = []

               (0...image.height).each do |y|
                 (0...image.width).each do |x|
                   gray = ChunkyPNG::Color.grayscale_teint 
                     image[x, y]

                   shadows << [x, y] if gray < 128
                 end
               end




This code will build an array of the x/y locations we’ll need to click with the mouse.
FFI
                                  https://github.com/ffi/ffi




To grab hold of the platform-specific mouse API, we’re going to use FFI, the foreign function
interface library that started in the Rubinius project and is now available in at least three other Ruby
implementations.
require 'ffi'

         module User32
           extend FFI::Library

            ffi_lib        'user32'
            ffi_convention :stdcall

            MOUSEEVENTF_LEFTDOWN = 0x0002
            MOUSEEVENTF_LEFTUP   = 0x0004

           attach_function :SetCursorPos, [:long, :long], :int
           attach_function :mouse_event, [:long] * 5, :void
         end



To simulate a mouse click on this particular platform, you need to import two functions: one to
position the mouse, and one to click it. Notice how the FFI functions look vaguely like C
declarations.
include User32

              def mouse_click(x, y)
                SetCursorPos x, y
                mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
                mouse_event MOUSEEVENTF_LEFTUP,   0, 0, 0, 0
              end




Here’s how to actually simulate the click.
shadows.sort_by { rand }.each do |x, y|
                     mouse_click 100 + x, 100 + y
                     sleep 0.05
                   end




And here’s how we’ll draw the picture. To save a bunch of window-management code in these
examples, we’ll just assume the drawing app is maximized. We’ll give it a margin of 100 pixels each
way to make room for the toolbar.
win_gui
                        https://github.com/arvicco/win_gui




The code is even simpler if you use win_gui, a gem that provides FFI wrappers for common Windows
GUI calls.
require 'win_gui'

                w = WinGui::Window.find :title => /- Paint$/

                shadows.sort_by { rand }.each do |x, y|
                  w.click :point => [100 + x, 100 + y]
                  sleep 0.05
                end




Here’s the entire drawing routine in win_gui. We don’t need any of the FFI setup stuff any more, or
the definition of a mouse click.
In the real-life story that inspired this example, we were able to convert the screen scraper to C
with basically a few macros in Emacs. The program did its job, and we abandoned it as soon as we
could to move on to more worthy projects.
3. sharing your code
                   with co-workers
                         ...without annoying them too much




Now, I’d like to talk about deployment. Once you’ve written that brilliant text parser, data converter,
or web front end, how do you share it with your co-workers who may be on an IT-supplied
Windows XP box?
running from source



The simplest way to share code internally is to just hand your co-worker a .rb file and be done with
it.
2005


                       “just download Ruby from here”




In 2005, that worked pretty well. You could just tell people, “Download the all-in-one Ruby installer
from here, save this .rb file onto your machine, and run it.”
2008

                                          MSWin                  MinGW


                      1.8                    easy                   scary


                      1.9                    hard                   scary


Then life got complicated. Not only were there there two versions of Ruby, there were two
alternative Windows builds of Ruby. If your program depended on a gem that had C code in it, the
compiled code would only work in one particular Ruby variant.
2010

                                          MSWin                  MinGW


                      1.8                   gone                    easy


                      1.9                   gone                    easy


The story is much better now. MinGW has emerged as the winner of the C compiler battle, as far as
Ruby is concerned. And the Windows folks have found a way to deal with C code that works in both
1.8 and 1.9.
RubyInstaller
                     https://github.com/oneclick/rubyinstaller




It’s all thanks to Luis Lavena’s RubyInstaller, which installs Ruby onto your system and has an
optional dev kit that pretty much makes “gem install” work the same on Windows as it does on
UNIX. You still have to worry about dependencies, but this is a huge step forward.
self-contained
                           executables



Another approach is to build binaries for people that include enough Ruby for them to run your
program without an extra installation step.
OCRA
                           https://github.com/larsch/ocra




Windows Rubyists have OCRA, the One-Click Ruby Application builder. This will bundle up your
Ruby program with a copy of the interpreter and any gems you need into a single .exe file.
what shall we deploy?



Let’s pick an app to serve as a guinea pig, so we can show a few of these techniques.
holman’s Boom app
                         http://github.com/holman/boom




In keeping with the Hubot chat robot from yesterday, let’s show something that appears to have
made Zach Holman the fastest draw in Campfire: a command-line clipboard manager called Boom.
(Pronounce it “bewwwwwm.”)
...
require 'boom'
                            Boom::Command.execute(*ARGV)




                                 C:boom> ocra boom.rb




                                           boom.exe




This app has a gem dependency (on json-pure). As long as that’s installed on our system, OCRA will
find it. We just write a trivial .rb file to launch Boom, point OCRA at it, and we get a working exe.
Warbler
                      https://github.com/nicksieger/warbler




I’m partial to JRuby myself, because it makes it easy to use gems that have a compiled component.
JRuby binary gems (such as ActiveRecord database adapters) don’t have to be compiled for each
specific platform. Warbler is a JRuby build tool that looks at your app’s Gemfile and creates a
runnable .jar file that anyone with Java installed can run.
# bin/boom
                           require 'boom'
                           Boom::Command.execute(*ARGV)



                                    # Gemfile
                                    source :rubygems
                                    gem 'boom'
                                    gem 'httparty'



                                       $ bundle
                                       $ warble jar



                                          boom.jar
The workflow with Warbler is nearly the same as with OCRA. Warbler keys off your project’s Gemfile,
rather than watching your require calls.
4. deploying your
                          software
                  ...to honest-to-goodness paying customers!




The techniques we’ve seen so far have been good enough for sharing code with co-workers, and
perhaps a few customers (at work, we’ve put OCRA-based binaries on our website for end users). At
some point, though, you begin to wonder, “Does this app need an installer?”
RailsInstaller
                             https://github.com/railsinstaller




If you wanted to build a full installer for a Ruby app, you could start with the RubyInstaller project
and then add some installation steps that contain your own Ruby code and dependencies. That’s
pretty much what the RailsInstaller project from Engine Yard does. It installs Ruby, Rails, Git, and
some other dependencies onto a Windows machine.
BoomInstaller
                                    what would it take?




As a thought experiment, what would it take to turn the RailsInstaller into a BoomInstaller?
# railsinstaller.yml
                                 ---
                                 :gems:
                                   :name: Gems
                                   :title: Ruby Gems
                                   :category: gems
                                   :list:
                                     - boom

                                 :boom:
                                   :name: Boom
                                   :title: Text snippets
                                   :category: gem




It’s pretty easy, as it turns out. Dr. Nic and crew have made their installation recipes configurable.
You’d just need to add the Boom gem to a YAML config file.
# actions.rb
                  module RailsInstaller

                     def self.build!

                        components = [
                          BSDTar, SevenZip, DevKit, Ruby187,
                        ]

                        components.each do |package|
                          section package.title
                          download package
                          extract package
                        end

                      link_devkit_with_ruby
                    end
                  end
Then you’d need to shorten the list of installed components (unless you want to deploy Git and SQL
bindings along with Boom).
;railsinstaller.iss

-#define InstallerName "RailsInstaller"
+#define InstallerName "BoomInstaller"

-DefaultDirName={sd}RailsInstaller
+DefaultDirName={sd}BoomInstaller

-VersionInfoDescription=Rails development environment installer...
+VersionInfoDescription=Boom installer for Windows

 ;...




The ugliest part is editing the Inno Setup script. It’s mostly just grepping through for each
occurrence of Rails and deciding whether or not to replace it with Boom.
licenses and artwork




You’d also want to change licenses and artwork....
licenses and artwork




...to something for your app.
BoomInstaller
              https://github.com/undees/railsinstaller-windows/
                                 tree/boom




You can see the changes I made in the “boom” branch of my fork of RailsInstaller.
That wraps up the concrete portion of the program. Let’s zoom back out to the big questions of
why we’re doing this.

Image courtesy http://www.flickr.com/photos/chrisbevan/2476405
playfulness



For me, and I suspect for many of you, Ruby imparts a sense of playfulness. And in the next few
minutes, I’m going to prove that one can carefully cherry-pick a few items from Brain Science™ to
support the importance of play at work.
Brain Science™ on play




              Stuart Brown                                          Tim Brown


First, here’s a pair of TED talks on creative play. TED is the conference speaker’s ideal substitute for
research, by the way. Stuart Brown says, “Nothing lights up the brain like play,” and then proceeds
to tell us how that works, biologically speaking. Tim Brown explains how playfulness improves the
performance of entire teams.
Next, there’s material I was actually exposed to as a kid... on vinyl. It’s about how to harness the
huge parallel processing unit in our heads to solve problems in ways we didn’t expect. (See also
Andy Hunt’s Pragmatic Thinking and Learning). The gist is that play unlocks your brain’s problem-
solving engine.
Finally, there’s I Hate People, an airplane reading book that sounds like it’s going to be Dilbert
come to life, but does a Randy-Pausch-style head fake into shaping your career. The authors talk
about the notion of being a Soloist, someone who does creative work with a supportive ensemble at
work. tl;dr: by their scrappy entrepreneurship, Soloists drag their organizations kicking and
screaming to success.
Which brings us here. Over the past two days, you’ve heard how crucial it is to keep yourself
engaged and challenged in your work. You’ve heard about the importance of community in
promoting that virtuous cycle that feeds success into success. My hope is that Cascadia Ruby Conf
doesn’t end here. (We haven’t had lunch yet!) My hope is that we continue to connect, to support
one another, to stay playful, and to keep making great things. Long live Cascadia Ruby Conf.
Cheers.
slides and code
                      https://github.com/undees/cascadiaruby




Slides and code will be available at this address (eventually).

Mais conteúdo relacionado

Mais procurados

Ruby for Perl Programmers
Ruby for Perl ProgrammersRuby for Perl Programmers
Ruby for Perl Programmersamiable_indian
 
name name2 n2.ppt
name name2 n2.pptname name2 n2.ppt
name name2 n2.pptcallroom
 
Python Workshop - Learn Python the Hard Way
Python Workshop - Learn Python the Hard WayPython Workshop - Learn Python the Hard Way
Python Workshop - Learn Python the Hard WayUtkarsh Sengar
 
Inside Python [OSCON 2012]
Inside Python [OSCON 2012]Inside Python [OSCON 2012]
Inside Python [OSCON 2012]Tom Lee
 
Memory Management In Python The Basics
Memory Management In Python The BasicsMemory Management In Python The Basics
Memory Management In Python The BasicsNina Zakharenko
 
Variables: names, bindings, type, scope
Variables: names, bindings, type, scopeVariables: names, bindings, type, scope
Variables: names, bindings, type, scopesuthi
 
A(n abridged) tour of the Rust compiler [PDX-Rust March 2014]
A(n abridged) tour of the Rust compiler [PDX-Rust March 2014]A(n abridged) tour of the Rust compiler [PDX-Rust March 2014]
A(n abridged) tour of the Rust compiler [PDX-Rust March 2014]Tom Lee
 
Learn Python The Hard Way Presentation
Learn Python The Hard Way PresentationLearn Python The Hard Way Presentation
Learn Python The Hard Way PresentationAmira ElSharkawy
 
Ti1220 Lecture 2: Names, Bindings, and Scopes
Ti1220 Lecture 2: Names, Bindings, and ScopesTi1220 Lecture 2: Names, Bindings, and Scopes
Ti1220 Lecture 2: Names, Bindings, and ScopesEelco Visser
 
Php Extensions for Dummies
Php Extensions for DummiesPhp Extensions for Dummies
Php Extensions for DummiesElizabeth Smith
 
Python Compiler Internals Presentation Slides
Python Compiler Internals Presentation SlidesPython Compiler Internals Presentation Slides
Python Compiler Internals Presentation SlidesTom Lee
 
Intro to Functions Python
Intro to Functions PythonIntro to Functions Python
Intro to Functions Pythonprimeteacher32
 

Mais procurados (13)

Ruby for Perl Programmers
Ruby for Perl ProgrammersRuby for Perl Programmers
Ruby for Perl Programmers
 
ppt9
ppt9ppt9
ppt9
 
name name2 n2.ppt
name name2 n2.pptname name2 n2.ppt
name name2 n2.ppt
 
Python Workshop - Learn Python the Hard Way
Python Workshop - Learn Python the Hard WayPython Workshop - Learn Python the Hard Way
Python Workshop - Learn Python the Hard Way
 
Inside Python [OSCON 2012]
Inside Python [OSCON 2012]Inside Python [OSCON 2012]
Inside Python [OSCON 2012]
 
Memory Management In Python The Basics
Memory Management In Python The BasicsMemory Management In Python The Basics
Memory Management In Python The Basics
 
Variables: names, bindings, type, scope
Variables: names, bindings, type, scopeVariables: names, bindings, type, scope
Variables: names, bindings, type, scope
 
A(n abridged) tour of the Rust compiler [PDX-Rust March 2014]
A(n abridged) tour of the Rust compiler [PDX-Rust March 2014]A(n abridged) tour of the Rust compiler [PDX-Rust March 2014]
A(n abridged) tour of the Rust compiler [PDX-Rust March 2014]
 
Learn Python The Hard Way Presentation
Learn Python The Hard Way PresentationLearn Python The Hard Way Presentation
Learn Python The Hard Way Presentation
 
Ti1220 Lecture 2: Names, Bindings, and Scopes
Ti1220 Lecture 2: Names, Bindings, and ScopesTi1220 Lecture 2: Names, Bindings, and Scopes
Ti1220 Lecture 2: Names, Bindings, and Scopes
 
Php Extensions for Dummies
Php Extensions for DummiesPhp Extensions for Dummies
Php Extensions for Dummies
 
Python Compiler Internals Presentation Slides
Python Compiler Internals Presentation SlidesPython Compiler Internals Presentation Slides
Python Compiler Internals Presentation Slides
 
Intro to Functions Python
Intro to Functions PythonIntro to Functions Python
Intro to Functions Python
 

Semelhante a Playfulness at Work

Real World Haskell: Lecture 1
Real World Haskell: Lecture 1Real World Haskell: Lecture 1
Real World Haskell: Lecture 1Bryan O'Sullivan
 
RSpec 3.0: Under the Covers
RSpec 3.0: Under the CoversRSpec 3.0: Under the Covers
RSpec 3.0: Under the CoversBrian Gesiak
 
The Ring programming language version 1.7 book - Part 43 of 196
The Ring programming language version 1.7 book - Part 43 of 196The Ring programming language version 1.7 book - Part 43 of 196
The Ring programming language version 1.7 book - Part 43 of 196Mahmoud Samir Fayed
 
Uses & Abuses of Mocks & Stubs
Uses & Abuses of Mocks & StubsUses & Abuses of Mocks & Stubs
Uses & Abuses of Mocks & StubsPatchSpace Ltd
 
Solving the Riddle of Search: Using Sphinx with Rails
Solving the Riddle of Search: Using Sphinx with RailsSolving the Riddle of Search: Using Sphinx with Rails
Solving the Riddle of Search: Using Sphinx with Railsfreelancing_god
 
Creating your own Abstract Processor
Creating your own Abstract ProcessorCreating your own Abstract Processor
Creating your own Abstract ProcessorAodrulez
 
The Essential Perl Hacker's Toolkit
The Essential Perl Hacker's ToolkitThe Essential Perl Hacker's Toolkit
The Essential Perl Hacker's ToolkitStephen Scaffidi
 
NoSQL and SQL Anti Patterns
NoSQL and SQL Anti PatternsNoSQL and SQL Anti Patterns
NoSQL and SQL Anti PatternsGleicon Moraes
 
Ruby -the wheel Technology
Ruby -the wheel TechnologyRuby -the wheel Technology
Ruby -the wheel Technologyppparthpatel123
 
The Holistic Programmer
The Holistic ProgrammerThe Holistic Programmer
The Holistic ProgrammerAdam Keys
 
CS 112 PA #4Like the previous programming assignment, this assignm.docx
CS 112 PA #4Like the previous programming assignment, this assignm.docxCS 112 PA #4Like the previous programming assignment, this assignm.docx
CS 112 PA #4Like the previous programming assignment, this assignm.docxannettsparrow
 
What's new in Ruby 2.0
What's new in Ruby 2.0What's new in Ruby 2.0
What's new in Ruby 2.0Kartik Sahoo
 
Rapid web development, the right way.
Rapid web development, the right way.Rapid web development, the right way.
Rapid web development, the right way.nubela
 
Hipster FP code harder to maintain because it actively removes domain knowledge
Hipster FP code harder to maintain because it actively removes domain knowledge Hipster FP code harder to maintain because it actively removes domain knowledge
Hipster FP code harder to maintain because it actively removes domain knowledge Philip Schwarz
 
Postobjektové programovanie v Ruby
Postobjektové programovanie v RubyPostobjektové programovanie v Ruby
Postobjektové programovanie v RubyJano Suchal
 

Semelhante a Playfulness at Work (20)

Real World Haskell: Lecture 1
Real World Haskell: Lecture 1Real World Haskell: Lecture 1
Real World Haskell: Lecture 1
 
Python Homework Help
Python Homework HelpPython Homework Help
Python Homework Help
 
RSpec 3.0: Under the Covers
RSpec 3.0: Under the CoversRSpec 3.0: Under the Covers
RSpec 3.0: Under the Covers
 
The Ring programming language version 1.7 book - Part 43 of 196
The Ring programming language version 1.7 book - Part 43 of 196The Ring programming language version 1.7 book - Part 43 of 196
The Ring programming language version 1.7 book - Part 43 of 196
 
Uses & Abuses of Mocks & Stubs
Uses & Abuses of Mocks & StubsUses & Abuses of Mocks & Stubs
Uses & Abuses of Mocks & Stubs
 
Fancy talk
Fancy talkFancy talk
Fancy talk
 
Solving the Riddle of Search: Using Sphinx with Rails
Solving the Riddle of Search: Using Sphinx with RailsSolving the Riddle of Search: Using Sphinx with Rails
Solving the Riddle of Search: Using Sphinx with Rails
 
Creating your own Abstract Processor
Creating your own Abstract ProcessorCreating your own Abstract Processor
Creating your own Abstract Processor
 
The Essential Perl Hacker's Toolkit
The Essential Perl Hacker's ToolkitThe Essential Perl Hacker's Toolkit
The Essential Perl Hacker's Toolkit
 
NoSQL and SQL Anti Patterns
NoSQL and SQL Anti PatternsNoSQL and SQL Anti Patterns
NoSQL and SQL Anti Patterns
 
Ruby -the wheel Technology
Ruby -the wheel TechnologyRuby -the wheel Technology
Ruby -the wheel Technology
 
The Holistic Programmer
The Holistic ProgrammerThe Holistic Programmer
The Holistic Programmer
 
CS 112 PA #4Like the previous programming assignment, this assignm.docx
CS 112 PA #4Like the previous programming assignment, this assignm.docxCS 112 PA #4Like the previous programming assignment, this assignm.docx
CS 112 PA #4Like the previous programming assignment, this assignm.docx
 
The Bund language
The Bund languageThe Bund language
The Bund language
 
Lightning talk- testing
Lightning talk- testingLightning talk- testing
Lightning talk- testing
 
What's new in Ruby 2.0
What's new in Ruby 2.0What's new in Ruby 2.0
What's new in Ruby 2.0
 
Rapid web development, the right way.
Rapid web development, the right way.Rapid web development, the right way.
Rapid web development, the right way.
 
Hipster FP code harder to maintain because it actively removes domain knowledge
Hipster FP code harder to maintain because it actively removes domain knowledge Hipster FP code harder to maintain because it actively removes domain knowledge
Hipster FP code harder to maintain because it actively removes domain knowledge
 
Postobjektové programovanie v Ruby
Postobjektové programovanie v RubyPostobjektové programovanie v Ruby
Postobjektové programovanie v Ruby
 
lab4_php
lab4_phplab4_php
lab4_php
 

Mais de Erin Dees

Logic Lessons That Last Generations
Logic Lessons That Last GenerationsLogic Lessons That Last Generations
Logic Lessons That Last GenerationsErin Dees
 
How 5 people with 4 day jobs in 3 time zones enjoyed 2 years writing 1 book
How 5 people with 4 day jobs in 3 time zones enjoyed 2 years writing 1 bookHow 5 people with 4 day jobs in 3 time zones enjoyed 2 years writing 1 book
How 5 people with 4 day jobs in 3 time zones enjoyed 2 years writing 1 bookErin Dees
 
How 5 people with 4 day jobs in 3 time zones enjoyed 2 years writing 1 book
How 5 people with 4 day jobs in 3 time zones enjoyed 2 years writing 1 bookHow 5 people with 4 day jobs in 3 time zones enjoyed 2 years writing 1 book
How 5 people with 4 day jobs in 3 time zones enjoyed 2 years writing 1 bookErin Dees
 
A jar-nORM-ous Task
A jar-nORM-ous TaskA jar-nORM-ous Task
A jar-nORM-ous TaskErin Dees
 
Cucumber meets iPhone
Cucumber meets iPhoneCucumber meets iPhone
Cucumber meets iPhoneErin Dees
 

Mais de Erin Dees (6)

Logic Lessons That Last Generations
Logic Lessons That Last GenerationsLogic Lessons That Last Generations
Logic Lessons That Last Generations
 
How 5 people with 4 day jobs in 3 time zones enjoyed 2 years writing 1 book
How 5 people with 4 day jobs in 3 time zones enjoyed 2 years writing 1 bookHow 5 people with 4 day jobs in 3 time zones enjoyed 2 years writing 1 book
How 5 people with 4 day jobs in 3 time zones enjoyed 2 years writing 1 book
 
How 5 people with 4 day jobs in 3 time zones enjoyed 2 years writing 1 book
How 5 people with 4 day jobs in 3 time zones enjoyed 2 years writing 1 bookHow 5 people with 4 day jobs in 3 time zones enjoyed 2 years writing 1 book
How 5 people with 4 day jobs in 3 time zones enjoyed 2 years writing 1 book
 
A jar-nORM-ous Task
A jar-nORM-ous TaskA jar-nORM-ous Task
A jar-nORM-ous Task
 
Cucumber meets iPhone
Cucumber meets iPhoneCucumber meets iPhone
Cucumber meets iPhone
 
Yes, But
Yes, ButYes, But
Yes, But
 

Último

A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????blackmambaettijean
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 

Último (20)

A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 

Playfulness at Work

  • 1. (Nothing says “playful” like a broken printing press from the 1840s.)
  • 2. playfulness at work a real serious message™ with Ruby as the medium Ian Dees / @undees Hi, I’m Ian. I’m here to talk about playfulness at work, and how that relates to Ruby.
  • 3. 1. playfulness in the workplace... 2. ...or the way playfulness works? “Playfulness at Work”—does that mean “bringing play into the workplace” or “the way playfulness works?”
  • 4. yes Both, actually. I’ll get into the strange arc of this talk in a moment.
  • 5. first, a word of thanks But first, I’ve got two groups of people to thank.
  • 6. our organizers Ben Bleything Shane Becker First, to our organizers Ben and Shane, thank you for putting this whole thing together.
  • 7. our hosts Seattle.rb Second, to our host city and its Rubyists, thank you for having us here and for making so much great software.
  • 8. Seriously—these folks have made tons of useful software: just look at it all!
  • 9. their stuff will help your stuff flog flay heckle ... and much more! I’ll just highlight a couple of seattle.rb libraries here.... flog and flay report trouble spots in your code: methods that are too long or too similar; that kind of thing. heckle inserts bugs into your code and makes sure each bug results in a failing test case. If you’ve never run these before, catch me in the hallway later and I’ll embarrass myself by running them on my own code for you.
  • 10. Okay, on to the topic at hand. I make oscilloscopes. There’s something gratifying about making something physical that lets you see into an invisible world.... But what does that have to do with Ruby?
  • 11. why this talk? In other words, why this talk? Well, it turns out that even in a big organization like the one where I work, there are scattered pockets of Ruby resistance against the C++ empire.
  • 12. why Ruby? Why is that? Aren’t we supposed to be writing embedded software here? Close. As Rich Kilmer reminded us yesterday, what we’re supposed to do is create something that solves a problem for someone. That might mean embedded code, a web front end for some engineering data, a one-off shell script, a document, or nothing at all.
  • 13. (“Nothing at all... nothing at all....”)
  • 14. Anyway.... On those days when we need to munge some data or glue a couple of programs together, Ruby comes to the rescue.
  • 15. why bother? There’s always a temptation is to follow the path of least acceleration and just do what the organization thinks it wants to do. Fighting that temptation keeps our creative impulses sharp— paradoxically resulting in our doing a better job than if we’d just done what was asked or expected of us.
  • 16. why this talk? why bother? why Ruby? why? why? why? So, all these questions seem like they’re leading somewhere.
  • 17. _why Does anyone remember why the lucky stiff’s 2004 essay, “Wearing Ruby Slippers to Work?”
  • 18. It was about sneaking Ruby into work through the back door, using it to get little scripting tasks done.
  • 19. what’s changed? we can walk in through the front door now! Stealth was the only option back then. We had to prove ourselves with any unknown technology. And now... Ruby is in the top twenty languages, according to that chart we saw yesterday. We’ve got a little more leeway to storm the workplace and use Ruby when it suits the task at hand.
  • 20. 1. dealing with crusty data formats and protocols ...in a lighthearted way I’d like to talk about a few of these kinds of those situations now, mainly as an excuse to bring up some Ruby libraries you may find useful.
  • 21. 2. scripting other people's software ...whether they know it or not ...
  • 22. 3. sharing your code with co-workers ...without annoying them too much ...
  • 23. 4. deploying your software ...to honest-to-goodness paying customers! ...
  • 25. 1. dealing with crusty data formats and protocols ...in a lighthearted way First, data parsing. I work at a bigco, where we’ve seen ad hoc data formats come and go. For example, you might hear, “That file full of test logs we just sort of started cutting and pasting into… can you figure out how many times the Foo subsystem called into the Bar module?” The goal: get the answer quickly with your sanity intact.
  • 26. introducing my own ad hoc format... Just to get a taste of how easy it is to wrangle arbitrary data in Ruby, I’ll introduce a toy format and then show a few lines of code to parse it.
  • 27. TaskParchment (with apologies to TaskPaper) - Invent my own crufty data format - Start with a good format @done - Ruin it @badidea @done - ??? - Profit! The format will be based on TaskPaper, which seems to be a reasonable format for to-do lists. Except I’m going to take everything cool out of it, so we can meaningfully talk about it in a few slides. So, it’s like TaskPaper, but thinner: ergo, TaskParchment.
  • 28. kschiess’s Parslet DSL https://github.com/kschiess/parslet We’ll use the Parslet library for picking apart the data. It’s based on the idea of Parsing Expression Grammars—regular expressions attached to bits of code. Sounds like a hack, but there’s actually a solid theoretical foundation for it.
  • 29. describe TaskParchment::Parser do before { @parser = TaskParchment::Parser.new } it 'parses a task' do input = "- Task @taggedn" expected = {:desc=>"Task ", :tags=>[{:tag => "tagged"}]} @parser.task_line.parse(input).must_equal expected end # ... end The first stage of parsing is to get the text into some kind of in-memory representation of a tree. Parslet’s representation is a conglomeration of hashes and arrays. Here’s a first taste. Notice we’re using minitest (built into Ruby 1.9.2) to do our testing. We can invoke a single parsing rule at a time —in this case the yet-to-be-written “task_line” rule. This is a big help for testing.
  • 30. require 'parslet' module TaskParchment class Parser < Parslet::Parser # Example: # # - This is a task @tag # rule(:task_line) { begin_task >> description.as(:desc) >> tags.maybe >> newline } # ... end end Here’s the implementation of that rule. See how fluidly Parslet reads: a single line of a task consists of punctuation, followed by a description, possibly some tags, and finally a newline. Each of these components is itself a rule. Let’s define those next.
  • 31. rule(:begin_task) { str('- ') } rule(:description) { desc_char.repeat(1) } rule(:desc_char) { match('[^@n]') } rule(:newline) { str("n") } These are the the basic building blocks of a task. Notice that we can match exact strings or regular expressions.
  • 32. rule(:tags) { tag.repeat(1).as(:tags) } rule(:tag) { begin_tag >> tag_char.repeat(1).as(:tag) >> space.maybe } Here’s how we define tags for a task. Notice the “as(:tag)” marker. This is a signal to Parslet to discard all the other stuff (spaces and punctuation) and just keep the tag name in the final in- memory tree.
  • 33. rule(:begin_tag) { str('@') } rule(:tag_char) { match('[^@ n]') } rule(:space) { str(' ') } Here are the last few pieces of punctuation we haven’t defined yet.
  • 34. $ ruby test_task_parchment.rb Loaded suite test_task_parchment Started . Finished in 0.001903 seconds. 1 tests, 1 assertions, 0 failures, 0 errors, 0 skips Test run options: --seed 23512 Now our tests pass.
  • 35. whew! Let’s take a breath for a sec, before jumping into tasks that contain subtasks.
  • 36. it 'parses a terrible plan into a tree' do input = <<HERE - Invent my own crufty data format - Start with a good format @done - Ruin it @badidea @done - ??? - Profit! HERE # ... end Here’s the original TaskParchment string we wanted to parse.
  • 37. it 'parses a terrible plan into a tree' do # ... expected = [{:desc=>"Invent my own crufty data format", :subtasks=> [{:desc=>"Start with a good format ", :tags=>[{:tag=>"done"}], :subtasks=>[]}, {:desc=>"Ruin it ", :tags=>[{:tag=>"badidea"}, {:tag=>"done"}], :subtasks=>[]}]}, {:desc=>"???", :subtasks=>[]}, {:desc=>"Profit!", :subtasks=>[]}] # ... end Here’s the in-memory representation we want.
  • 38. it 'parses a terrible plan into a tree' do # ... @parser.parse(input).must_equal expected end And here’s the test assertion.
  • 39. def task_line_indented_at(indent) space.repeat(indent, indent) >> task_line end def task_indented_at(indent) parser = task_line_indented_at(indent) parser >>= task_indented_at(indent + 2). repeat(0).as(:subtasks) unless indent > 20 parser end rule(:list) { task_indented_at(0).repeat(0) } root(:list) Believe it or not, we can do this with just a couple more parser rules. We’ll define these as functions that take an indentation parameter. We’ll cap the indentation at 20 to prevent an infinite regression in our parser (quite easy to do in PEG parsers). That “root” bit at the bottom gives the starting rule for parsing an entire document.
  • 40. $ ruby test_task_parchment.rb Loaded suite test_task_parchment Started .. Finished in 0.009532 seconds. 2 tests, 2 assertions, 0 failures, 0 errors, 0 skips Test run options: --seed 63924 Two passing tests.
  • 41. yay! From here, Parslet has other tools for transforming those raw arrays and hashes into your own Ruby classes. But let’s prepare to jump to another topic now. The lesson here is that we could have rolled our own parser and had less fun (not to mention poorer syntax error reporting). Instead, we used Ruby as an excuse for experimenting with a peculiar parsing technique.
  • 42. 2. scripting other people's software ...whether they know it or not Next up: scripting. One day, you may be asked to write a data converter for a nasty binary format that’s undocumented, unsupported, and has no developer hooks in the only software that knows how to read it. You might try to reverse-engineer their API, or you might get nasty and just drive their software through the user interface.
  • 43. something silly Rather than shame the vendor of this particular piece of software, I’d rather just go off in a different direction and do something silly with FFI in Ruby. We’re going to write a script that renders a black- and-white picture in the least efficient way possible: by clicking it pixel-by-pixel with the mouse.
  • 44. chunky_png https://github.com/wvanbergen/chunky_png First, we need to crack open the picture and find the dark pixels. To do this, we’ll use the excellent chunky_png, a pure-Ruby PNG decoder.
  • 45. require 'chunky_png' image = ChunkyPNG::Image.from_file filename shadows = [] (0...image.height).each do |y| (0...image.width).each do |x| gray = ChunkyPNG::Color.grayscale_teint image[x, y] shadows << [x, y] if gray < 128 end end This code will build an array of the x/y locations we’ll need to click with the mouse.
  • 46. FFI https://github.com/ffi/ffi To grab hold of the platform-specific mouse API, we’re going to use FFI, the foreign function interface library that started in the Rubinius project and is now available in at least three other Ruby implementations.
  • 47. require 'ffi' module User32 extend FFI::Library ffi_lib 'user32' ffi_convention :stdcall MOUSEEVENTF_LEFTDOWN = 0x0002 MOUSEEVENTF_LEFTUP = 0x0004 attach_function :SetCursorPos, [:long, :long], :int attach_function :mouse_event, [:long] * 5, :void end To simulate a mouse click on this particular platform, you need to import two functions: one to position the mouse, and one to click it. Notice how the FFI functions look vaguely like C declarations.
  • 48. include User32 def mouse_click(x, y) SetCursorPos x, y mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 end Here’s how to actually simulate the click.
  • 49. shadows.sort_by { rand }.each do |x, y| mouse_click 100 + x, 100 + y sleep 0.05 end And here’s how we’ll draw the picture. To save a bunch of window-management code in these examples, we’ll just assume the drawing app is maximized. We’ll give it a margin of 100 pixels each way to make room for the toolbar.
  • 50. win_gui https://github.com/arvicco/win_gui The code is even simpler if you use win_gui, a gem that provides FFI wrappers for common Windows GUI calls.
  • 51. require 'win_gui' w = WinGui::Window.find :title => /- Paint$/ shadows.sort_by { rand }.each do |x, y| w.click :point => [100 + x, 100 + y] sleep 0.05 end Here’s the entire drawing routine in win_gui. We don’t need any of the FFI setup stuff any more, or the definition of a mouse click.
  • 52. In the real-life story that inspired this example, we were able to convert the screen scraper to C with basically a few macros in Emacs. The program did its job, and we abandoned it as soon as we could to move on to more worthy projects.
  • 53. 3. sharing your code with co-workers ...without annoying them too much Now, I’d like to talk about deployment. Once you’ve written that brilliant text parser, data converter, or web front end, how do you share it with your co-workers who may be on an IT-supplied Windows XP box?
  • 54. running from source The simplest way to share code internally is to just hand your co-worker a .rb file and be done with it.
  • 55. 2005 “just download Ruby from here” In 2005, that worked pretty well. You could just tell people, “Download the all-in-one Ruby installer from here, save this .rb file onto your machine, and run it.”
  • 56. 2008 MSWin MinGW 1.8 easy scary 1.9 hard scary Then life got complicated. Not only were there there two versions of Ruby, there were two alternative Windows builds of Ruby. If your program depended on a gem that had C code in it, the compiled code would only work in one particular Ruby variant.
  • 57. 2010 MSWin MinGW 1.8 gone easy 1.9 gone easy The story is much better now. MinGW has emerged as the winner of the C compiler battle, as far as Ruby is concerned. And the Windows folks have found a way to deal with C code that works in both 1.8 and 1.9.
  • 58. RubyInstaller https://github.com/oneclick/rubyinstaller It’s all thanks to Luis Lavena’s RubyInstaller, which installs Ruby onto your system and has an optional dev kit that pretty much makes “gem install” work the same on Windows as it does on UNIX. You still have to worry about dependencies, but this is a huge step forward.
  • 59. self-contained executables Another approach is to build binaries for people that include enough Ruby for them to run your program without an extra installation step.
  • 60. OCRA https://github.com/larsch/ocra Windows Rubyists have OCRA, the One-Click Ruby Application builder. This will bundle up your Ruby program with a copy of the interpreter and any gems you need into a single .exe file.
  • 61. what shall we deploy? Let’s pick an app to serve as a guinea pig, so we can show a few of these techniques.
  • 62. holman’s Boom app http://github.com/holman/boom In keeping with the Hubot chat robot from yesterday, let’s show something that appears to have made Zach Holman the fastest draw in Campfire: a command-line clipboard manager called Boom. (Pronounce it “bewwwwwm.”)
  • 63. ...
  • 64. require 'boom' Boom::Command.execute(*ARGV) C:boom> ocra boom.rb boom.exe This app has a gem dependency (on json-pure). As long as that’s installed on our system, OCRA will find it. We just write a trivial .rb file to launch Boom, point OCRA at it, and we get a working exe.
  • 65. Warbler https://github.com/nicksieger/warbler I’m partial to JRuby myself, because it makes it easy to use gems that have a compiled component. JRuby binary gems (such as ActiveRecord database adapters) don’t have to be compiled for each specific platform. Warbler is a JRuby build tool that looks at your app’s Gemfile and creates a runnable .jar file that anyone with Java installed can run.
  • 66. # bin/boom require 'boom' Boom::Command.execute(*ARGV) # Gemfile source :rubygems gem 'boom' gem 'httparty' $ bundle $ warble jar boom.jar The workflow with Warbler is nearly the same as with OCRA. Warbler keys off your project’s Gemfile, rather than watching your require calls.
  • 67. 4. deploying your software ...to honest-to-goodness paying customers! The techniques we’ve seen so far have been good enough for sharing code with co-workers, and perhaps a few customers (at work, we’ve put OCRA-based binaries on our website for end users). At some point, though, you begin to wonder, “Does this app need an installer?”
  • 68. RailsInstaller https://github.com/railsinstaller If you wanted to build a full installer for a Ruby app, you could start with the RubyInstaller project and then add some installation steps that contain your own Ruby code and dependencies. That’s pretty much what the RailsInstaller project from Engine Yard does. It installs Ruby, Rails, Git, and some other dependencies onto a Windows machine.
  • 69. BoomInstaller what would it take? As a thought experiment, what would it take to turn the RailsInstaller into a BoomInstaller?
  • 70. # railsinstaller.yml --- :gems: :name: Gems :title: Ruby Gems :category: gems :list: - boom :boom: :name: Boom :title: Text snippets :category: gem It’s pretty easy, as it turns out. Dr. Nic and crew have made their installation recipes configurable. You’d just need to add the Boom gem to a YAML config file.
  • 71. # actions.rb module RailsInstaller def self.build! components = [ BSDTar, SevenZip, DevKit, Ruby187, ] components.each do |package| section package.title download package extract package end link_devkit_with_ruby end end Then you’d need to shorten the list of installed components (unless you want to deploy Git and SQL bindings along with Boom).
  • 72. ;railsinstaller.iss -#define InstallerName "RailsInstaller" +#define InstallerName "BoomInstaller" -DefaultDirName={sd}RailsInstaller +DefaultDirName={sd}BoomInstaller -VersionInfoDescription=Rails development environment installer... +VersionInfoDescription=Boom installer for Windows ;... The ugliest part is editing the Inno Setup script. It’s mostly just grepping through for each occurrence of Rails and deciding whether or not to replace it with Boom.
  • 73. licenses and artwork You’d also want to change licenses and artwork....
  • 74. licenses and artwork ...to something for your app.
  • 75. BoomInstaller https://github.com/undees/railsinstaller-windows/ tree/boom You can see the changes I made in the “boom” branch of my fork of RailsInstaller.
  • 76. That wraps up the concrete portion of the program. Let’s zoom back out to the big questions of why we’re doing this. Image courtesy http://www.flickr.com/photos/chrisbevan/2476405
  • 77. playfulness For me, and I suspect for many of you, Ruby imparts a sense of playfulness. And in the next few minutes, I’m going to prove that one can carefully cherry-pick a few items from Brain Science™ to support the importance of play at work.
  • 78. Brain Science™ on play Stuart Brown Tim Brown First, here’s a pair of TED talks on creative play. TED is the conference speaker’s ideal substitute for research, by the way. Stuart Brown says, “Nothing lights up the brain like play,” and then proceeds to tell us how that works, biologically speaking. Tim Brown explains how playfulness improves the performance of entire teams.
  • 79. Next, there’s material I was actually exposed to as a kid... on vinyl. It’s about how to harness the huge parallel processing unit in our heads to solve problems in ways we didn’t expect. (See also Andy Hunt’s Pragmatic Thinking and Learning). The gist is that play unlocks your brain’s problem- solving engine.
  • 80. Finally, there’s I Hate People, an airplane reading book that sounds like it’s going to be Dilbert come to life, but does a Randy-Pausch-style head fake into shaping your career. The authors talk about the notion of being a Soloist, someone who does creative work with a supportive ensemble at work. tl;dr: by their scrappy entrepreneurship, Soloists drag their organizations kicking and screaming to success.
  • 81. Which brings us here. Over the past two days, you’ve heard how crucial it is to keep yourself engaged and challenged in your work. You’ve heard about the importance of community in promoting that virtuous cycle that feeds success into success. My hope is that Cascadia Ruby Conf doesn’t end here. (We haven’t had lunch yet!) My hope is that we continue to connect, to support one another, to stay playful, and to keep making great things. Long live Cascadia Ruby Conf. Cheers.
  • 82. slides and code https://github.com/undees/cascadiaruby Slides and code will be available at this address (eventually).