SlideShare une entreprise Scribd logo
1  sur  37
Télécharger pour lire hors ligne
ThoughtWorks




    Introduction to JRuby

                NEAL FORD thoughtworker / meme wrangler


                           ThoughtWorks
             14 Wall St, Suite 2019,   New York, NY   10005

             nford@thoughtworks.com
             www.nealford.com
             www.thoughtworks.com
             memeagora.blogspot.com




                                                                  ThoughtWorks

Questions, Slides, & Samples
 Please feel free to ask questions anytime
 Slides and samples at www.nealford.com
ThoughtWorks

What This Session Covers:
 Motivation for JRuby
 What makes Ruby cool?
   Classes & objects
   Closures
   Mixins
   Idioms

 Ruby + Java




                                    ThoughtWorks

Why Ruby?
 Purely object-oriented
 Dynamically typed (“duck typed”)
 Compact syntax
 Closures
 Open classes
 Awesome meta-programming support
 Rails
ThoughtWorks

What is JRuby?
 JRuby is the Ruby interpreter, rewritten in Java
   MRI (Matz Reference Implementation) written in C and
   Ruby
   JRuby developers ported the C code to Java
 Now produces byte code
   The compiler is done (available in the JRuby 1.1 release)
   Faster than MRI on almost all benchmarks!!!




                                                    ThoughtWorks

Why JRuby?
 JRuby == Ruby on the JVM
 Allows Java capabilities with Ruby syntax
   Smart about properties
   Access to Java libraries
 Ruby libraries from Java
 Supports all Ruby syntax and built-in libraries
   Easy to port the libraries written in Ruby
   C libraries ported to Java
ThoughtWorks

Motivations
 Use Java libraries (i.e., Swing) from Ruby code
 Use Ruby libraries (i.e., ActiveRecord) from Java
   Using Bean Scripting Framework (JDK <= 1.5)
   Using JSR 223 Scripting API (JDK > 1.5)
 Get an (eventually) faster Ruby
   Much slower now
   Lessons learned from IronPython




                                                      ThoughtWorks

What JRuby Gives You
 JRuby classes can
   Inherit from Java classes
   Implement Java interfaces
   Open Java classes (visible from JRuby, not Java)

 Running on the JVM provides
   Native threads
   Unicode Support
   Portability
ThoughtWorks

Current Limitations
 Does not support continuations/bindings
 Fine-grained timer
   Benchmarking code depends on finer grained timings than
   the JVM supports
   Solved(?) in a future JVM via a current JSR
 Identical thread behavior
 Missing File operations
   The JVM is missing some file operations needed by File
   and friends in Ruby




                                                 ThoughtWorks

Some Ruby Syntax
 Just the interesting stuff
 Example
   hr.rb
   hr_runner.rb
   Tests
    test_employee.rb

    test_manager.rb

    test_all.rb
ThoughtWorks

Ruby Blocks
 Delineated with either
   { . . . } # idiomatically used for single line blocks
   do . . . end # idiomatically used for multi-line blocks
 Both support parameters with |my_param|
 Examples
   hr_blocks.rb
   hr_blocks_ruby_way.rb




                                                           ThoughtWorks

What Makes a Block a Closure?
 A closure object has
   Code to run (the executable)
   State around the code (the environment, including the
   local variables)

 The closure captures the environment
   You can reference the local variable inside the closure...
   ...even if the variable has gone out of scope

 Example
   hr_closures.rb
ThoughtWorks

Important Closure Characteristics
 Closures combine a block of code with an
 environment
   Sets it apart from function pointers, et al
   Java’s anonymous inner classes can access locals (only if
   they are final)

 Require very little syntax
   Crucial because they are used all the time
   Cumbersome to create something like an anonymous
   inner class all the time




                                                     ThoughtWorks

Open Classes
 Ruby allows you to “open” classes
   When you write a class definition that already appears on
   the classpath, Ruby opens the class
   You can make changes to the class
    Methods

    Member variables

    Method characteristics

 You can also add methods to object instances
   open_employee
ThoughtWorks

Modules
 Allow you to group classes, method, and
 constants
 Provide two major benefits
   Namespaces
   Mixins
 Mixins are Ruby’s alternatives to
   Multiple inheritance
   Interfaces




                                                    ThoughtWorks

Mixins
 When you include a module into a class, the
 modules methods are mixed into the class
 Methods defined in the module can interact with
 instance variables of the class
 Don’t be fooled by the include keyword
   Not like a C/C++ include
   Class references the module (i.e., no copying)

 Example: hr_mixin.rb
ThoughtWorks

Using Java Classes in Ruby
 Must contain require        “java”

 5 options
   Provide full class name when using
     frame = javax.swing.JFrame.new(quot;My Titlequot;)

   Assign full class name to a constant.
     JFrame = javax.swing.JFrame
     frame = JFrame.new(quot;My Titlequot;)

   Use include_class
    include_class quot;javax.swing.JFramequot;
    frame = JFrame.new(quot;My Titlequot;)




                                                   ThoughtWorks

Using Java Classes in Ruby
 5 options (continued)
   Use include_class with an alias
   Useful when Java class name matches Ruby class name
   include_class(quot;java.lang.Stringquot;) do |pkg_name, class_name|
     quot;J#{class_name}quot;
   end
   msg = JString.new(quot;My Messagequot;)

   Use include_package to scope Java classes in a Ruby
   module namespace (only in a module)
   module Swing
     include_package quot;javax.swingquot;
   end
   frame = Swing::JFrame.new(quot;My Titlequot;)
ThoughtWorks

