SlideShare uma empresa Scribd logo
1 de 177
Baixar para ler offline
The Enterprise
                              Strikes Back
                              Burke    Stefan
                              Libbey   Penner




Wednesday, 23 November, 11
Burke    Stefan
                             Libbey   Penner




Wednesday, 23 November, 11
Burke Libbey   Stefan Penner
                         @burkelibbey   @stefanpenner




Wednesday, 23 November, 11
Burke Libbey   Stefan Penner
                         @burkelibbey   @stefanpenner




Wednesday, 23 November, 11
Burke Libbey   Stefan Penner
                         @burkelibbey   @stefanpenner




Wednesday, 23 November, 11
Overview
           • Core concepts
           • Ruby on the JVM (and the CLR, sort of)
           • Data
           • Integration
           • Deployment
           • Sysadmin
           • The Cloud
Wednesday, 23 November, 11
Ruby’s weaknesses


                       • Poor performance
                       • Type system sometimes causes
                             headaches in large codebases

                       • No compiler to catch certain bugs
                             But your tests catch these, right?




Wednesday, 23 November, 11
Why ruby is slow


                 • Late method lookup
                 • Lots of context tracking to allow for eval
                 • Stop-the-world Mark & Sweep GC
                 • Runtime modification of code



Wednesday, 23 November, 11
Ruby’s strengths


                       • Developing working code quickly
                       • Reducing incidental complexity
                             Especially when best practices are adhered to


                       • Ease of developing powerful libraries
                             and succinct DSLs



Wednesday, 23 November, 11
Uniform Access Principle
                             All services o ered by a
                             module should be available
                             through a uniform notation,
                             which does not betray whether
                             they are implemented through
                             storage or through
                             computation.


                               - Bertrand Meyer




Wednesday, 23 November, 11
Two Rules


              • Everything is an object
              • Objects expose methods and only methods




Wednesday, 23 November, 11
Wednesday, 23 November, 11
</background>




Wednesday, 23 November, 11
Ruby             Java




                         + Productive   + Not Scary
                         - Scary        - Less productive



Wednesday, 23 November, 11
Ruby in Java




                              + Not Scary
                              + Productive



Wednesday, 23 November, 11
http://jruby.org


Wednesday, 23 November, 11
• Full ruby implementation on the JVM
                 • Access to both ruby and Java libraries
                 • Can be deployed to existing Java
                        infrastructure




Wednesday, 23 November, 11
The many flavours of ruby
                 • MRI (and YARV)
                 • JRuby
                 • IronRuby
                 • MacRuby
                 • Rubinius
                 • ...and several more...

Wednesday, 23 November, 11
java.lang.System.out.println("Hello World")




Wednesday, 23 November, 11
The Magic Sauce



                              require 'java'
                                (contains up to 30% midichlorians)




Wednesday, 23 November, 11
Calling Java from ruby

  f = javax.swing.JFrame.new
  f.getContentPane.add(javax.swing.JLabel.new("Hello World"))
  close_operation = javax.swing.JFrame::EXIT_ON_CLOSE
  f.setDefaultCloseOperation(close_operation)
  f.pack
  f.setVisible(true)




Wednesday, 23 November, 11
Impedance Mismatch

  f = javax.swing.JFrame.new
  f.getContentPane.add(javax.swing.JLabel.new("Hello World"))
  close_operation = javax.swing.JFrame::EXIT_ON_CLOSE
  f.setDefaultCloseOperation(close_operation)
  f.pack
  f.setVisible(true)



                             Let’s break this down.


Wednesday, 23 November, 11
Impedance Mismatch
                  “Getters” and “Setters” are non-idiomatic in ruby.
  f = javax.swing.JFrame.new
  f.getContentPane.add(javax.swing.JLabel.new("Hello World"))
    getContentPane
  close_operation = javax.swing.JFrame::EXIT_ON_CLOSE
  f.setDefaultCloseOperation(close_operation)
  f.pack
  f.setVisible(true)

                   snake_case is generally preferred to CamelCase




Wednesday, 23 November, 11
Impedance Mismatch
                     JavaBean properties can be accessed like this:
  f = javax.swing.JFrame.new
  f.content_pane.add(javax.swing.JLabel.new("Hello World"))
  close_operation = javax.swing.JFrame::EXIT_ON_CLOSE
  f.setDefaultCloseOperation(close_operation)
  f.pack
  f.setVisible(true)
                                  (UA P in action!)
             “get” disappears, CamelCase changes to snake_case




Wednesday, 23 November, 11
Impedance Mismatch
                                “set” is replaced by “=”

  f = javax.swing.JFrame.new
  f.content_pane.add(javax.swing.JLabel.new("Hello World"))
  close_operation = javax.swing.JFrame::EXIT_ON_CLOSE
  f.default_close_operation = close_operation
  f.pack
  f.visible = true
                             “setDefaultCloseOperation(x)”
                                       becomes
                             “default_close_operation = x”


Wednesday, 23 November, 11
Ugliness Abounds

  f = javax.swing.
      javax.swing.JFrame.new
  f.content_pane.add(javax.swing.JLabel.new("Hello World"))
                     javax.swing.
  close_operation = javax.swing.
                    javax.swing.JFrame::EXIT_ON_CLOSE
  f.default_close_operation = close_operation
  f.pack
  f.visible = true



                              Namespaces everywhere!


Wednesday, 23 November, 11
Ugliness Abounds
  java_import 'javax.swing.JFrame'
  java_import 'javax.swing.JLabel'
  f = JFrame.new
  f.content_pane.add(JLabel.new("Hello World"))
                     JLabel.new
  close_operation = JFrame::EXIT_ON_CLOSE
  f.default_close_operation = close_operation
  f.pack
  f.visible = true



                  java_import adds classes to a ruby context


Wednesday, 23 November, 11
100% Rubified™

          java_import 'javax.swing.JFrame'
          java_import 'javax.swing.JLabel'

          JFrame.new.tap do |f|
            f.content_pane.add JLabel.new("Hello World")
            f.default_close_operation = JFrame::EXIT_ON_CLOSE
            f.pack
            f.visible = true
          end




Wednesday, 23 November, 11
Method Rubification™



                 • In general, CamelCase Java methods
                        can optionally be transliterated to snake
                        case.




Wednesday, 23 November, 11
Method Rubification™


                             Java   System.currentTimeMillis()
                             Ruby   System.current_time_millis




Wednesday, 23 November, 11
Seriously though, not
                                                       actually trademarked.



                    Method Rubification™


                             Java   person.getName()
                             Ruby   person.name




Wednesday, 23 November, 11
Someone should
                                                          get on that.



                    Method Rubification™


                             Java   person.setAge(42)
                             Ruby   person.age = 42




Wednesday, 23 November, 11
Method Rubification™
       FALSE!              TRUE!

                             Java   person.isJedi()
                             Ruby   person.jedi?