Calling Semantics
 Parenthesis aren’t required when calling methods
 Java get/set/is methods are invoked like Ruby
 accessors
  emp.getName()        => e.name
  emp.setName(“Homer”) => e.name = “Homer”
  emp.isManager()      => e.manager?


 Camelcase Java names can be called with
 underscores
  require quot;javaquot;
  url = java.net.URL.new(quot;http://www.nealford.comquot;)
  puts url.to_external_form # method name is toExternalForm
  puts url.to_uri # method name is toURI




                                                    ThoughtWorks

Building Swing in Ruby
 Much friendlier syntax
   Dynamic typing cuts way down on useless code
 Uses blocks intelligently
   Define button click behavior in a block at definition
 Example
   hello_frame.rb
ThoughtWorks

Ruby Methods Added to Core Java
 JRuby adds lots of methods to core JDK classes
 Decorated all the collections classes to make
 them “humane”
 Added operators to String and type wrappers
   <=>, <, <=, =>, >, between?
 Example
   JRuby Super Console




                                          ThoughtWorks

Proxy Classes
 JRuby builds proxies for Java classes
 Allows open classes with Java
   Add methods to the class
   Add methods to the object instance
 Example
   array_list_proxy.rb
ThoughtWorks

JRuby Inheriting from Java Classes
 JRuby classes can inherit from Java classes
 Example
   Car.java
   race_car.rb




                                               ThoughtWorks

Testing Java with JRuby
 You can use JRuby to write unit tests against Java code
 Including powerful mock-object libraries from Ruby
 (like Mocha)
 Example
   OrderInteractionTester.java
   OrderInteractionTest.rb

 Mocha provides
   Mocks and stubs
   Automatic verification
ThoughtWorks

JRuby on Rails
 Yes, Rails now runs on JRuby
 You can build a WAR file from a Rails application
 and deploy it on a JVM
 Still slower than Ruby
 Still some manual tweaking for stuff like databases
 But it works!




                                                   ThoughtWorks

JRuby Advantages over Ruby
 Ola Bini’s recipe:
   Take one large Rails application with good Selenium test
   base
   Convert database configuration to use JDBC
   Start a selenium proxy with quot;jake test:selenium_proxyquot;
   Start acceptance testing from another window with quot;jake
   test:acceptancequot;
   In yet another window, write quot;jconsolequot;
   Choose your application
ThoughtWorks

The Result?




                                          ThoughtWorks

Future Directions
 Performance, performance, performance!
 Improving the Rails experience
 Version 1.0 is the current version
 Version 1.1 (with compiler) soon
ThoughtWorks

Benchmarks




             ThoughtWorks

Benchmarks
ThoughtWorks

JRuby vs. Groovy
 JRuby is an interpreter written in Java
   With compilation (in version 1.1)

   Interacts with Java classes via proxies

 Groovy is an alternative Java syntax
   Wraps Java classes with proxies

   Compiles to byte code




                                                    ThoughtWorks

JRuby vs. Groovy
 Groovy can only perform operations allowed by
 byte code in the JVM
 JRuby is free to do anything that Ruby can do
   The most powerful mainstream meta-programming
   language
   JRuby on Rails can do things that are difficult and
   impossible with Groovy
 Ruby is the most powerful mainstream language
ThoughtWorks

JRuby vs. Groovy
                                     Ruby/JRuby
Java




                         Groovy




                                             ThoughtWorks

Resources
 The JRuby web site
   http://jruby.codehaus.org/
   Includes documentation, tutorials, etc.
 Charles Nutter’s Blog
   http://headius.blogspot.com/

 Ola Bini’s Blog
   http://ola-bini.blogspot.com/
ThoughtWorks



                               Questions?
       Please fill out the session evaluations
      Samples & slides at www.nealford.com
                                                        NEAL FORD thoughtworker / meme wrangler


                                                                   ThoughtWorks
                                                     14 Wall St, Suite 2019,   New York, NY   10005

This work is licensed under the Creative Commons     nford@thoughtworks.com
                                                     www.nealford.com
Attribution-Noncommercial-Share Alike 2.5 License.   www.thoughtworks.com
                                                     memeagora.blogspot.com
 http://creativecommons.org/licenses/by-nc-sa/2.5/
hr.rb                                              2007-04-22
class Employee
  def initialize(name, salary, hire_year)
    @name = name
    @salary = salary
    @hire_year = hire_year
  end

  attr_reader :salary, :hire_year

  def to_s
    quot;Name is #{@name}, salary is #{@salary}, quot; +
    quot;hire year is #{@hire_year}quot;
  end

  def raise_salary_by(perc)
    @salary += (@salary * (perc * 0.01))
  end
end

class Manager < Employee
  def initialize(name, salary, hire_year, asst)
    super(name, salary, hire_year)
    @asst = asst
  end

  def to_s
    super + quot;,tAssistant info: #{@asst}quot;
  end

  def raise_salary_by(perc)
    perc += 2005 - @hire_year
    super(perc)
  end
end




                                    - 1/1 -
hr_runner.rb                                                      2007-04-22
require 'hr'

def show(emps)
  emps.each { |e| puts e }
end

employees = Array.new
employees[0] = Employee.new(quot;Homerquot;, 200.0, 1995)
employees[1] = Employee.new(quot;Lennyquot;, 150.0, 2000)
employees[2] = Employee.new(quot;Carlquot;, 250.0, 1999)
employees[3] = Manager.new(quot;Montyquot;, 3000.0, 1950, employees[2])

show(employees)

employees.each { |e| e.raise_salary_by(10) }
puts quot;nGive everyone a raisennquot;
show employees




                                    - 1/1 -
test_employee.rb                                        2007-04-22
require 'test/unit/testcase'
require 'test/unit/autorunner'
require 'hr'

class TestEmployee < Test::Unit::TestCase
  @@Test_Salary = 2500

  def setup
    @emp = Employee.new(quot;Homerquot;, @@Test_Salary, 2003)
  end

  def test_raise_salary
    @emp.raise_salary_by(10)
    expected = (@@Test_Salary * 0.10) + @@Test_Salary
    assert expected == @emp.salary
  end

end




                                    - 1/1 -
test_all.rb                                                   2007-04-22
require   'test/unit/testsuite'
require   'test/unit/ui/tk/testrunner'
require   'test/unit/ui/console/testrunner'
require   'test_employee'
require   'test_manager'



class TestSuite_AllTests
    def self.suite
        suite = Test::Unit::TestSuite.new(quot;HR Testsquot;)
        suite << TestEmployee.suite
        suite << TestManager.suite
        return suite
    end
end

# Test::Unit::UI::Tk::TestRunner.run(TestSuite_AllTests)
Test::Unit::UI::Console::TestRunner.run(TestSuite_AllTests)




                                      - 1/1 -
hr_blocks_4_ruby_way.rb                            2007-04-22
class Employee
  attr_reader :name, :salary, :hire_year

  def initialize(name, salary, hire_year)
    @name = name
    @salary = salary
    @hire_year = hire_year
  end

  def to_s
    quot;Name is #{@name}, salary is #{@salary}, quot; +
    quot;hire year is #{@hire_year}quot;
  end

  def raise_salary_by(perc)
    @salary += (@salary * 0.10)
  end

end



class EmployeeList
  def initialize
    @employees = Array.new
  end

  def add(an_employee)
    @employees.push(an_employee)
    self
  end

  def delete_first
    @employees.shift
  end

  def delete_last
    @employees.pop
  end

  def show
    @employees.each { |e|
      puts e
    }
  end

                                    - 1/2 -
hr_blocks_4_ruby_way.rb                                  2007-04-22

  def [](key)
    return @employees[key] if key.kind_of?(Integer)
    return @employees.find do |anEmp|
      key == anEmp.name
    end
    return nil
  end
end

list = EmployeeList.new
list.add(Employee.new(quot;Homerquot;, 200.0, 1995)).
  add(Employee.new(quot;Lennyquot;, 150.0, 2000)).
  add(Employee.new(quot;Carlquot;, 250.0, 1999))

list.show
puts quot;Employee #1 is quot; + list[0].to_s
puts quot;Employee named 'Homer' is quot; + list[quot;Homerquot;].to_s




                                    - 2/2 -
hr_closures.rb                                  2007-04-22
#!/usr/bin/env ruby

class Employee
    def initialize(name, salary)
      @name = name
      @salary = salary
    end

      attr_accessor :name, :salary

      def to_s
        quot;#{@name} makes #{@salary}quot;
      end
end




                                      - 1/1 -
hr_closures_runner.rb                               2007-04-22
#!/usr/bin/env ruby
#
# Created by Neal Ford on 2007-04-20.
# Copyright (c) 2007. All rights reserved.

require 'hr_closures'

def high_paid(emps)
  threshold = 40000
  return emps.select {|e| e.salary > threshold}
end

def paid_more(amount)
  return Proc.new {|e| e.salary > amount}
end

employees   = Array.new
employees   << Employee.new(quot;Homerquot;, 15000)
employees   << Employee.new(quot;Montyquot;, 100000)
employees   << Employee.new(quot;Smithersquot;, 80000)
employees   << Employee.new(quot;Carlquot;, 50000)
employees   << Employee.new(quot;Lennyquot;, 55000)

puts quot;Closures that capture local variable scopequot;
20.times { print '-'}
puts
puts high_paid(employees)

puts
puts quot;Closures that capture definition scopequot;
20.times { print '-'}
puts
is_high_paid = paid_more(60000)

puts is_high_paid.call(employees[0])
puts is_high_paid.call(employees[2])




                                       - 1/1 -
make_counter.rb                                         2007-08-20
def make_counter
  var = 0
  # lambda { var += 1 }
  proc { var += 1}
end

c1 = make_counter
c1.call                   # => 1
c1.call                   # => 2
c1.call                   # => 3

c2 = make_counter         # => #<Proc:0x000258dc@-:3>

puts quot;c1 = #{c1.call}, c2 = #{c2.call}quot;
# >> c1 = 4, c2 = 1




                                      - 1/1 -
open_employee.rb                                           2007-11-07
require File.dirname(__FILE__) + quot;/../01. classes/hrquot;

=begin rdoc
  Open class demonstration, add a method and atribute to
  an existing class
=end
class Employee
  attr_accessor :birth_year

  def age
    Time.now.year - birth_year;
  end

end

e = Employee.new quot;Homerquot;, 20000
e.birth_year = 1950
puts quot;Age is #{e.age}quot;



=begin rdoc
  Add method to an object instance
=end

def e.big_raise(by_perc)
    @salary += (@salary * (by_perc * 0.1))
end

old_salary = e.salary
e.big_raise(5)
puts quot;Big money! From #{old_salary} to #{e.salary}quot;

=begin rdoc
  Overwriting a method from an open class
=end

def e.raise_salary_by(perc)
  @salary -= (@salary * (perc * 0.01))
end

old_salary = e.salary
e.raise_salary_by(5)
puts quot;Small money! From #{old_salary} to #{e.salary}quot;



                                     - 1/1 -
hr_mixin.rb                                                    2007-04-22
module Debug
  def who_am_i?
    quot;#{self.class.name} (##{self.object_id}): #{self.to_s}quot;
  end
end

class Employee
  include Debug
  def initialize(name, salary, hire_year)
    @name = name
    @salary = salary
    @hire_year = hire_year
  end

  def to_s
    quot;Name is #{@name}, salary is #{@salary}, quot; +
    quot;hire year is #{@hire_year}quot;
  end

  def raise_salary_by(perc)
    @salary += (@salary * 0.10)
  end
end

class Manager < Employee
  #include Debug
  def initialize(name, salary, hire_year, asst)
    super(name, salary, hire_year)
    @asst = asst
  end

  def to_s
    super + quot;,tAssistant info: #{@asst}quot;
  end

  def raise_salary_by(perc)
    perc += 2005 - @hire_year
    super(perc)
  end
end



def show(emps)
  emps.each { |e| puts e }

                                    - 1/2 -
hr_mixin.rb                                                       2007-04-22
end

employees = Array.new
employees[0] = Employee.new(quot;Homerquot;, 200.0, 1995)
employees[1] = Employee.new(quot;Lennyquot;, 150.0, 2000)
employees[2] = Employee.new(quot;Carlquot;, 250.0, 1999)
employees[3] = Manager.new(quot;Montyquot;, 3000.0, 1950, employees[2])

show(employees)

puts quot;nnWho are they?quot;
puts employees[0].who_am_i?
puts employees[3].who_am_i?




                                    - 2/2 -
hello_frame.rb                                                       2007-04-22
#!/usr/bin/env ruby

require quot;javaquot;

BorderLayout = java.awt.BorderLayout
JButton = javax.swing.JButton
JFrame = javax.swing.JFrame
JLabel = javax.swing.JLabel
JOptionPane = javax.swing.JOptionPane
JPanel = javax.swing.JPanel
JTextField = javax.swing.JTextField

# BlockActionListener is ActionListener whose constructor takes a Ruby block.
# It holds the block and invokes it when actionPerformed is called.
class BlockActionListener < java.awt.event.ActionListener
  # super call is needed for now
  def initialize(&block)
    super
    @block = block
  end

  def actionPerformed(e)
    @block.call(e)
  end
end

# Extend Swing JButton class with a new constructor that takes the button text
# and a Ruby block to be invoked when the button is pressed.
class JButton
  def initialize(name, &block)
    super(name)
    addActionListener(BlockActionListener.new(&block))
  end
end

# Define a class that represents the JFrame implementation of the GUI.
class HelloFrame < JFrame
  def initialize
    super(quot;Hello Swing!quot;)
    populate
    pack
    resizable = false
    defaultCloseOperation = JFrame::EXIT_ON_CLOSE
  end

                                    - 1/2 -
hello_frame.rb                                                       2007-04-22

  def populate
    name_panel = JPanel.new
    name_panel.add JLabel.new(quot;Name:quot;)
    name_field = JTextField.new(20)
    name_panel.add name_field

    button_panel = JPanel.new
    # Note how a block is passed to the JButton constructor.
    greet_button = JButton.new(quot;Greetquot;) do
      name = name_field.text
      # Demonstrate display of HTML in a dialog box.
      msg = %(<html>Hello <span style=quot;color:redquot;>#{name}</span>!</html>)
      JOptionPane.showMessageDialog self, msg
    end
    button_panel.add greet_button
    # Note how a block is passed to the JButton constructor.
    clear_button = JButton.new(quot;Clearquot;) { name_field.text = quot;quot; }
    button_panel.add clear_button

    contentPane.add name_panel, BorderLayout::CENTER
    contentPane.add button_panel, BorderLayout::SOUTH
  end
end # of HelloFrame class

HelloFrame.new.visible = true




                                    - 2/2 -
comparisons.rb                                                       2007-08-20
require File.dirname(__FILE__) + quot;/../01. classes/hrquot;

class Employee
  include Comparable

  def <=>(other)
      name <=> other.name
  end
end

list   = Array.new
list   << Employee.new(quot;Montyquot;, 10000)
list   << Employee.new(quot;Homerquot;, 50000)
list   << Employee.new(quot;Bartquot;, 5000)



puts list

list.sort!

puts list

p quot;Monty vs. Homerquot;, list[0] < list[1]
p quot;Homer vs. Montyquot;, list[0] > list[1]

p quot;Homer is between Bart and Monty?quot;, list[1].between(list[0], list[2])




                                         - 1/1 -
array_list_proxy.rb                                                   2007-04-22
#!/usr/bin/env ruby

require quot;javaquot;
include_class quot;java.util.ArrayListquot;
list = ArrayList.new
%w(Red Green Blue).each { |color| list.add(color) }

# Add quot;firstquot; method to proxy of Java ArrayList class.
class ArrayList
  def first
    size == 0 ? nil : get(0)
  end
end
puts quot;first item is #{list.first}quot;

# Add quot;lastquot; method only to the list object ... a singleton method.
def list.last
  size == 0 ? nil : get(size - 1)
end
puts quot;last item is #{list.last}quot;




                                    - 1/1 -
Car.java                                                           2007-04-22
public class Car {
      private String make;
      private String model;
      private int year;

      public Car() {}

      public Car(String make, String model, int year) {
        this.make = make;
        this.model = model;
        this.year = year;
      }

      public String getMake() { return make; }
      public String getModel() { return model; }
      public int getYear() { return year; }

      public void setMake(String make) { this.make = make; }
      public void setModel(String model) { this.model = model; }
      public void setYear(int year) { this.year = year; }

      public String toString() {
        return year + quot; quot; + make + quot; quot; + model;
      }
}




                                    - 1/1 -
race_car.rb                                      2007-04-22
#!/usr/bin/env ruby
require quot;javaquot;

include_class quot;Carquot;

c = Car.new(quot;Hondaquot;, quot;Accordquot;, 1997)
puts c

class RaceCar < Car
  attr_accessor :top_speed

  def initialize(
    make=nil, model=nil, year=0, top_speed=0)
    super(make, model, year)
    @top_speed = top_speed
  end

  def to_s
    quot;#{super} can go #{@top_speed} MPHquot;
  end
end

c = RaceCar.new(quot;Ferrariquot;, quot;F430quot;, 2005, 196)
puts c

c = RaceCar.new(quot;Porchequot;, quot;917quot;)
c.year = 1971
c.top_speed = 248
puts c




                                       - 1/1 -
order_interaction_test.rb                                             2007-08-20
require 'test/unit'
require 'rubygems'
require 'mocha'

require quot;javaquot;
require quot;Warehouse.jarquot;
OrderImpl = com.nealford.conf.jmock.warehouse.OrderImpl
Order = com.nealford.conf.jmock.warehouse.Order
Warehouse = com.nealford.conf.jmock.warehouse.Warehouse
WarehouseImpl = com.nealford.conf.jmock.warehouse.WarehouseImpl



class OrderInteractionTest < Test::Unit::TestCase
  TALISKER = quot;Taliskerquot;

  def test_filling_removes_inventory_if_in_stock
    order = OrderImpl.new(TALISKER, 50)
    warehouse = Warehouse.new
    warehouse.stubs(:hasInventory).with(TALISKER, 50).returns(true)
    warehouse.stubs(:remove).with(TALISKER, 50)

    order.fill(warehouse)
    assert order.is_filled
  end

  def test_filling_does_not_remove_if_not_enough_in_stock
    order = OrderImpl.new(TALISKER, 51)
    warehouse = Warehouse.new
    warehouse.stubs(:hasInventory).returns(false)
    order.fill(warehouse)

    assert   !order.is_filled
  end

end




                                    - 1/1 -

Contenu connexe

Tendances

RJB - another choice for Ruby and Java interoperability
RJB - another choice for Ruby and Java interoperabilityRJB - another choice for Ruby and Java interoperability
RJB - another choice for Ruby and Java interoperabilityAkio Tajima
 
Ruby On Rails Basics
Ruby On Rails BasicsRuby On Rails Basics
Ruby On Rails BasicsAmit Solanki
 
Ruby on Rails survival guide of an aged Java developer
Ruby on Rails survival guide of an aged Java developerRuby on Rails survival guide of an aged Java developer
Ruby on Rails survival guide of an aged Java developergicappa
 
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 TorqueBoxbobmcwhirter
 
TorqueBox for Rubyists
TorqueBox for RubyistsTorqueBox for Rubyists
TorqueBox for Rubyistsbobmcwhirter
 
Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)
Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)
Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)ngotogenome
 
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...bobmcwhirter
 
Expert JavaScript Programming
Expert JavaScript ProgrammingExpert JavaScript Programming
Expert JavaScript ProgrammingYoshiki Shibukawa
 
Introduction To Grails
Introduction To GrailsIntroduction To Grails
Introduction To GrailsEric Berry
 
Type script, for dummies
Type script, for dummiesType script, for dummies
Type script, for dummiessantiagoaguiar
 
MacRuby: What is it? and why should you care?
MacRuby: What is it? and why should you care?MacRuby: What is it? and why should you care?
MacRuby: What is it? and why should you care?Joshua Ballanco
 
How to develop Jenkins plugin using to ruby and Jenkins.rb
How to develop Jenkins plugin using to ruby and Jenkins.rbHow to develop Jenkins plugin using to ruby and Jenkins.rb
How to develop Jenkins plugin using to ruby and Jenkins.rbHiroshi SHIBATA
 
Asynchronous I/O in NodeJS - new standard or challenges?
Asynchronous I/O in NodeJS - new standard or challenges?Asynchronous I/O in NodeJS - new standard or challenges?
Asynchronous I/O in NodeJS - new standard or challenges?Dinh Pham
 
Ruby C extensions at the Ruby drink-up of Sophia, April 2012
Ruby C extensions at the Ruby drink-up of Sophia, April 2012Ruby C extensions at the Ruby drink-up of Sophia, April 2012
Ruby C extensions at the Ruby drink-up of Sophia, April 2012rivierarb
 
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory CourseRuby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Coursepeter_marklund
 