Wednesday, 23 November, 11
Is ruby an acceptable
                               Java?            (http://bit.ly/pfNluA)




                 • Most Java code can literally be written
                        as ruby with few high-level changes.

                 • A more relaxed type system and syntax
                        often has productivity benefits.




Wednesday, 23 November, 11
Exhibit A
                             // interfaces = HashMap{ label => NetworkInterface }
         Java                Collection c = interfaces.values();
                             Iterator itr = c.iterator();

                             while(itr.hasNext()) {
                               NetworkInterface interface = itr.next();
                               if (interface.isLoopback()) {
                                 return interface.getDisplayName();
                               }
                             }
                                                  VS.

                             # interfaces = {label => NetworkInterface}
        Ruby                 interfaces.values.find(&:loopback?).display_name




Wednesday, 23 November, 11
Exhibit A
                             // interfaces = HashMap{ label => NetworkInterface }
         Java                Collection c = interfaces.values();
                             Iterator itr = c.iterator();

                             while(itr.hasNext()) {
                               NetworkInterface interface = itr.next();
                               if (interface.isLoopback()) {
                                 return interface.getDisplayName();
                               }
                             }
                                                   VS.

                             # interfaces = {label => NetworkInterface}
        Ruby                 interfaces.values.find(&:loopback?).display_name
                                      1       2     345          67


                                   Only 7 characters of syntactic support!

Wednesday, 23 November, 11
“Are you suggesting I write
           all my Java in ruby?!”

                 • Not really...
                       • JRuby is much slower than Java
                             (doesn’t matter as often as you’d think)


                       • Ruby’s added expressiveness makes it
                             easier to shoot yourself in the foot.
                             (or, in fact, to lazily clone an infinite number of your feet every
                             planck length between your gun and your target)




Wednesday, 23 November, 11
“Are you suggesting I write
           all my Java in ruby?!”
                 • ...but maybe sometimes.
                 • One possibility:
                       • Encode high-level logic in expressive
                             and concise ruby code

                       • Supporting code in fast, safe Java
                       • Mix and match as appropriate

Wednesday, 23 November, 11
Ruby as Glue


                       • Ruby is great for:
                             • wiring existing codebases together
                             • other miscellaneous tasks



Wednesday, 23 November, 11
Perl      The original
                               “Swiss Army Knife”




Wednesday, 23 November, 11
Perl   Pretty much mean
                                the same thing.


                               • “glue”
                               • “duct tape”
                               • “swiss army knife”



Wednesday, 23 November, 11
Perl   Ruby
Wednesday, 23 November, 11
Subcategories of “Glue”



                             • Wiring stu together
                             • Sysadmin tasks




Wednesday, 23 November, 11
Wiring stu together



                 • There’s a lot we could cover here, but:




Wednesday, 23 November, 11
Nokogiri



                 • An extremely user-friendly XML library
                 • fast! (wraps libxml2)




Wednesday, 23 November, 11
Nokogiri
        require 'open-uri'
        require 'nokogiri'
        html = open("http://slashdot.org").read
        doc = Nokogiri::XML(html)
        (doc/".story a").each do |link|
          puts "#{link.text} (#{link.attr('href')})"
        end

        # Britain's Broadband Censors: a Bunch of Students (//yro.slashdot...
        # ...




Wednesday, 23 November, 11
Don’t do this.

  (Nokogiri::XML(open("http://slashdot.org").read)/".story a").each{|a|puts
  "#{a.text} (#{a.attr("href")})"}




Wednesday, 23 November, 11
Sysadmin with Ruby



                 • Nice system APIs
                        (quite similar to perl’s)


                 • System provisioning libraries/DSLs




Wednesday, 23 November, 11
Provisioning systems


                              • Puppet
                              • Chef
                              • Vagrant



Wednesday, 23 November, 11
Puppet
                 • Describe system, and puppet sets it up
                 • Nontrivial, but the general idea is:
                       • I want mysql
                       • I want nginx < 0.8
                       • I want this cron job: “....”
                       • Go.
                                      http://puppetlabs.com/

Wednesday, 23 November, 11
Puppet
    class postgres-server {
      package { postgresql-server:
         ensure => latest
      }
      group { postgres: gid => 26 }
      user { postgres:
        comment => "PostgreSQL Server",
        uid => 26,
        gid => 26,
        home => "/var/lib/pgsql",
        shell => "/bin/bash"
      }
      service { postgresql:
         running => true,
         pattern => "/usr/bin/postmaster",
         require => package["postgresql-server"]
      }
    }

Wednesday, 23 November, 11
Puppet



                 • Fantastic for defining a reproducible
                        production environment




Wednesday, 23 November, 11
Chef


                 • Same idea as puppet
                 • Somewhat less powerful
                 • Slightly more approachable to most
                        ruby developers



                                 http://www.opscode.com/chef/
Wednesday, 23 November, 11
Chef
        package "sudo" do
          action :upgrade
        end

        template "/etc/sudoers" do
          source "sudoers.erb"
          mode 0440
          owner "root"
          group "root"
          variables(
            :sudoers_groups => node['authorization']['sudo']['groups'],
            :sudoers_users => node['authorization']['sudo']['users'],
            :passwordless => node['authorization']['sudo']['passwordless']
          )
        end




Wednesday, 23 November, 11
Puppet        Chef

              Configuration Language         custom         ruby

                             Targeted at   production   production

                      “Powerfulness”          Lots      Mostly lots

                               Verdict       Good        Di erent

                             Written in      ruby          ruby




Wednesday, 23 November, 11
Vagrant

                 • Uses puppet and/or chef
                 • End product is a virtual machine for
                        development use

                 • Consistent system for all developers, per
                        project



Wednesday, 23 November, 11
Vagrant



                 • If you use puppet or chef, vagrant lets
                        you test production locally




Wednesday, 23 November, 11
Suggestions


                 • As a non-ruby-dev:
                       • Use puppet
                       • Consider vagrant



Wednesday, 23 November, 11
Suggestions


                 • As a ruby developer:
                       • Consider chef and puppet, use
                             whichever suits your taste and needs

                       • Consider vagrant



Wednesday, 23 November, 11
Databases



Wednesday, 23 November, 11
In the Real World,




Wednesday, 23 November, 11
In the Real World,

                               We have Data




Wednesday, 23 November, 11
In the Real World,

                               We have Data

                 Which lives in Databases



Wednesday, 23 November, 11
Databases Are Always
                            simple




Wednesday, 23 November, 11
All our data is
                               ALWAYS
                             in the same DBMS




Wednesday, 23 November, 11
Reality Check




Wednesday, 23 November, 11
Luckily
                               We have

                             ODBC + JDBC




Wednesday, 23 November, 11
Luckily
                               We have

                             ODBC + JDBC
                                +
                               Ruby
Wednesday, 23 November, 11
Ruby Gives you Options
                 • Active Record
                 • Sequel
                 • DataMapper
                 • more


Wednesday, 23 November, 11
Active Record
        Design pattern coined by Martin Fowler in
        “Patterns of enterprise application
        architecture”.

        Also, Ruby on Rails’s default ORM.

       • Lots of Power
       • Lots of Opinion
       • Might fight with you (for non-standard uses)
     https://github.com/rails/rails/tree/master/activerecord

Wednesday, 23 November, 11
Active Record Syntax (Raw)
      require 'active_record'

      ActiveRecord::Base.establish_connection({
         :adapter => 'mysql',
         :database => 'test_database',
         :username => 'tester',
         :password => 'test22'
      })

      connection = ActiveRecord::Base.connection

      connection.tables
      > ['users', 'products', 'ducks', 'oranges']

      users = []
      connection.execute('SELECT * FROM users').each_hash do |user|
        users << user
      end

      users
      > .... array of users, each user as a hash.

      users.first
      > { :id => 1, :username => 'stefan', :password => 'is_super_secure' }




Wednesday, 23 November, 11
Active Record Syntax (ORM)

    require 'active_record'

    ActiveRecord::Base.establish_connection({
       :adapter => 'mysql',
       :database => 'test_database',
       :username => 'tester',
       :password => 'test22'
    })

    # class <camel_case_singular_table_name> < ActiveRecord::Base
    class User < ActiveRecord::Base
      # if the table's name does not fit convention, it can be manually overridden.
      # table_name :users_table
    end

    User.first
    > #<User id: 2,          :name => 'stefan', :password => 'is_super_secure' >

    User.find(2)
    > #<User id: 2,          :name => 'stefan', :password => 'is_super_secure' >

    User.where(:name => 'stefan')
    > #<User id: 2, :name => 'stefan', :password => 'is_super_secure' >




Wednesday, 23 November, 11
Active Record Syntax (AREL)

    User.first
    > #<User id: 2,          :name => 'stefan', :password => 'is_super_secure' >

    User.find(2)
    > #<User id: 2,          :name => 'stefan', :password => 'is_super_secure' >

    User.where(:name => 'stefan')
    > #<User id: 2, :name => 'stefan', :password => 'is_super_secure' >

    User.where(:name => 'stefan').order('id ASC')
    > #<User id: 2, :name => 'stefan', :password => 'is_super_secure' >




Wednesday, 23 November, 11
Sequel
        Elegant Full featured database toolkit for ruby.
        • Supports a ton of DBMS’s
        • DSL
        • ORM


           http://sequel.rubyforge.org/

            Supports
            - ADO, Amalgalite, DataObjects, DB2, DBI, DO, Firebird, ibmdb, Informix,
            JDBC, MySQL, Mysql2, ODBC, OpenBase, Oracle, PostgreSQL, SQLite3,
            Swift, and tinytds



Wednesday, 23 November, 11
require "sequel"
                                              Sequel Example
         # connect to an in-memory database
         DB = Sequel.sqlite

         # create an items table
         DB.create_table :items do
           primary_key :id
           String :name
           Float :price
         end

         # create a dataset from the items table
         items = DB[:items]

         # populate the table
         items.insert(:name => 'abc', :price => rand * 100)
         items.insert(:name => 'def', :price => rand * 100)
         items.insert(:name => 'ghi', :price => rand * 100)

         # print out the number of records
         puts "Item count: #{items.count}"

         # print out the average price
         puts "The average price is: #{items.avg(:price)}"




Wednesday, 23 November, 11
Sequel ORM
        require "sequel"

        # connect to an in-memory database
        DB = Sequel.sqlite

        # create an items table
        DB.create_table :items do
          primary_key :id
          String :name
          Float :price
        end

        # create a dataset from the items table
        class Item < Sequel::Model(:items)
          # associations
          # validations
        end

        # populate the table
        Item.create(:name => 'abc', :price => rand * 100)
        Item.create(:name => 'def', :price => rand * 100)
        Item.create(:name => 'ghi', :price => rand * 100)

        # print out the number of records
        puts "Item count: #{Item.count}"

        # print out the average price
        puts "The average price is: #{Item.avg(:price)}"




Wednesday, 23 November, 11
Sequel ORM


                                 +
                               jRuby
                             ready out of the box



Wednesday, 23 November, 11
Sequel ORM


                                 +
                             IRONRuby
                              apparently works?



Wednesday, 23 November, 11
Case Study (Access)
      •      Access (top 2 solutions)

             •      Solution 1 (Cross Platform)

                   •         jRuby

                   •         JDBC

                   •         HXTT’s driver (www.hxtt.com)

                   •         Sequel

             •      Solution 2 (Windows Only)

                   •         Ruby

                   •         ADO via WIN32OLE

                   •         Sequel




Wednesday, 23 November, 11
Case Study (Access)




Wednesday, 23 November, 11
Case Study (Access)
                              1. Download jRuby
                                 http://jruby.org/




Wednesday, 23 November, 11
Case Study (Access)
                              1. Download jRuby
                                 http://jruby.org/


                              2. Install Sequel
                                  gem install Sequel




Wednesday, 23 November, 11
Case Study (Access)
                              1. Download jRuby
                                 http://jruby.org/


                              2. Install Sequel
                                  gem install Sequel


                              3. Download JDBC Access Driver
                                http://www.hxtt.com/access.html


Wednesday, 23 November, 11
Case Study (Access)
    require          'rubygems'
    require          'sequel'
    require          'sequel/adapters/jdbc'
    require          'sequel/jdbc_hxtt_adapter'
    require          '../Support/Access_JDBC40.jar'

    root = File.expand_path "../../", __FILE__
    path_to_db = root + "/Support/AccessThemeDemo.mdb"
    DB = Sequel.connect("jdbc:access:////#{path_to_db}")
    puts DB.tables

    class Notes < Sequel::Model(:Notes)
    end

    class ThemeImages < Sequel::Model(:tbl_ThemeImages)
    end

    class Users < Sequel::Model(:tbl_Users)
    end
Wednesday, 23 November, 11
ba-da-bing




Wednesday, 23 November, 11
But our new app
                         and our old database
                             have di erent
                         system requirements.



Wednesday, 23 November, 11
We Want Isolation




Wednesday, 23 November, 11
_
                               -Need
                             We Want Isolation




Wednesday, 23 November, 11
Power by.. Sinatra
                                                 Web DSL

                             get '/pictures' do
                               ['picture1','picture2','picture2']
                             end

                             post   '/pictures'     {}
                             put    '/pictures/:id' {}
                             delete '/pictures/:id' {}


                                          used at linkedIn
                http://engineering.linkedin.com/44/linkedin-app-end-end-jruby-frontier-and-voldemort


Wednesday, 23 November, 11
sooo... big deal?




Wednesday, 23 November, 11
RestServer


                 • any jdbc database into a restful json
                        service

                 • https://github.com/stefanpenner/restserver




Wednesday, 23 November, 11
Portability/Bundling

                 • Warbler
                   http://github.com/nicksieger/warbler

                 • single jar/war file
                 • compiled (if needed)



Wednesday, 23 November, 11
it’s an app!


Wednesday, 23 November, 11
Putting it all together (p1)
                             ScreenShotr
                                  download:
      https://github.com/stefanpenner/screenshotr/zipball/master


                     git@github.com:stefanpenner/screenshotr

Wednesday, 23 November, 11
Sorry, contrived
                                example!



Wednesday, 23 November, 11
anyways...
Wednesday, 23 November, 11
Java Gives Us
                                • Portability



                             Ruby Gives Us
                                • Happiness



Wednesday, 23 November, 11
ScreenShotr

                   Normally Annoying re: Portability

                 • screen capture
                 • GUI




                                                   but thx jRuby
Wednesday, 23 November, 11
Lets Shoot some Screens
      require 'java'

      java_import            'java.awt.Robot'
      java_import            'java.awt.Toolkit'
      java_import            'java.awt.Rectangle'
      java_import            'java.awt.Image'
      java_import            'java.awt.image.BufferedImage'
      java_import            'javax.imageio.ImageIO'

      screenRect = Rectangle.new(Toolkit.default_toolkit.getScreenSize())
      capture        = Robot.new.createScreenCapture(screenRect)

      ImageIO.write(capture,'jpg',java.io.File.new('some_tmp_file.jpg'))




Wednesday, 23 November, 11
Hold UP




Wednesday, 23 November, 11
Hold UP
                             java_import ?




Wednesday, 23 November, 11
Hold UP
                             java_import ?

            why not require?




Wednesday, 23 November, 11
Hold UP
                                     java_import ?

            why not require?
                   requiring classes just makes them discoverable later.




Wednesday, 23 November, 11
Hold UP
                                     java_import ?

            why not require?
                   requiring classes just makes them discoverable later.


           why not import?




Wednesday, 23 November, 11
Hold UP
                                     java_import ?

            why not require?
                   requiring classes just makes them discoverable later.


           why not import?
                    Rake defines import




Wednesday, 23 November, 11
Hold UP
                                     java_import ?

            why not require?
                   requiring classes just makes them discoverable later.


           why not import?
                    Rake defines import



                                                                           weird...
Wednesday, 23 November, 11
And fill some clipboards

   require 'java'

   java_import 'java.awt.Toolkit'
   java_import 'javax.imageio.ImageIO'

   ss = StringSelection.new(public_url)
        Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, nil)