Tendances (20)

RJB - another choice for Ruby and Java interoperability
RJB - another choice for Ruby and Java interoperabilityRJB - another choice for Ruby and Java interoperability
RJB - another choice for Ruby and Java interoperability
 
Rjb
RjbRjb
Rjb
 
Ruby On Rails Basics
Ruby On Rails BasicsRuby On Rails Basics
Ruby On Rails Basics
 
Ruby on Rails survival guide of an aged Java developer
Ruby on Rails survival guide of an aged Java developerRuby on Rails survival guide of an aged Java developer
Ruby on Rails survival guide of an aged Java developer
 
Ruby on Rails
Ruby on RailsRuby on Rails
Ruby on Rails
 
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
 
TorqueBox for Rubyists
TorqueBox for RubyistsTorqueBox for Rubyists
TorqueBox for Rubyists
 
Ruby on Rails for beginners
Ruby on Rails for beginnersRuby on Rails for beginners
Ruby on Rails for beginners
 
Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)
Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)
Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)
 
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...
 
Expert JavaScript Programming
Expert JavaScript ProgrammingExpert JavaScript Programming
Expert JavaScript Programming
 
RubyGems 3 & 4
RubyGems 3 & 4RubyGems 3 & 4
RubyGems 3 & 4
 
Introduction To Grails
Introduction To GrailsIntroduction To Grails
Introduction To Grails
 
Type script, for dummies
Type script, for dummiesType script, for dummies
Type script, for dummies
 
MacRuby: What is it? and why should you care?
MacRuby: What is it? and why should you care?MacRuby: What is it? and why should you care?
MacRuby: What is it? and why should you care?
 
How to develop Jenkins plugin using to ruby and Jenkins.rb
How to develop Jenkins plugin using to ruby and Jenkins.rbHow to develop Jenkins plugin using to ruby and Jenkins.rb
How to develop Jenkins plugin using to ruby and Jenkins.rb
 
Asynchronous I/O in NodeJS - new standard or challenges?
Asynchronous I/O in NodeJS - new standard or challenges?Asynchronous I/O in NodeJS - new standard or challenges?
Asynchronous I/O in NodeJS - new standard or challenges?
 
Ruby C extensions at the Ruby drink-up of Sophia, April 2012
Ruby C extensions at the Ruby drink-up of Sophia, April 2012Ruby C extensions at the Ruby drink-up of Sophia, April 2012
Ruby C extensions at the Ruby drink-up of Sophia, April 2012
 
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory CourseRuby on Rails 101 - Presentation Slides for a Five Day Introductory Course
Ruby on Rails 101 - Presentation Slides for a Five Day Introductory Course
 
Devignition 2011
Devignition 2011Devignition 2011
Devignition 2011
 

Similaire à Introduction to JRuby

Java, Ruby & Rails
Java, Ruby & RailsJava, Ruby & Rails
Java, Ruby & RailsPeter Lind
 
XRuby_Overview_20070831
XRuby_Overview_20070831XRuby_Overview_20070831
XRuby_Overview_20070831dreamhead
 
Dynamic Languages on the JVM
Dynamic Languages on the JVMDynamic Languages on the JVM
Dynamic Languages on the JVMelliando dias
 
JRuby - Programmer's Best Friend on JVM
JRuby - Programmer's Best Friend on JVMJRuby - Programmer's Best Friend on JVM
JRuby - Programmer's Best Friend on JVMRaimonds Simanovskis
 
Ruby on Rails Training - Module 1
Ruby on Rails Training - Module 1Ruby on Rails Training - Module 1
Ruby on Rails Training - Module 1Mark Menard
 
OOP with Java
OOP with JavaOOP with Java
OOP with JavaOmegaHub
 
Introduction to JRuby And JRuby on Rails
Introduction to JRuby And JRuby on RailsIntroduction to JRuby And JRuby on Rails
Introduction to JRuby And JRuby on RailsFramgia Vietnam
 
Jruby synergy-of-ruby-and-java
Jruby synergy-of-ruby-and-javaJruby synergy-of-ruby-and-java
Jruby synergy-of-ruby-and-javaKeith Bennett
 
Bitter Java, Sweeten with JRuby
Bitter Java, Sweeten with JRubyBitter Java, Sweeten with JRuby
Bitter Java, Sweeten with JRubyBrian Sam-Bodden
 
Java interview questions and answers for cognizant By Data Council Pune
Java interview questions and answers for cognizant By Data Council PuneJava interview questions and answers for cognizant By Data Council Pune
Java interview questions and answers for cognizant By Data Council PunePankaj kshirsagar
 
Workin ontherailsroad
Workin ontherailsroadWorkin ontherailsroad
Workin ontherailsroadJim Jones
 
WorkinOnTheRailsRoad
WorkinOnTheRailsRoadWorkinOnTheRailsRoad
WorkinOnTheRailsRoadwebuploader
 
Java for Mainframers
Java for MainframersJava for Mainframers
Java for MainframersRich Helton
 
Devoxx%202008%20Tutorial
Devoxx%202008%20TutorialDevoxx%202008%20Tutorial
Devoxx%202008%20Tutorialtutorialsruby
 

Similaire à Introduction to JRuby (20)

Java, Ruby & Rails
Java, Ruby & RailsJava, Ruby & Rails
Java, Ruby & Rails
 
Practical JRuby
Practical JRubyPractical JRuby
Practical JRuby
 
JRuby Basics
JRuby BasicsJRuby Basics
JRuby Basics
 
XRuby_Overview_20070831
XRuby_Overview_20070831XRuby_Overview_20070831
XRuby_Overview_20070831
 
Dynamic Languages on the JVM
Dynamic Languages on the JVMDynamic Languages on the JVM
Dynamic Languages on the JVM
 
JRuby - Programmer's Best Friend on JVM
JRuby - Programmer's Best Friend on JVMJRuby - Programmer's Best Friend on JVM
JRuby - Programmer's Best Friend on JVM
 
Ruby on Rails Training - Module 1
Ruby on Rails Training - Module 1Ruby on Rails Training - Module 1
Ruby on Rails Training - Module 1
 
OOP with Java
OOP with JavaOOP with Java
OOP with Java
 
Ruby Metaprogramming 08
Ruby Metaprogramming 08Ruby Metaprogramming 08
Ruby Metaprogramming 08
 
Introduction to JRuby And JRuby on Rails
Introduction to JRuby And JRuby on RailsIntroduction to JRuby And JRuby on Rails
Introduction to JRuby And JRuby on Rails
 
Jruby synergy-of-ruby-and-java
Jruby synergy-of-ruby-and-javaJruby synergy-of-ruby-and-java
Jruby synergy-of-ruby-and-java
 
Bitter Java, Sweeten with JRuby
Bitter Java, Sweeten with JRubyBitter Java, Sweeten with JRuby
Bitter Java, Sweeten with JRuby
 
Viva file
Viva fileViva file
Viva file
 
Java interview questions and answers for cognizant By Data Council Pune
Java interview questions and answers for cognizant By Data Council PuneJava interview questions and answers for cognizant By Data Council Pune
Java interview questions and answers for cognizant By Data Council Pune
 
Workin ontherailsroad
Workin ontherailsroadWorkin ontherailsroad
Workin ontherailsroad
 
WorkinOnTheRailsRoad
WorkinOnTheRailsRoadWorkinOnTheRailsRoad
WorkinOnTheRailsRoad
 
Java for Mainframers
Java for MainframersJava for Mainframers
Java for Mainframers
 
Java1
Java1Java1
Java1
 
Java
Java Java
Java
 
Devoxx%202008%20Tutorial
Devoxx%202008%20TutorialDevoxx%202008%20Tutorial
Devoxx%202008%20Tutorial
 

Plus de elliando dias

Clojurescript slides
Clojurescript slidesClojurescript slides
Clojurescript slideselliando dias
 
Why you should be excited about ClojureScript
Why you should be excited about ClojureScriptWhy you should be excited about ClojureScript
Why you should be excited about ClojureScriptelliando dias
 
Functional Programming with Immutable Data Structures
Functional Programming with Immutable Data StructuresFunctional Programming with Immutable Data Structures
Functional Programming with Immutable Data Structureselliando dias
 
Nomenclatura e peças de container
Nomenclatura  e peças de containerNomenclatura  e peças de container
Nomenclatura e peças de containerelliando dias
 
Polyglot and Poly-paradigm Programming for Better Agility
Polyglot and Poly-paradigm Programming for Better AgilityPolyglot and Poly-paradigm Programming for Better Agility
Polyglot and Poly-paradigm Programming for Better Agilityelliando dias
 
Javascript Libraries
Javascript LibrariesJavascript Libraries
Javascript Librarieselliando dias
 
How to Make an Eight Bit Computer and Save the World!
How to Make an Eight Bit Computer and Save the World!How to Make an Eight Bit Computer and Save the World!
How to Make an Eight Bit Computer and Save the World!elliando dias
 
A Practical Guide to Connecting Hardware to the Web
A Practical Guide to Connecting Hardware to the WebA Practical Guide to Connecting Hardware to the Web
A Practical Guide to Connecting Hardware to the Webelliando dias
 
Introdução ao Arduino
Introdução ao ArduinoIntrodução ao Arduino
Introdução ao Arduinoelliando dias
 
Incanter Data Sorcery
Incanter Data SorceryIncanter Data Sorcery
Incanter Data Sorceryelliando dias
 
Fab.in.a.box - Fab Academy: Machine Design
Fab.in.a.box - Fab Academy: Machine DesignFab.in.a.box - Fab Academy: Machine Design
Fab.in.a.box - Fab Academy: Machine Designelliando dias
 
The Digital Revolution: Machines that makes
The Digital Revolution: Machines that makesThe Digital Revolution: Machines that makes
The Digital Revolution: Machines that makeselliando dias
 
Hadoop - Simple. Scalable.
Hadoop - Simple. Scalable.Hadoop - Simple. Scalable.
Hadoop - Simple. Scalable.elliando dias
 
Hadoop and Hive Development at Facebook
Hadoop and Hive Development at FacebookHadoop and Hive Development at Facebook
Hadoop and Hive Development at Facebookelliando dias
 
Multi-core Parallelization in Clojure - a Case Study
Multi-core Parallelization in Clojure - a Case StudyMulti-core Parallelization in Clojure - a Case Study
Multi-core Parallelization in Clojure - a Case Studyelliando dias
 

Plus de elliando dias (20)

Clojurescript slides
Clojurescript slidesClojurescript slides
Clojurescript slides
 
Why you should be excited about ClojureScript
Why you should be excited about ClojureScriptWhy you should be excited about ClojureScript
Why you should be excited about ClojureScript
 
Functional Programming with Immutable Data Structures
Functional Programming with Immutable Data StructuresFunctional Programming with Immutable Data Structures
Functional Programming with Immutable Data Structures
 
Nomenclatura e peças de container
Nomenclatura  e peças de containerNomenclatura  e peças de container
Nomenclatura e peças de container
 
Geometria Projetiva
Geometria ProjetivaGeometria Projetiva
Geometria Projetiva
 
Polyglot and Poly-paradigm Programming for Better Agility
Polyglot and Poly-paradigm Programming for Better AgilityPolyglot and Poly-paradigm Programming for Better Agility
Polyglot and Poly-paradigm Programming for Better Agility
 
Javascript Libraries
Javascript LibrariesJavascript Libraries
Javascript Libraries
 
How to Make an Eight Bit Computer and Save the World!
How to Make an Eight Bit Computer and Save the World!How to Make an Eight Bit Computer and Save the World!
How to Make an Eight Bit Computer and Save the World!
 
Ragel talk
Ragel talkRagel talk
Ragel talk
 