Wednesday, 23 November, 11
upload to server
           gem install rest-client

           require 'rubygems'

           require 'rest-client'

           RestClient.post('http://../resource',
                                           :file => File.new('path/to/file'))




Wednesday, 23 November, 11
upload to server
           gem install rest-client

           require 'rubygems'

           require 'rest-client'

           RestClient.post('http://../resource',
                                           :file => File.new('path/to/file'))




Wednesday, 23 November, 11
<Insert Segue Here>



Wednesday, 23 November, 11
...and Vice Versa



            • We’ve done a lot of calling Java from ruby.
            • The reverse is possible as well.




Wednesday, 23 November, 11
...and Vice Versa

        import org.jruby.embed.InvokeFailedException;
        import org.jruby.embed.ScriptingContainer;

        // ...
        ScriptingContainer container = new ScriptingContainer();
        container.runScriptlet("puts "That's no Moon"");




                                http://en.wikipedia.org/wiki/Jruby
Wednesday, 23 November, 11
Testing Java with Ruby




                “i find your lack of
                         tests disturbing.”
Wednesday, 23 November, 11
Testing Java with Ruby

                 • JtestR is wonderful
                       • Includes most of ruby’s leading
                             testing libraries

                       • supports ant and maven
                       • easy to add to a project
                       • takes advantage of jruby/java bridge

Wednesday, 23 November, 11
JtestR Installation

             • Download jarfile from jtestr.codehaus.org
             • Add to classpath
             • Add a task to maven/ant
             • Create tests in ./test or ./spec
             • Run task


Wednesday, 23 November, 11
Example!
         import java.util.HashMap

         describe "An empty", HashMap do
           before :each do
             @hash_map = HashMap.new
           end

             it "accepts new entries" do
               @hash_map.put "foo", "bar"
               @hash_map.get("foo").should == "bar"
             end

           it "returns a keyset iterator that throws an exception on next" do
             proc do
               @hash_map.key_set.iterator.next
             end.should raise_error(java.util.NoSuchElementException)
           end
         end


Wednesday, 23 November, 11
BDD Any language

                               • Cucumber
                               • http://cukes.info




Wednesday, 23 November, 11
“i saw a city
                             in the clouds”




Wednesday, 23 November, 11
MYTH: Ruby can’t scale.




Wednesday, 23 November, 11
FACT: Ruby scales like a BOSS




Wednesday, 23 November, 11
FACT: Ruby scales like a BOSS
                             (because it has to)




Wednesday, 23 November, 11
Fog

                 • “The Ruby Cloud Services Library”
                 • Lets you upload to S3, provision
                        instances in EC2, set DNS records in
                        DNSimple...

                 • ...and much more.


Wednesday, 23 November, 11
Fog




      “
           • Chewbacca-approved.
               whargarblbgarblgr-

Wednesday, 23 November, 11
                                      ”
                             garblgragh
Fog




      “
           • Chewbacca-approved. (chewbaccaproved?)
               whargarblbgarblgr-

Wednesday, 23 November, 11
                                  garblgragh          ”
2.5 imperial tons of
                                  providers




Wednesday, 23 November, 11
(         )eh.
                             2.5 imperial tons of
                                         H
                                  providers




Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Sinatra Example


                             #config.ru
                             require './lib/screen_shotr/server'
                             run ScreenShotr::Server.new




Wednesday, 23 November, 11
require 'sinatra'
                             require 'fog'
                             require 'digest/sha1'




Wednesday, 23 November, 11
module ScreenShotr
  class Server < Sinatra::Base
    def storage
      #@storage ||= Fog::Storage.new({
      # :provider => 'AWS',
      # :aws_access_key_id => ACCESS_KEY_ID,
      # :aws_secret_access_key => SECRET_ACCESS_KEY})

             @storage ||= Fog::Storage.new({
                 :local_root => '~/fog',
                 :provider   => 'Local'
             })

         def directory
           storage.directories.find("data").first or
             storage.directories.create(:key => 'data' )
         end

# snip ....



Wednesday, 23 November, 11
get '/' do
                               "hello, world!"
                             end




Wednesday, 23 November, 11
post '/picture/create' do
             file     = params[:file]
             data     = file[:tempfile]

               #super secure filename
               filename = file[:filename]

               key = Digest::SHA1.hexdigest("super random seed"+Time.now.to_s)
               key << '.jpg'

             file = directory.files.create(
               :body => data.read,
               :key => key
             )
             file.public_url or "http://0.0.0.0:9292/picture/#{key}"
           end




Wednesday, 23 November, 11
get '/picture/:key' do
                    file = directory.files.get(params[:key])
                    send_file file.send(:path)
                  end




Wednesday, 23 November, 11
rackup




Wednesday, 23 November, 11
and...




Wednesday, 23 November, 11
Wednesday, 23 November, 11
Fog Storage:
                             Kind of cool.



Wednesday, 23 November, 11
Fog Compute:
                              Wicked cool.



Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Wednesday, 23 November, 11
Heroku

                             Classic Stack (run rack/rails)
                             Cedar Stack (run “anything”)




Wednesday, 23 November, 11
Heroku
        Classic Stack (run rack/rails)
       $ heroku create
       Created sushi.herokuapp.com | git@heroku.com:sushi.git

       $ git push heroku master
       -----> Heroku receiving push
       -----> Rails app detected
       -----> Compiled slug size is 8.0MB
       -----> Launching... done, v1
       http://sushi.herokuapp.com deployed to Heroku




Wednesday, 23 November, 11
Heroku
        Cedar Stack (run “anything”)
       $ cat Procfile
       web:           bundle                     exec         rails server -p $PORT
       worker:        bundle                     exec         rake resque:work QUEUE=*
       urgentworker: bundle                      exec         rake resque:work QUEUE=urgent
       clock:         bundle                     exec         clockwork clock.rb

       $ heroku scale web=4 worker=2 urgentworker=1 clock=1
       Scaling processes... done




        “O cially Everything”:
             Ruby, Node.js,Clojure, Java, Python, and Scala



Wednesday, 23 November, 11
Recap
           • Core concepts
           • Ruby on the JVM (and the CLR, sort of)
           • Data
           • Integration
           • Deployment
           • Sysadmin
           • The Cloud
Wednesday, 23 November, 11
“help me ruby...
         you’re my only hope!”
Wednesday, 23 November, 11
“good... the force is
                             strong with you.


                                           Thanks!




    a powerful rubyist you
Wednesday, 23 November, 11
                              will become.”

Mais conteúdo relacionado

Mais procurados (12)

TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011TorqueBox at DC:JBUG - November 2011
TorqueBox at DC:JBUG - November 2011
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
 
Devignition 2011
Devignition 2011Devignition 2011
Devignition 2011
 
Complex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBoxComplex Made Simple: Sleep Better with TorqueBox
Complex Made Simple: Sleep Better with TorqueBox
 
Plugin Memcached%20 Study
Plugin Memcached%20 StudyPlugin Memcached%20 Study
Plugin Memcached%20 Study
 
Memcached
MemcachedMemcached
Memcached
 
Rails Performance Tuning
Rails Performance TuningRails Performance Tuning
Rails Performance Tuning
 
TorqueBox for Rubyists
TorqueBox for RubyistsTorqueBox for Rubyists
TorqueBox for Rubyists
 
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
 
The JVM is your friend
The JVM is your friendThe JVM is your friend
The JVM is your friend
 
Torquebox @ Raleigh.rb - April 2011
Torquebox @ Raleigh.rb - April 2011Torquebox @ Raleigh.rb - April 2011
Torquebox @ Raleigh.rb - April 2011
 
Lightweight Grids With Terracotta
Lightweight Grids With TerracottaLightweight Grids With Terracotta
Lightweight Grids With Terracotta
 

Mais de Burke Libbey (6)

Nix: What even is it though?
Nix: What even is it though?Nix: What even is it though?
Nix: What even is it though?
 
Learn Ruby by Reading the Source
Learn Ruby by Reading the SourceLearn Ruby by Reading the Source
Learn Ruby by Reading the Source
 
Ruby Internals
Ruby InternalsRuby Internals
Ruby Internals
 
Coffeescript
CoffeescriptCoffeescript
Coffeescript
 
Fuck Yeah Nouns
Fuck Yeah NounsFuck Yeah Nouns
Fuck Yeah Nouns
 
Ruby's Object Model: Metaprogramming and other Magic
Ruby's Object Model: Metaprogramming and other MagicRuby's Object Model: Metaprogramming and other Magic
Ruby's Object Model: Metaprogramming and other Magic
 

Último

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Último (20)

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 

The Enterprise Strikes Back

  • 1. The Enterprise Strikes Back Burke Stefan Libbey Penner Wednesday, 23 November, 11
  • 2. Burke Stefan Libbey Penner Wednesday, 23 November, 11
  • 3. Burke Libbey Stefan Penner @burkelibbey @stefanpenner Wednesday, 23 November, 11
  • 4. Burke Libbey Stefan Penner @burkelibbey @stefanpenner Wednesday, 23 November, 11
  • 5. Burke Libbey Stefan Penner @burkelibbey @stefanpenner Wednesday, 23 November, 11
  • 6. Overview • Core concepts • Ruby on the JVM (and the CLR, sort of) • Data • Integration • Deployment • Sysadmin • The Cloud Wednesday, 23 November, 11
  • 7. Ruby’s weaknesses • Poor performance • Type system sometimes causes headaches in large codebases • No compiler to catch certain bugs But your tests catch these, right? Wednesday, 23 November, 11
  • 8. Why ruby is slow • Late method lookup • Lots of context tracking to allow for eval • Stop-the-world Mark & Sweep GC • Runtime modification of code Wednesday, 23 November, 11
  • 9. Ruby’s strengths • Developing working code quickly • Reducing incidental complexity Especially when best practices are adhered to • Ease of developing powerful libraries and succinct DSLs Wednesday, 23 November, 11
  • 10. Uniform Access Principle All services o ered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation. - Bertrand Meyer Wednesday, 23 November, 11
  • 11. Two Rules • Everything is an object • Objects expose methods and only methods Wednesday, 23 November, 11
  • 14. Ruby Java + Productive + Not Scary - Scary - Less productive Wednesday, 23 November, 11
  • 15. Ruby in Java + Not Scary + Productive Wednesday, 23 November, 11
  • 17. • Full ruby implementation on the JVM • Access to both ruby and Java libraries • Can be deployed to existing Java infrastructure Wednesday, 23 November, 11
  • 18. The many flavours of ruby • MRI (and YARV) • JRuby • IronRuby • MacRuby • Rubinius • ...and several more... Wednesday, 23 November, 11
  • 20. The Magic Sauce require 'java' (contains up to 30% midichlorians) Wednesday, 23 November, 11
  • 21. Calling Java from ruby f = javax.swing.JFrame.new f.getContentPane.add(javax.swing.JLabel.new("Hello World")) close_operation = javax.swing.JFrame::EXIT_ON_CLOSE f.setDefaultCloseOperation(close_operation) f.pack f.setVisible(true) Wednesday, 23 November, 11
  • 22. Impedance Mismatch f = javax.swing.JFrame.new f.getContentPane.add(javax.swing.JLabel.new("Hello World")) close_operation = javax.swing.JFrame::EXIT_ON_CLOSE f.setDefaultCloseOperation(close_operation) f.pack f.setVisible(true) Let’s break this down. Wednesday, 23 November, 11
  • 23. Impedance Mismatch “Getters” and “Setters” are non-idiomatic in ruby. f = javax.swing.JFrame.new f.getContentPane.add(javax.swing.JLabel.new("Hello World")) getContentPane close_operation = javax.swing.JFrame::EXIT_ON_CLOSE f.setDefaultCloseOperation(close_operation) f.pack f.setVisible(true) snake_case is generally preferred to CamelCase Wednesday, 23 November, 11
  • 24. Impedance Mismatch JavaBean properties can be accessed like this: f = javax.swing.JFrame.new f.content_pane.add(javax.swing.JLabel.new("Hello World")) close_operation = javax.swing.JFrame::EXIT_ON_CLOSE f.setDefaultCloseOperation(close_operation) f.pack f.setVisible(true) (UA P in action!) “get” disappears, CamelCase changes to snake_case Wednesday, 23 November, 11
  • 25. Impedance Mismatch “set” is replaced by “=” f = javax.swing.JFrame.new f.content_pane.add(javax.swing.JLabel.new("Hello World")) close_operation = javax.swing.JFrame::EXIT_ON_CLOSE f.default_close_operation = close_operation f.pack f.visible = true “setDefaultCloseOperation(x)” becomes “default_close_operation = x” Wednesday, 23 November, 11
  • 26. Ugliness Abounds f = javax.swing. javax.swing.JFrame.new f.content_pane.add(javax.swing.JLabel.new("Hello World")) javax.swing. close_operation = javax.swing. javax.swing.JFrame::EXIT_ON_CLOSE f.default_close_operation = close_operation f.pack f.visible = true Namespaces everywhere! Wednesday, 23 November, 11
  • 27. Ugliness Abounds java_import 'javax.swing.JFrame' java_import 'javax.swing.JLabel' f = JFrame.new f.content_pane.add(JLabel.new("Hello World")) JLabel.new close_operation = JFrame::EXIT_ON_CLOSE f.default_close_operation = close_operation f.pack f.visible = true java_import adds classes to a ruby context Wednesday, 23 November, 11
  • 28. 100% Rubified™ java_import 'javax.swing.JFrame' java_import 'javax.swing.JLabel' JFrame.new.tap do |f| f.content_pane.add JLabel.new("Hello World") f.default_close_operation = JFrame::EXIT_ON_CLOSE f.pack f.visible = true end Wednesday, 23 November, 11
  • 29. Method Rubification™ • In general, CamelCase Java methods can optionally be transliterated to snake case. Wednesday, 23 November, 11
  • 30. Method Rubification™ Java System.currentTimeMillis() Ruby System.current_time_millis Wednesday, 23 November, 11
  • 31. Seriously though, not actually trademarked. Method Rubification™ Java person.getName() Ruby person.name Wednesday, 23 November, 11
  • 32. Someone should get on that. Method Rubification™ Java person.setAge(42) Ruby person.age = 42 Wednesday, 23 November, 11
  • 33. Method Rubification™ FALSE! TRUE! Java person.isJedi() Ruby person.jedi? Wednesday, 23 November, 11
  • 34. Is ruby an acceptable Java? (http://bit.ly/pfNluA) • Most Java code can literally be written as ruby with few high-level changes. • A more relaxed type system and syntax often has productivity benefits. Wednesday, 23 November, 11
  • 35. Exhibit A // interfaces = HashMap{ label => NetworkInterface } Java Collection c = interfaces.values(); Iterator itr = c.iterator(); while(itr.hasNext()) { NetworkInterface interface = itr.next(); if (interface.isLoopback()) { return interface.getDisplayName(); } } VS. # interfaces = {label => NetworkInterface} Ruby interfaces.values.find(&:loopback?).display_name Wednesday, 23 November, 11
  • 36. Exhibit A // interfaces = HashMap{ label => NetworkInterface } Java Collection c = interfaces.values(); Iterator itr = c.iterator(); while(itr.hasNext()) { NetworkInterface interface = itr.next(); if (interface.isLoopback()) { return interface.getDisplayName(); } } VS. # interfaces = {label => NetworkInterface} Ruby interfaces.values.find(&:loopback?).display_name 1 2 345 67 Only 7 characters of syntactic support! Wednesday, 23 November, 11
  • 37. “Are you suggesting I write all my Java in ruby?!” • Not really... • JRuby is much slower than Java (doesn’t matter as often as you’d think) • Ruby’s added expressiveness makes it easier to shoot yourself in the foot. (or, in fact, to lazily clone an infinite number of your feet every planck length between your gun and your target) Wednesday, 23 November, 11
  • 38. “Are you suggesting I write all my Java in ruby?!” • ...but maybe sometimes. • One possibility: • Encode high-level logic in expressive and concise ruby code • Supporting code in fast, safe Java • Mix and match as appropriate Wednesday, 23 November, 11
  • 39. Ruby as Glue • Ruby is great for: • wiring existing codebases together • other miscellaneous tasks Wednesday, 23 November, 11
  • 40. Perl The original “Swiss Army Knife” Wednesday, 23 November, 11
  • 41. Perl Pretty much mean the same thing. • “glue” • “duct tape” • “swiss army knife” Wednesday, 23 November, 11
  • 42. Perl Ruby Wednesday, 23 November, 11
  • 43. Subcategories of “Glue” • Wiring stu together • Sysadmin tasks Wednesday, 23 November, 11
  • 44. Wiring stu together • There’s a lot we could cover here, but: Wednesday, 23 November, 11
  • 45. Nokogiri • An extremely user-friendly XML library • fast! (wraps libxml2) Wednesday, 23 November, 11
  • 46. Nokogiri require 'open-uri' require 'nokogiri' html = open("http://slashdot.org").read doc = Nokogiri::XML(html) (doc/".story a").each do |link| puts "#{link.text} (#{link.attr('href')})" end # Britain's Broadband Censors: a Bunch of Students (//yro.slashdot... # ... Wednesday, 23 November, 11
  • 47. Don’t do this. (Nokogiri::XML(open("http://slashdot.org").read)/".story a").each{|a|puts "#{a.text} (#{a.attr("href")})"} Wednesday, 23 November, 11
  • 48. Sysadmin with Ruby • Nice system APIs (quite similar to perl’s) • System provisioning libraries/DSLs Wednesday, 23 November, 11
  • 49. Provisioning systems • Puppet • Chef • Vagrant Wednesday, 23 November, 11
  • 50. Puppet • Describe system, and puppet sets it up • Nontrivial, but the general idea is: • I want mysql • I want nginx < 0.8 • I want this cron job: “....” • Go. http://puppetlabs.com/ Wednesday, 23 November, 11
  • 51. Puppet class postgres-server { package { postgresql-server: ensure => latest } group { postgres: gid => 26 } user { postgres: comment => "PostgreSQL Server", uid => 26, gid => 26, home => "/var/lib/pgsql", shell => "/bin/bash" } service { postgresql: running => true, pattern => "/usr/bin/postmaster", require => package["postgresql-server"] } } Wednesday, 23 November, 11
  • 52. Puppet • Fantastic for defining a reproducible production environment Wednesday, 23 November, 11
  • 53. Chef • Same idea as puppet • Somewhat less powerful • Slightly more approachable to most ruby developers http://www.opscode.com/chef/ Wednesday, 23 November, 11
  • 54. Chef package "sudo" do action :upgrade end template "/etc/sudoers" do source "sudoers.erb" mode 0440 owner "root" group "root" variables( :sudoers_groups => node['authorization']['sudo']['groups'], :sudoers_users => node['authorization']['sudo']['users'], :passwordless => node['authorization']['sudo']['passwordless'] ) end Wednesday, 23 November, 11
  • 55. Puppet Chef Configuration Language custom ruby Targeted at production production “Powerfulness” Lots Mostly lots Verdict Good Di erent Written in ruby ruby Wednesday, 23 November, 11
  • 56. Vagrant • Uses puppet and/or chef • End product is a virtual machine for development use • Consistent system for all developers, per project Wednesday, 23 November, 11
  • 57. Vagrant • If you use puppet or chef, vagrant lets you test production locally Wednesday, 23 November, 11
  • 58. Suggestions • As a non-ruby-dev: • Use puppet • Consider vagrant Wednesday, 23 November, 11
  • 59. Suggestions • As a ruby developer: • Consider chef and puppet, use whichever suits your taste and needs • Consider vagrant Wednesday, 23 November, 11
  • 61. In the Real World, Wednesday, 23 November, 11
  • 62. In the Real World, We have Data Wednesday, 23 November, 11
  • 63. In the Real World, We have Data Which lives in Databases Wednesday, 23 November, 11
  • 64. Databases Are Always simple Wednesday, 23 November, 11
  • 65. All our data is ALWAYS in the same DBMS Wednesday, 23 November, 11
  • 67. Luckily We have ODBC + JDBC Wednesday, 23 November, 11
  • 68. Luckily We have ODBC + JDBC + Ruby Wednesday, 23 November, 11
  • 69. Ruby Gives you Options • Active Record • Sequel • DataMapper • more Wednesday, 23 November, 11
  • 70. Active Record Design pattern coined by Martin Fowler in “Patterns of enterprise application architecture”. Also, Ruby on Rails’s default ORM. • Lots of Power • Lots of Opinion • Might fight with you (for non-standard uses) https://github.com/rails/rails/tree/master/activerecord Wednesday, 23 November, 11
  • 71. Active Record Syntax (Raw) require 'active_record' ActiveRecord::Base.establish_connection({ :adapter => 'mysql', :database => 'test_database', :username => 'tester', :password => 'test22' }) connection = ActiveRecord::Base.connection connection.tables > ['users', 'products', 'ducks', 'oranges'] users = [] connection.execute('SELECT * FROM users').each_hash do |user| users << user end users > .... array of users, each user as a hash. users.first > { :id => 1, :username => 'stefan', :password => 'is_super_secure' } Wednesday, 23 November, 11
  • 72. Active Record Syntax (ORM) require 'active_record' ActiveRecord::Base.establish_connection({ :adapter => 'mysql', :database => 'test_database', :username => 'tester', :password => 'test22' }) # class <camel_case_singular_table_name> < ActiveRecord::Base class User < ActiveRecord::Base # if the table's name does not fit convention, it can be manually overridden. # table_name :users_table end User.first > #<User id: 2, :name => 'stefan', :password => 'is_super_secure' > User.find(2) > #<User id: 2, :name => 'stefan', :password => 'is_super_secure' > User.where(:name => 'stefan') > #<User id: 2, :name => 'stefan', :password => 'is_super_secure' > Wednesday, 23 November, 11
  • 73. Active Record Syntax (AREL) User.first > #<User id: 2, :name => 'stefan', :password => 'is_super_secure' > User.find(2) > #<User id: 2, :name => 'stefan', :password => 'is_super_secure' > User.where(:name => 'stefan') > #<User id: 2, :name => 'stefan', :password => 'is_super_secure' > User.where(:name => 'stefan').order('id ASC') > #<User id: 2, :name => 'stefan', :password => 'is_super_secure' > Wednesday, 23 November, 11
  • 74. Sequel Elegant Full featured database toolkit for ruby. • Supports a ton of DBMS’s • DSL • ORM http://sequel.rubyforge.org/ Supports - ADO, Amalgalite, DataObjects, DB2, DBI, DO, Firebird, ibmdb, Informix, JDBC, MySQL, Mysql2, ODBC, OpenBase, Oracle, PostgreSQL, SQLite3, Swift, and tinytds Wednesday, 23 November, 11
  • 75. require "sequel" Sequel Example # connect to an in-memory database DB = Sequel.sqlite # create an items table DB.create_table :items do primary_key :id String :name Float :price end # create a dataset from the items table items = DB[:items] # populate the table items.insert(:name => 'abc', :price => rand * 100) items.insert(:name => 'def', :price => rand * 100) items.insert(:name => 'ghi', :price => rand * 100) # print out the number of records puts "Item count: #{items.count}" # print out the average price puts "The average price is: #{items.avg(:price)}" Wednesday, 23 November, 11
  • 76. Sequel ORM require "sequel" # connect to an in-memory database DB = Sequel.sqlite # create an items table DB.create_table :items do primary_key :id String :name Float :price end # create a dataset from the items table class Item < Sequel::Model(:items) # associations # validations end # populate the table Item.create(:name => 'abc', :price => rand * 100) Item.create(:name => 'def', :price => rand * 100) Item.create(:name => 'ghi', :price => rand * 100) # print out the number of records puts "Item count: #{Item.count}" # print out the average price puts "The average price is: #{Item.avg(:price)}" Wednesday, 23 November, 11
  • 77. Sequel ORM + jRuby ready out of the box Wednesday, 23 November, 11
  • 78. Sequel ORM + IRONRuby apparently works? Wednesday, 23 November, 11
  • 79. Case Study (Access) • Access (top 2 solutions) • Solution 1 (Cross Platform) • jRuby • JDBC • HXTT’s driver (www.hxtt.com) • Sequel • Solution 2 (Windows Only) • Ruby • ADO via WIN32OLE • Sequel Wednesday, 23 November, 11
  • 81. Case Study (Access) 1. Download jRuby http://jruby.org/ Wednesday, 23 November, 11
  • 82. Case Study (Access) 1. Download jRuby http://jruby.org/ 2. Install Sequel gem install Sequel Wednesday, 23 November, 11
  • 83. Case Study (Access) 1. Download jRuby http://jruby.org/ 2. Install Sequel gem install Sequel 3. Download JDBC Access Driver http://www.hxtt.com/access.html Wednesday, 23 November, 11
  • 84. Case Study (Access) require 'rubygems' require 'sequel' require 'sequel/adapters/jdbc' require 'sequel/jdbc_hxtt_adapter' require '../Support/Access_JDBC40.jar' root = File.expand_path "../../", __FILE__ path_to_db = root + "/Support/AccessThemeDemo.mdb" DB = Sequel.connect("jdbc:access:////#{path_to_db}") puts DB.tables class Notes < Sequel::Model(:Notes) end class ThemeImages < Sequel::Model(:tbl_ThemeImages) end class Users < Sequel::Model(:tbl_Users) end Wednesday, 23 November, 11
  • 86. But our new app and our old database have di erent system requirements. Wednesday, 23 November, 11
  • 87. We Want Isolation Wednesday, 23 November, 11
  • 88. _ -Need We Want Isolation Wednesday, 23 November, 11
  • 89. Power by.. Sinatra Web DSL get '/pictures' do ['picture1','picture2','picture2'] end post '/pictures' {} put '/pictures/:id' {} delete '/pictures/:id' {} used at linkedIn http://engineering.linkedin.com/44/linkedin-app-end-end-jruby-frontier-and-voldemort Wednesday, 23 November, 11
  • 90. sooo... big deal? Wednesday, 23 November, 11
  • 91. RestServer • any jdbc database into a restful json service • https://github.com/stefanpenner/restserver Wednesday, 23 November, 11
  • 92. Portability/Bundling • Warbler http://github.com/nicksieger/warbler • single jar/war file • compiled (if needed) Wednesday, 23 November, 11
  • 93. it’s an app! Wednesday, 23 November, 11
  • 94. Putting it all together (p1) ScreenShotr download: https://github.com/stefanpenner/screenshotr/zipball/master git@github.com:stefanpenner/screenshotr Wednesday, 23 November, 11
  • 95. Sorry, contrived example! Wednesday, 23 November, 11
  • 97. Java Gives Us • Portability Ruby Gives Us • Happiness Wednesday, 23 November, 11
  • 98. ScreenShotr Normally Annoying re: Portability • screen capture • GUI but thx jRuby Wednesday, 23 November, 11
  • 99. Lets Shoot some Screens require 'java' java_import 'java.awt.Robot' java_import 'java.awt.Toolkit' java_import 'java.awt.Rectangle' java_import 'java.awt.Image' java_import 'java.awt.image.BufferedImage' java_import 'javax.imageio.ImageIO' screenRect = Rectangle.new(Toolkit.default_toolkit.getScreenSize()) capture = Robot.new.createScreenCapture(screenRect) ImageIO.write(capture,'jpg',java.io.File.new('some_tmp_file.jpg')) Wednesday, 23 November, 11
  • 100. Hold UP Wednesday, 23 November, 11
  • 101. Hold UP java_import ? Wednesday, 23 November, 11
  • 102. Hold UP java_import ? why not require? Wednesday, 23 November, 11
  • 103. Hold UP java_import ? why not require? requiring classes just makes them discoverable later. Wednesday, 23 November, 11
  • 104. Hold UP java_import ? why not require? requiring classes just makes them discoverable later. why not import? Wednesday, 23 November, 11
  • 105. Hold UP java_import ? why not require? requiring classes just makes them discoverable later. why not import? Rake defines import Wednesday, 23 November, 11
  • 106. Hold UP java_import ? why not require? requiring classes just makes them discoverable later. why not import? Rake defines import weird... Wednesday, 23 November, 11
  • 107. And fill some clipboards require 'java' java_import 'java.awt.Toolkit' java_import 'javax.imageio.ImageIO' ss = StringSelection.new(public_url) Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, nil) Wednesday, 23 November, 11
  • 108. upload to server gem install rest-client require 'rubygems' require 'rest-client' RestClient.post('http://../resource', :file => File.new('path/to/file')) Wednesday, 23 November, 11
  • 109. upload to server gem install rest-client require 'rubygems' require 'rest-client' RestClient.post('http://../resource', :file => File.new('path/to/file')) Wednesday, 23 November, 11
  • 110. <Insert Segue Here> Wednesday, 23 November, 11
  • 111. ...and Vice Versa • We’ve done a lot of calling Java from ruby. • The reverse is possible as well. Wednesday, 23 November, 11
  • 112. ...and Vice Versa import org.jruby.embed.InvokeFailedException; import org.jruby.embed.ScriptingContainer; // ... ScriptingContainer container = new ScriptingContainer(); container.runScriptlet("puts "That's no Moon""); http://en.wikipedia.org/wiki/Jruby Wednesday, 23 November, 11
  • 113. Testing Java with Ruby “i find your lack of tests disturbing.” Wednesday, 23 November, 11
  • 114. Testing Java with Ruby • JtestR is wonderful • Includes most of ruby’s leading testing libraries • supports ant and maven • easy to add to a project • takes advantage of jruby/java bridge Wednesday, 23 November, 11
  • 115. JtestR Installation • Download jarfile from jtestr.codehaus.org • Add to classpath • Add a task to maven/ant • Create tests in ./test or ./spec • Run task Wednesday, 23 November, 11
  • 116. Example! import java.util.HashMap describe "An empty", HashMap do before :each do @hash_map = HashMap.new end it "accepts new entries" do @hash_map.put "foo", "bar" @hash_map.get("foo").should == "bar" end it "returns a keyset iterator that throws an exception on next" do proc do @hash_map.key_set.iterator.next end.should raise_error(java.util.NoSuchElementException) end end Wednesday, 23 November, 11
  • 117. BDD Any language • Cucumber • http://cukes.info Wednesday, 23 November, 11
  • 118. “i saw a city in the clouds” Wednesday, 23 November, 11
  • 119. MYTH: Ruby can’t scale. Wednesday, 23 November, 11
  • 120. FACT: Ruby scales like a BOSS Wednesday, 23 November, 11
  • 121. FACT: Ruby scales like a BOSS (because it has to) Wednesday, 23 November, 11
  • 122. Fog • “The Ruby Cloud Services Library” • Lets you upload to S3, provision instances in EC2, set DNS records in DNSimple... • ...and much more. Wednesday, 23 November, 11
  • 123. Fog “ • Chewbacca-approved. whargarblbgarblgr- Wednesday, 23 November, 11 ” garblgragh
  • 124. Fog “ • Chewbacca-approved. (chewbaccaproved?) whargarblbgarblgr- Wednesday, 23 November, 11 garblgragh ”
  • 125. 2.5 imperial tons of providers Wednesday, 23 November, 11
  • 126. ( )eh. 2.5 imperial tons of H providers Wednesday, 23 November, 11
  • 151. Sinatra Example #config.ru require './lib/screen_shotr/server' run ScreenShotr::Server.new Wednesday, 23 November, 11
  • 152. require 'sinatra' require 'fog' require 'digest/sha1' Wednesday, 23 November, 11
  • 153. module ScreenShotr class Server < Sinatra::Base def storage #@storage ||= Fog::Storage.new({ # :provider => 'AWS', # :aws_access_key_id => ACCESS_KEY_ID, # :aws_secret_access_key => SECRET_ACCESS_KEY}) @storage ||= Fog::Storage.new({ :local_root => '~/fog', :provider => 'Local' }) def directory storage.directories.find("data").first or storage.directories.create(:key => 'data' ) end # snip .... Wednesday, 23 November, 11
  • 154. get '/' do "hello, world!" end Wednesday, 23 November, 11
  • 155. post '/picture/create' do file = params[:file] data = file[:tempfile] #super secure filename filename = file[:filename] key = Digest::SHA1.hexdigest("super random seed"+Time.now.to_s) key << '.jpg' file = directory.files.create( :body => data.read, :key => key ) file.public_url or "http://0.0.0.0:9292/picture/#{key}" end Wednesday, 23 November, 11
  • 156. get '/picture/:key' do file = directory.files.get(params[:key]) send_file file.send(:path) end Wednesday, 23 November, 11
  • 160. Fog Storage: Kind of cool. Wednesday, 23 November, 11
  • 161. Fog Compute: Wicked cool. Wednesday, 23 November, 11
  • 172. Heroku Classic Stack (run rack/rails) Cedar Stack (run “anything”) Wednesday, 23 November, 11
  • 173. Heroku Classic Stack (run rack/rails) $ heroku create Created sushi.herokuapp.com | git@heroku.com:sushi.git $ git push heroku master -----> Heroku receiving push -----> Rails app detected -----> Compiled slug size is 8.0MB -----> Launching... done, v1 http://sushi.herokuapp.com deployed to Heroku Wednesday, 23 November, 11
  • 174. Heroku Cedar Stack (run “anything”) $ cat Procfile web: bundle exec rails server -p $PORT worker: bundle exec rake resque:work QUEUE=* urgentworker: bundle exec rake resque:work QUEUE=urgent clock: bundle exec clockwork clock.rb $ heroku scale web=4 worker=2 urgentworker=1 clock=1 Scaling processes... done “O cially Everything”: Ruby, Node.js,Clojure, Java, Python, and Scala Wednesday, 23 November, 11
  • 175. Recap • Core concepts • Ruby on the JVM (and the CLR, sort of) • Data • Integration • Deployment • Sysadmin • The Cloud Wednesday, 23 November, 11
  • 176. “help me ruby... you’re my only hope!” Wednesday, 23 November, 11
  • 177. “good... the force is strong with you. Thanks! a powerful rubyist you Wednesday, 23 November, 11 will become.”