A Practical Guide to Connecting Hardware to the Web
A Practical Guide to Connecting Hardware to the WebA Practical Guide to Connecting Hardware to the Web
A Practical Guide to Connecting Hardware to the Web
 
Introdução ao Arduino
Introdução ao ArduinoIntrodução ao Arduino
Introdução ao Arduino
 
Minicurso arduino
Minicurso arduinoMinicurso arduino
Minicurso arduino
 
Incanter Data Sorcery
Incanter Data SorceryIncanter Data Sorcery
Incanter Data Sorcery
 
Rango
RangoRango
Rango
 
Fab.in.a.box - Fab Academy: Machine Design
Fab.in.a.box - Fab Academy: Machine DesignFab.in.a.box - Fab Academy: Machine Design
Fab.in.a.box - Fab Academy: Machine Design
 
The Digital Revolution: Machines that makes
The Digital Revolution: Machines that makesThe Digital Revolution: Machines that makes
The Digital Revolution: Machines that makes
 
Hadoop + Clojure
Hadoop + ClojureHadoop + Clojure
Hadoop + Clojure
 
Hadoop - Simple. Scalable.
Hadoop - Simple. Scalable.Hadoop - Simple. Scalable.
Hadoop - Simple. Scalable.
 
Hadoop and Hive Development at Facebook
Hadoop and Hive Development at FacebookHadoop and Hive Development at Facebook
Hadoop and Hive Development at Facebook
 
Multi-core Parallelization in Clojure - a Case Study
Multi-core Parallelization in Clojure - a Case StudyMulti-core Parallelization in Clojure - a Case Study
Multi-core Parallelization in Clojure - a Case Study
 

Dernier

Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
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
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
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
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesZilliz
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 

Dernier (20)

Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
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!
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
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
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector Databases
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 

Introduction to JRuby

  • 1. ThoughtWorks Introduction to JRuby NEAL FORD thoughtworker / meme wrangler ThoughtWorks 14 Wall St, Suite 2019, New York, NY 10005 nford@thoughtworks.com www.nealford.com www.thoughtworks.com memeagora.blogspot.com ThoughtWorks Questions, Slides, & Samples Please feel free to ask questions anytime Slides and samples at www.nealford.com
  • 2. ThoughtWorks What This Session Covers: Motivation for JRuby What makes Ruby cool? Classes & objects Closures Mixins Idioms Ruby + Java ThoughtWorks Why Ruby? Purely object-oriented Dynamically typed (“duck typed”) Compact syntax Closures Open classes Awesome meta-programming support Rails
  • 3. ThoughtWorks What is JRuby? JRuby is the Ruby interpreter, rewritten in Java MRI (Matz Reference Implementation) written in C and Ruby JRuby developers ported the C code to Java Now produces byte code The compiler is done (available in the JRuby 1.1 release) Faster than MRI on almost all benchmarks!!! ThoughtWorks Why JRuby? JRuby == Ruby on the JVM Allows Java capabilities with Ruby syntax Smart about properties Access to Java libraries Ruby libraries from Java Supports all Ruby syntax and built-in libraries Easy to port the libraries written in Ruby C libraries ported to Java
  • 4. ThoughtWorks Motivations Use Java libraries (i.e., Swing) from Ruby code Use Ruby libraries (i.e., ActiveRecord) from Java Using Bean Scripting Framework (JDK <= 1.5) Using JSR 223 Scripting API (JDK > 1.5) Get an (eventually) faster Ruby Much slower now Lessons learned from IronPython ThoughtWorks What JRuby Gives You JRuby classes can Inherit from Java classes Implement Java interfaces Open Java classes (visible from JRuby, not Java) Running on the JVM provides Native threads Unicode Support Portability
  • 5. ThoughtWorks Current Limitations Does not support continuations/bindings Fine-grained timer Benchmarking code depends on finer grained timings than the JVM supports Solved(?) in a future JVM via a current JSR Identical thread behavior Missing File operations The JVM is missing some file operations needed by File and friends in Ruby ThoughtWorks Some Ruby Syntax Just the interesting stuff Example hr.rb hr_runner.rb Tests test_employee.rb test_manager.rb test_all.rb
  • 6. ThoughtWorks Ruby Blocks Delineated with either { . . . } # idiomatically used for single line blocks do . . . end # idiomatically used for multi-line blocks Both support parameters with |my_param| Examples hr_blocks.rb hr_blocks_ruby_way.rb ThoughtWorks What Makes a Block a Closure? A closure object has Code to run (the executable) State around the code (the environment, including the local variables) The closure captures the environment You can reference the local variable inside the closure... ...even if the variable has gone out of scope Example hr_closures.rb
  • 7. ThoughtWorks Important Closure Characteristics Closures combine a block of code with an environment Sets it apart from function pointers, et al Java’s anonymous inner classes can access locals (only if they are final) Require very little syntax Crucial because they are used all the time Cumbersome to create something like an anonymous inner class all the time ThoughtWorks Open Classes Ruby allows you to “open” classes When you write a class definition that already appears on the classpath, Ruby opens the class You can make changes to the class Methods Member variables Method characteristics You can also add methods to object instances open_employee
  • 8. ThoughtWorks Modules Allow you to group classes, method, and constants Provide two major benefits Namespaces Mixins Mixins are Ruby’s alternatives to Multiple inheritance Interfaces ThoughtWorks Mixins When you include a module into a class, the modules methods are mixed into the class Methods defined in the module can interact with instance variables of the class Don’t be fooled by the include keyword Not like a C/C++ include Class references the module (i.e., no copying) Example: hr_mixin.rb
  • 9. ThoughtWorks Using Java Classes in Ruby Must contain require “java” 5 options Provide full class name when using frame = javax.swing.JFrame.new(quot;My Titlequot;) Assign full class name to a constant. JFrame = javax.swing.JFrame frame = JFrame.new(quot;My Titlequot;) Use include_class include_class quot;javax.swing.JFramequot; frame = JFrame.new(quot;My Titlequot;) ThoughtWorks Using Java Classes in Ruby 5 options (continued) Use include_class with an alias Useful when Java class name matches Ruby class name include_class(quot;java.lang.Stringquot;) do |pkg_name, class_name| quot;J#{class_name}quot; end msg = JString.new(quot;My Messagequot;) Use include_package to scope Java classes in a Ruby module namespace (only in a module) module Swing include_package quot;javax.swingquot; end frame = Swing::JFrame.new(quot;My Titlequot;)
  • 10. ThoughtWorks Calling Semantics Parenthesis aren’t required when calling methods Java get/set/is methods are invoked like Ruby accessors emp.getName() => e.name emp.setName(“Homer”) => e.name = “Homer” emp.isManager() => e.manager? Camelcase Java names can be called with underscores require quot;javaquot; url = java.net.URL.new(quot;http://www.nealford.comquot;) puts url.to_external_form # method name is toExternalForm puts url.to_uri # method name is toURI ThoughtWorks Building Swing in Ruby Much friendlier syntax Dynamic typing cuts way down on useless code Uses blocks intelligently Define button click behavior in a block at definition Example hello_frame.rb
  • 11. ThoughtWorks Ruby Methods Added to Core Java JRuby adds lots of methods to core JDK classes Decorated all the collections classes to make them “humane” Added operators to String and type wrappers <=>, <, <=, =>, >, between? Example JRuby Super Console ThoughtWorks Proxy Classes JRuby builds proxies for Java classes Allows open classes with Java Add methods to the class Add methods to the object instance Example array_list_proxy.rb
  • 12. ThoughtWorks JRuby Inheriting from Java Classes JRuby classes can inherit from Java classes Example Car.java race_car.rb ThoughtWorks Testing Java with JRuby You can use JRuby to write unit tests against Java code Including powerful mock-object libraries from Ruby (like Mocha) Example OrderInteractionTester.java OrderInteractionTest.rb Mocha provides Mocks and stubs Automatic verification
  • 13. ThoughtWorks JRuby on Rails Yes, Rails now runs on JRuby You can build a WAR file from a Rails application and deploy it on a JVM Still slower than Ruby Still some manual tweaking for stuff like databases But it works! ThoughtWorks JRuby Advantages over Ruby Ola Bini’s recipe: Take one large Rails application with good Selenium test base Convert database configuration to use JDBC Start a selenium proxy with quot;jake test:selenium_proxyquot; Start acceptance testing from another window with quot;jake test:acceptancequot; In yet another window, write quot;jconsolequot; Choose your application
  • 14. ThoughtWorks The Result? ThoughtWorks Future Directions Performance, performance, performance! Improving the Rails experience Version 1.0 is the current version Version 1.1 (with compiler) soon
  • 15. ThoughtWorks Benchmarks ThoughtWorks Benchmarks
  • 16. ThoughtWorks JRuby vs. Groovy JRuby is an interpreter written in Java With compilation (in version 1.1) Interacts with Java classes via proxies Groovy is an alternative Java syntax Wraps Java classes with proxies Compiles to byte code ThoughtWorks JRuby vs. Groovy Groovy can only perform operations allowed by byte code in the JVM JRuby is free to do anything that Ruby can do The most powerful mainstream meta-programming language JRuby on Rails can do things that are difficult and impossible with Groovy Ruby is the most powerful mainstream language
  • 17. ThoughtWorks JRuby vs. Groovy Ruby/JRuby Java Groovy ThoughtWorks Resources The JRuby web site http://jruby.codehaus.org/ Includes documentation, tutorials, etc. Charles Nutter’s Blog http://headius.blogspot.com/ Ola Bini’s Blog http://ola-bini.blogspot.com/
  • 18. ThoughtWorks Questions? Please fill out the session evaluations Samples & slides at www.nealford.com NEAL FORD thoughtworker / meme wrangler ThoughtWorks 14 Wall St, Suite 2019, New York, NY 10005 This work is licensed under the Creative Commons nford@thoughtworks.com www.nealford.com Attribution-Noncommercial-Share Alike 2.5 License. www.thoughtworks.com memeagora.blogspot.com http://creativecommons.org/licenses/by-nc-sa/2.5/
  • 19. hr.rb 2007-04-22 class Employee def initialize(name, salary, hire_year) @name = name @salary = salary @hire_year = hire_year end attr_reader :salary, :hire_year def to_s quot;Name is #{@name}, salary is #{@salary}, quot; + quot;hire year is #{@hire_year}quot; end def raise_salary_by(perc) @salary += (@salary * (perc * 0.01)) end end class Manager < Employee def initialize(name, salary, hire_year, asst) super(name, salary, hire_year) @asst = asst end def to_s super + quot;,tAssistant info: #{@asst}quot; end def raise_salary_by(perc) perc += 2005 - @hire_year super(perc) end end - 1/1 -
  • 20. hr_runner.rb 2007-04-22 require 'hr' def show(emps) emps.each { |e| puts e } end employees = Array.new employees[0] = Employee.new(quot;Homerquot;, 200.0, 1995) employees[1] = Employee.new(quot;Lennyquot;, 150.0, 2000) employees[2] = Employee.new(quot;Carlquot;, 250.0, 1999) employees[3] = Manager.new(quot;Montyquot;, 3000.0, 1950, employees[2]) show(employees) employees.each { |e| e.raise_salary_by(10) } puts quot;nGive everyone a raisennquot; show employees - 1/1 -
  • 21. test_employee.rb 2007-04-22 require 'test/unit/testcase' require 'test/unit/autorunner' require 'hr' class TestEmployee < Test::Unit::TestCase @@Test_Salary = 2500 def setup @emp = Employee.new(quot;Homerquot;, @@Test_Salary, 2003) end def test_raise_salary @emp.raise_salary_by(10) expected = (@@Test_Salary * 0.10) + @@Test_Salary assert expected == @emp.salary end end - 1/1 -
  • 22. test_all.rb 2007-04-22 require 'test/unit/testsuite' require 'test/unit/ui/tk/testrunner' require 'test/unit/ui/console/testrunner' require 'test_employee' require 'test_manager' class TestSuite_AllTests def self.suite suite = Test::Unit::TestSuite.new(quot;HR Testsquot;) suite << TestEmployee.suite suite << TestManager.suite return suite end end # Test::Unit::UI::Tk::TestRunner.run(TestSuite_AllTests) Test::Unit::UI::Console::TestRunner.run(TestSuite_AllTests) - 1/1 -
  • 23. hr_blocks_4_ruby_way.rb 2007-04-22 class Employee attr_reader :name, :salary, :hire_year def initialize(name, salary, hire_year) @name = name @salary = salary @hire_year = hire_year end def to_s quot;Name is #{@name}, salary is #{@salary}, quot; + quot;hire year is #{@hire_year}quot; end def raise_salary_by(perc) @salary += (@salary * 0.10) end end class EmployeeList def initialize @employees = Array.new end def add(an_employee) @employees.push(an_employee) self end def delete_first @employees.shift end def delete_last @employees.pop end def show @employees.each { |e| puts e } end - 1/2 -
  • 24. hr_blocks_4_ruby_way.rb 2007-04-22 def [](key) return @employees[key] if key.kind_of?(Integer) return @employees.find do |anEmp| key == anEmp.name end return nil end end list = EmployeeList.new list.add(Employee.new(quot;Homerquot;, 200.0, 1995)). add(Employee.new(quot;Lennyquot;, 150.0, 2000)). add(Employee.new(quot;Carlquot;, 250.0, 1999)) list.show puts quot;Employee #1 is quot; + list[0].to_s puts quot;Employee named 'Homer' is quot; + list[quot;Homerquot;].to_s - 2/2 -
  • 25. hr_closures.rb 2007-04-22 #!/usr/bin/env ruby class Employee def initialize(name, salary) @name = name @salary = salary end attr_accessor :name, :salary def to_s quot;#{@name} makes #{@salary}quot; end end - 1/1 -
  • 26. hr_closures_runner.rb 2007-04-22 #!/usr/bin/env ruby # # Created by Neal Ford on 2007-04-20. # Copyright (c) 2007. All rights reserved. require 'hr_closures' def high_paid(emps) threshold = 40000 return emps.select {|e| e.salary > threshold} end def paid_more(amount) return Proc.new {|e| e.salary > amount} end employees = Array.new employees << Employee.new(quot;Homerquot;, 15000) employees << Employee.new(quot;Montyquot;, 100000) employees << Employee.new(quot;Smithersquot;, 80000) employees << Employee.new(quot;Carlquot;, 50000) employees << Employee.new(quot;Lennyquot;, 55000) puts quot;Closures that capture local variable scopequot; 20.times { print '-'} puts puts high_paid(employees) puts puts quot;Closures that capture definition scopequot; 20.times { print '-'} puts is_high_paid = paid_more(60000) puts is_high_paid.call(employees[0]) puts is_high_paid.call(employees[2]) - 1/1 -
  • 27. make_counter.rb 2007-08-20 def make_counter var = 0 # lambda { var += 1 } proc { var += 1} end c1 = make_counter c1.call # => 1 c1.call # => 2 c1.call # => 3 c2 = make_counter # => #<Proc:0x000258dc@-:3> puts quot;c1 = #{c1.call}, c2 = #{c2.call}quot; # >> c1 = 4, c2 = 1 - 1/1 -
  • 28. open_employee.rb 2007-11-07 require File.dirname(__FILE__) + quot;/../01. classes/hrquot; =begin rdoc Open class demonstration, add a method and atribute to an existing class =end class Employee attr_accessor :birth_year def age Time.now.year - birth_year; end end e = Employee.new quot;Homerquot;, 20000 e.birth_year = 1950 puts quot;Age is #{e.age}quot; =begin rdoc Add method to an object instance =end def e.big_raise(by_perc) @salary += (@salary * (by_perc * 0.1)) end old_salary = e.salary e.big_raise(5) puts quot;Big money! From #{old_salary} to #{e.salary}quot; =begin rdoc Overwriting a method from an open class =end def e.raise_salary_by(perc) @salary -= (@salary * (perc * 0.01)) end old_salary = e.salary e.raise_salary_by(5) puts quot;Small money! From #{old_salary} to #{e.salary}quot; - 1/1 -
  • 29. hr_mixin.rb 2007-04-22 module Debug def who_am_i? quot;#{self.class.name} (##{self.object_id}): #{self.to_s}quot; end end class Employee include Debug def initialize(name, salary, hire_year) @name = name @salary = salary @hire_year = hire_year end def to_s quot;Name is #{@name}, salary is #{@salary}, quot; + quot;hire year is #{@hire_year}quot; end def raise_salary_by(perc) @salary += (@salary * 0.10) end end class Manager < Employee #include Debug def initialize(name, salary, hire_year, asst) super(name, salary, hire_year) @asst = asst end def to_s super + quot;,tAssistant info: #{@asst}quot; end def raise_salary_by(perc) perc += 2005 - @hire_year super(perc) end end def show(emps) emps.each { |e| puts e } - 1/2 -
  • 30. hr_mixin.rb 2007-04-22 end employees = Array.new employees[0] = Employee.new(quot;Homerquot;, 200.0, 1995) employees[1] = Employee.new(quot;Lennyquot;, 150.0, 2000) employees[2] = Employee.new(quot;Carlquot;, 250.0, 1999) employees[3] = Manager.new(quot;Montyquot;, 3000.0, 1950, employees[2]) show(employees) puts quot;nnWho are they?quot; puts employees[0].who_am_i? puts employees[3].who_am_i? - 2/2 -
  • 31. hello_frame.rb 2007-04-22 #!/usr/bin/env ruby require quot;javaquot; BorderLayout = java.awt.BorderLayout JButton = javax.swing.JButton JFrame = javax.swing.JFrame JLabel = javax.swing.JLabel JOptionPane = javax.swing.JOptionPane JPanel = javax.swing.JPanel JTextField = javax.swing.JTextField # BlockActionListener is ActionListener whose constructor takes a Ruby block. # It holds the block and invokes it when actionPerformed is called. class BlockActionListener < java.awt.event.ActionListener # super call is needed for now def initialize(&block) super @block = block end def actionPerformed(e) @block.call(e) end end # Extend Swing JButton class with a new constructor that takes the button text # and a Ruby block to be invoked when the button is pressed. class JButton def initialize(name, &block) super(name) addActionListener(BlockActionListener.new(&block)) end end # Define a class that represents the JFrame implementation of the GUI. class HelloFrame < JFrame def initialize super(quot;Hello Swing!quot;) populate pack resizable = false defaultCloseOperation = JFrame::EXIT_ON_CLOSE end - 1/2 -
  • 32. hello_frame.rb 2007-04-22 def populate name_panel = JPanel.new name_panel.add JLabel.new(quot;Name:quot;) name_field = JTextField.new(20) name_panel.add name_field button_panel = JPanel.new # Note how a block is passed to the JButton constructor. greet_button = JButton.new(quot;Greetquot;) do name = name_field.text # Demonstrate display of HTML in a dialog box. msg = %(<html>Hello <span style=quot;color:redquot;>#{name}</span>!</html>) JOptionPane.showMessageDialog self, msg end button_panel.add greet_button # Note how a block is passed to the JButton constructor. clear_button = JButton.new(quot;Clearquot;) { name_field.text = quot;quot; } button_panel.add clear_button contentPane.add name_panel, BorderLayout::CENTER contentPane.add button_panel, BorderLayout::SOUTH end end # of HelloFrame class HelloFrame.new.visible = true - 2/2 -
  • 33. comparisons.rb 2007-08-20 require File.dirname(__FILE__) + quot;/../01. classes/hrquot; class Employee include Comparable def <=>(other) name <=> other.name end end list = Array.new list << Employee.new(quot;Montyquot;, 10000) list << Employee.new(quot;Homerquot;, 50000) list << Employee.new(quot;Bartquot;, 5000) puts list list.sort! puts list p quot;Monty vs. Homerquot;, list[0] < list[1] p quot;Homer vs. Montyquot;, list[0] > list[1] p quot;Homer is between Bart and Monty?quot;, list[1].between(list[0], list[2]) - 1/1 -
  • 34. array_list_proxy.rb 2007-04-22 #!/usr/bin/env ruby require quot;javaquot; include_class quot;java.util.ArrayListquot; list = ArrayList.new %w(Red Green Blue).each { |color| list.add(color) } # Add quot;firstquot; method to proxy of Java ArrayList class. class ArrayList def first size == 0 ? nil : get(0) end end puts quot;first item is #{list.first}quot; # Add quot;lastquot; method only to the list object ... a singleton method. def list.last size == 0 ? nil : get(size - 1) end puts quot;last item is #{list.last}quot; - 1/1 -
  • 35. Car.java 2007-04-22 public class Car { private String make; private String model; private int year; public Car() {} public Car(String make, String model, int year) { this.make = make; this.model = model; this.year = year; } public String getMake() { return make; } public String getModel() { return model; } public int getYear() { return year; } public void setMake(String make) { this.make = make; } public void setModel(String model) { this.model = model; } public void setYear(int year) { this.year = year; } public String toString() { return year + quot; quot; + make + quot; quot; + model; } } - 1/1 -
  • 36. race_car.rb 2007-04-22 #!/usr/bin/env ruby require quot;javaquot; include_class quot;Carquot; c = Car.new(quot;Hondaquot;, quot;Accordquot;, 1997) puts c class RaceCar < Car attr_accessor :top_speed def initialize( make=nil, model=nil, year=0, top_speed=0) super(make, model, year) @top_speed = top_speed end def to_s quot;#{super} can go #{@top_speed} MPHquot; end end c = RaceCar.new(quot;Ferrariquot;, quot;F430quot;, 2005, 196) puts c c = RaceCar.new(quot;Porchequot;, quot;917quot;) c.year = 1971 c.top_speed = 248 puts c - 1/1 -
  • 37. order_interaction_test.rb 2007-08-20 require 'test/unit' require 'rubygems' require 'mocha' require quot;javaquot; require quot;Warehouse.jarquot; OrderImpl = com.nealford.conf.jmock.warehouse.OrderImpl Order = com.nealford.conf.jmock.warehouse.Order Warehouse = com.nealford.conf.jmock.warehouse.Warehouse WarehouseImpl = com.nealford.conf.jmock.warehouse.WarehouseImpl class OrderInteractionTest < Test::Unit::TestCase TALISKER = quot;Taliskerquot; def test_filling_removes_inventory_if_in_stock order = OrderImpl.new(TALISKER, 50) warehouse = Warehouse.new warehouse.stubs(:hasInventory).with(TALISKER, 50).returns(true) warehouse.stubs(:remove).with(TALISKER, 50) order.fill(warehouse) assert order.is_filled end def test_filling_does_not_remove_if_not_enough_in_stock order = OrderImpl.new(TALISKER, 51) warehouse = Warehouse.new warehouse.stubs(:hasInventory).returns(false) order.fill(warehouse) assert !order.is_filled end end - 1/1 -