ruby for java developers
DESCRIPTION
Ruby for Java Developers. Neal Ford Architect Thought Works www.nealford.com www.thoughtworks.com [email protected] Blog: memeagora.blogspot.com. Questions, Slides, and Samples. Please feel free to ask questions anytime The slides and samples will be available at www.nealford.com - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/1.jpg)
Ruby for Java Developers
Neal FordArchitect
ThoughtWorkswww.nealford.com
Blog: memeagora.blogspot.com
![Page 2: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/2.jpg)
2
Questions, Slides, and Samples
• Please feel free to ask questions anytime• The slides and samples will be available at
www.nealford.com• I’ll show that address again at the end
![Page 3: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/3.jpg)
3
What This Session Covers:
• The Ruby Philosophy• Ruby syntax• Classes and objects in Ruby• Closures• Mixins• Networking• Threading• Test-first coding in Ruby• Ruby as a scripting language• Ruby as a web language
![Page 4: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/4.jpg)
4
What is Ruby?
• From www.ruby-lang.org:• Ruby is the interpreted scripting language for quick and easy
object-oriented programming. • It has many features to process text files and to do system
management tasks (as in Perl). • It is simple, straight-forward, extensible, and portable.
• Ruby has:• Simple syntax, partially inspired by Eiffel and Ada• Exception handling features, like Java or Python• operators that are syntax sugar for the methods. You can
redefine them easily
![Page 5: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/5.jpg)
5
Features of Ruby
• Ruby is a complete, full, pure object oriented language. • All data in Ruby is an object, in the sense of Smalltalk: no
exceptions. • Example: In Ruby, the number 1 is an instance of class Fixnum.
• Ruby's OO is carefully designed to be both complete and open for improvements. • Example: Ruby has the ability to add methods to a class, or
even to an instance during runtime. A• An instance of one class *can* behave differently from other
instances of the same class.
![Page 6: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/6.jpg)
6
Features of Ruby
• Ruby features single inheritance only, *on purpose*. • But Ruby knows the concept of modules (called Categories in
Objective-C). • Modules are collections of methods. • Every class can import a module and so gets all its methods for
free.
• Ruby features true closures. • Not just unnamed function, but with present variable bindings.
• Ruby features blocks in its syntax (code surrounded by '{' ... '}' or 'do' ... 'end'). • These blocks can be passed to methods, or converted into
closures.
![Page 7: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/7.jpg)
7
Features of Ruby
• Ruby features a true mark-and-sweep garbage collector. • It works with all Ruby objects. • You don't have to care about maintaining reference counts in
extension libraries.
• Integers in Ruby can (and should) be used without counting their internal representation. • There *are* small integers (instances of class Fixnum) and
large integers (Bignum), but you need not worry over which one is used currently.
• If a value is small enough, an integer is a Fixnum, otherwise it is a Bignum. Conversion occurs automatically.
![Page 8: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/8.jpg)
8
Features of Ruby
• Ruby needs no variable declarations. • It uses simple naming conventions to denote the scope of
variables.
• Ruby can load extension libraries dynamically if an OS allows.
• Ruby features OS independent threading• Ruby is highly portable: it is developed mostly on Linux,
but works on many types of UNIX, DOS, Windows 95/98/Me/NT/2000/XP, MacOS, BeOS, OS/2, etc.
var_name => local variable@var_name => instance variable@var_name => global variable
![Page 9: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/9.jpg)
9
Obtaining Ruby
• The main Ruby site: www.ruby-lang.org• For Windows, the One-Click Ruby Installer project on
RubyForge: http://rubyinstaller.rubyforge.org/wiki/wiki.pl• If you have Cygwin, you can choose Ruby as one of the
language options• There is a specific cygwin-ruby version, optimized for Cygwin
• The English reference manual is very outdated• However, http://www.ruby-doc.org/ has up to date
RubyDocs and other resources• The Pick-Axe book (shown at the end)
![Page 10: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/10.jpg)
10
Classes and Objects in Ruby
class Employee def initialize(name, salary, hire_year) @name = name @salary = salary @hire_year = hire_year end def to_s "Name is #{@name}, salary is #{@salary}, “
+ "hire year is #{@hire_year}" end def raise_salary_by(perc) @salary += (@salary * 0.10) endend
![Page 11: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/11.jpg)
11
Inheritance
class Manager < Employee def initialize(name, salary, hire_year, asst) super(name, salary, hire_year) @asst = asst end def to_s super + ",\tAssistant info: #{@asst}" end def raise_salary_by(perc) perc += 2005 - @hire_year super(perc) endend
![Page 12: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/12.jpg)
12
Tying It Together
def show(emps) emps.each { |e| puts e }end
employees = Array.newemployees[0] = Employee.new("Homer", 200.0, 1995)employees[1] = Employee.new("Lenny", 150.0, 2000)employees[2] = Employee.new("Carl", 250.0, 1999)employees[3] = Manager.new("Monty", 3000.0, 1950,
employees[2])
show(employees)
employees.each { |e| e.raise_salary_by(10) }puts "\nGive everyone a raise\n\n"show employees
![Page 13: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/13.jpg)
13
Class Members
class Employee @@num_employees = 0; def Employee.num_employees @@num_employees end def initialize(name, salary, hire_year) @name = name @salary = salary @hire_year = hire_year @@num_employees += 1 end # . . .
show employees
puts "Number of employees in the company: " + Employee.num_employees.to_s
![Page 14: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/14.jpg)
14
Properties
class Employee def name @name end def salary @salary end def hire_year @hire_year end # . . . emp = Employee.new("Homer", 100.0, 2004)printf "Name: %s\n", emp.nameprintf "Salary: %d\n", emp.salaryprintf "Hire Year: %s\n", emp.hire_year
![Page 15: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/15.jpg)
15
attr_readerclass Employee attr_reader :name, :salary, :hire_year def initialize(name, salary, hire_year) @name = name @salary = salary @hire_year = hire_year end
# . . .
emp = Employee.new("Homer", 100.0, 2004)printf "Name: %s\n", emp.nameprintf "Salary: %d\n", emp.salaryprintf "Hire Year: %s\n", emp.hire_year
![Page 16: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/16.jpg)
16
Writable Properties
class Employee def name @name end def name=(new_name) @name = new_name end def salary @salary end def hire_year @hire_year end # . . . emp = Employee.new("Homer", 100.0, 2004)emp.name = "Monty"printf "Name: %s\n", emp.name
![Page 17: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/17.jpg)
17
attr_writer
class Employee attr_reader :name, :salary, :hire_year attr_writer :name, :salary, :hire_year def initialize(name, salary, hire_year) @name = name @salary = salary @hire_year = hire_year end #. . .
emp = Employee.new("Homer", 100.0, 2004)emp.name = "Monty"printf "Name: %s\n", emp.name
![Page 18: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/18.jpg)
18
Singletons
class Logger private_class_method :new @@logger = nil def Logger.create @@logger = new unless @@logger @@logger endend
puts Logger.create.object_idputs Logger.create.object_id
![Page 19: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/19.jpg)
19
Access Control
• Ruby has 3 levels of access control
public • Called by anyone (i.e., no access control)• Default access (except for initialize, which is always private
protected • Only by objects of the defining class and its subclasses
private • Cannot be called without an explicit receiver• You cannot specify an object when using them• Can be called only in the defining class and by direct descendents within that same object
![Page 20: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/20.jpg)
20
Private vs. Protected
• The difference is subtle• Protected
• Can be called by any instance of the defining class or its subclasses
• Private• Called only within the context of the calling object• Never possible to access another object’s private methods
directly, even if the object is the same class as the caller
![Page 21: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/21.jpg)
21
Arrays - General Syntax
a = [ 3.14159, "pi", 99 ]a.type » Arraya.length » 3a[0] » 3.14159a[1] » "pi"a[2] » 99a[3] » nilb = Array.newb.type » Arrayb.length » 0b[0] = "second"b[1] = "array"b » ["second", "array"]
![Page 22: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/22.jpg)
22
Arrays - Indexing
• Negative indicesa = [ 1, 3, 5, 7, 9 ]a[-1] » 9a[-2] » 7a[-99] » nil
• Pairsa = [ 1, 3, 5, 7, 9 ]a[1, 3] » [3, 5, 7]a[3, 1] » [7]a[-3, 2] » [5, 7]
![Page 23: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/23.jpg)
23
Arrays - Ranges
a = [ 1, 3, 5, 7, 9 ]a[1..3] » [3, 5, 7]a[1...3] » [3, 5]a[3..3] » [7]a[-3..-1] » [5, 7, 9]
![Page 24: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/24.jpg)
24
Array Assignment
a = [ 1, 3, 5, 7, 9 ] » [1, 3, 5, 7, 9]a[1] = 'foo' » [1, "foo", 5, 7, 9]a[-3] = 'bar' » [1, "foo", "bar", 7, 9]a[3] = [ 9, 8 ] » [1, "foo", "bar", [9, 8],
9]a[6] = 99 » [1, "foo", "bar", [9, 8], 9, nil,
99]
![Page 25: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/25.jpg)
25
Array Assignment Ranges
a = [ 1, 3, 5, 7, 9 ] » [1, 3, 5, 7, 9]a[2, 2] = 'cat' » [1, 3, "cat", 9]a[2, 0] = 'dog' » [1, 3, "dog", "cat", 9]a[1, 1] = [ 9, 8, 7 ]
» [1, 9, 8, 7, "dog", "cat", 9]a[0..3] = [] » ["dog", "cat", 9]a[5] = 99 » ["dog", "cat", 9, nil, nil, 99]
![Page 26: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/26.jpg)
26
Hashes
h = { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' }
h.length » 3h['dog'] » "canine"h['cow'] = 'bovine'h[12] = 'dodecine'h['cat'] = 99h » {"cow"=>"bovine",
"cat"=>99, 12=>"dodecine", "donkey"=>"asinine", "dog"=>"canine"}
![Page 27: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/27.jpg)
27
Blocks
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
![Page 28: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/28.jpg)
28
Blocks def show @employees.each { |e| puts e } end def [](key) if key.kind_of?(Integer) @employees[key] end endend
list = EmployeeList.newlist.add(Employee.new("Homer", 200.0, 1995)). add(Employee.new("Lenny", 150.0, 2000)). add(Employee.new("Carl", 250.0, 1999))
list.showputs "Employee #1 is " + list[0].to_s
![Page 29: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/29.jpg)
29
Iterating with for def [](key) if key.kind_of?(Integer) @employees[key] else for i in [email protected] return @employees[i] if key == @employees[i].name end end return nil endend
list = EmployeeList.newlist.add(Employee.new("Homer", 200.0, 1995)). add(Employee.new("Lenny", 150.0, 2000)). add(Employee.new("Carl", 250.0, 1999))
list.showputs "Employee #1 is " + list[0].to_sputs "Employee named 'Homer' is " + list["Homer"].to_s
![Page 30: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/30.jpg)
30
Using Blocks
def [](key) if key.kind_of?(Integer) result = @employees[key] else result = @employees.find{ |anEmp| key == anEmp.name } end return result endend
puts "Employee #1 is " + list[0].to_sputs "Employee named 'Homer' is " +
list["Homer"].to_s
![Page 31: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/31.jpg)
31
The Ruby Way
def [](key) return @employees[key] if key.kind_of?(Integer) return @employees.find { |anEmp| key == anEmp.name } endend
list = EmployeeList.newlist.add(Employee.new("Homer", 200.0, 1995)). add(Employee.new("Lenny", 150.0, 2000)). add(Employee.new("Carl", 250.0, 1999))
list.showputs "Employee #1 is " + list[0].to_sputs "Employee named 'Homer' is " +
list["Homer"].to_s
![Page 32: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/32.jpg)
32
Building Iterators
def fib_up_to(max) i1, i2 = 1, 1 # parallel assignment while i1 <= max yield i1 i1, i2 = i2, i1+i2 endend
fib_up_to(1000) { |f| print f, " " }
![Page 33: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/33.jpg)
33
Blocks for Transactions
class File def File.open_and_process(*args) f = File.open(*args) yield f f.close() endend
File.open_and_process("testfile", "r") do |aFile| print while aFile.getsend
![Page 34: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/34.jpg)
34
Blocks for Transactions, Take 2
class File def File.myOpen(*args) aFile = File.new(*args) # If there's a block, pass in the file and close # the file when it returns if block_given? yield aFile aFile.close aFile = nil end return aFile endend
![Page 35: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/35.jpg)
35
Closures
• Closures represent a (nameless) block of code that retains its context, even if the context is out of scope
• A closure object has code to run, the executable, and state around the code, the scope.
• You can refer to the local variables inside a closure.• Even after the function has returned, and its local scope
has been destroyed, the local variables remain in existence as part of the closure object.
• When no one refers to the closure anymore, it's garbage collected, and the local variables go away.
![Page 36: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/36.jpg)
36
Closure Exampledef make_counter var = 0 proc do # coverts a block to a proc object
var +=1 endend
c1 = make_counterc1.callc1.callc1.call
c2 = make_counter
puts "c1 = #{c1.call}, c2 = #{c2.call}"# output: c1 = 4, c2 = 1
![Page 37: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/37.jpg)
37
Regular Expressions
• Regular expressions are a built-in data type in Ruby
a = Regexp.new('^\s*[a-z]') » /^\s*[a-z]/b = /^\s*[a-z]/ » /^\s*[a-z]/c = %r{^\s*[a-z]} » /^\s*[a-z]/
a = "Fats Waller"a =~ /a/ » 1a =~ /z/ » nila =~ "ll" » 7
![Page 38: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/38.jpg)
38
Extending Classes
• Classes are never closed in Ruby• You can add new methods to user or system classes• Just open the definition and start typing!class String def rot(num = 13) return self.split("").collect { |ch| if /^[a-z]$/ === ch ((ch[0] + num - 'a'[0]) % 26 + 'a'[0]).chr elsif /^[A-Z]$/ === ch ((ch[0] + num - 'A'[0]) % 26 + 'A'[0]).chr else ch end }.join("") end
alias rot13 rotend
![Page 39: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/39.jpg)
39
Conditionals
• True in Ruby implies• Any value that is not nil or the constant false• Zero is not false• A zero-length string is not false
• Ruby includes an operator defined?• Returns nil if its argument (which can be an arbitrary
expression) is not defined• Otherwise returns a description of the argument
defined? 1 » "expression"defined? dummy » nildefined? printf » "method"defined? String » "constant"
![Page 40: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/40.jpg)
40
Comparison Operators
Operator Meaning
== Equality
=== Equality in a case statement when clause
<=> General comparison operator, returns -1, 0, +1
<, <=, >=, >
Standard comparisons
=~ Regular expression pattern match
eql? True if receiver and argument are both the same type and have equal values1 == 1.0 >> true 1.eql?(1.0) >> false
equal? True if the receiver and argument have the same object id
![Page 41: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/41.jpg)
41
if Expression
• General form:
if emp.name == "Homer" then handle = "slacker"elsif emp.name == "Lenny" then handle = "go-getter"else handle = "unknown"end
![Page 42: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/42.jpg)
42
if Expression
• If you lay them out on separate lines, you can skip the then keyword
if emp.name == "Homer" handle = "slacker"elsif emp.name == "Lenny" handle = "go-getter"else handle = "unknown"end
![Page 43: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/43.jpg)
43
if Expression
• You can use if as an expression if you want
handle = if emp.name == "Homer" then "slacker" elsif emp.name == "Lenny" then "go-getter" else "unknown" end
![Page 44: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/44.jpg)
44
unless, Conditional Expressions
• The unless expression is a negated if statement
unless emp.salary > 2000 then raise_percentage = 0.10else raise_percentage = 0.11end
• There is also the ternary operator
raise_percentage = empl.salary > 2000 ? 0.10 : 0.11
![Page 45: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/45.jpg)
45
If and Unless Modifiers
• Like Perl, statement modifiers allow you to attach conditional statements onto the end of a normal statement
mon,day,year = $1,$2,$3 if /(\d\d)-(\d\d)-(\d\d)/puts "a = #{a}" if debugprint total unless total == 0
while gets next if /^#/ # Skip comments parseLine unless /^$/ # Don't parse empty lines
end
![Page 46: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/46.jpg)
46
Case Expressions
case inputLine when "debug" dumpDebugInfo dumpSymbols when /p\s+(\w+)/ dumpVariable($1) when "quit", "exit" exit else print "Illegal command: #{inputLine}"end
![Page 47: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/47.jpg)
47
Case + Regular Expressions
case line when /name=(.*)/ puts "Name is #$1" when /salary=(.*)/ puts "Salary is #$1" when /Hire\sYear=(.*)/ puts "Hire Year is #$1"end
![Page 48: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/48.jpg)
48
Loops
• While loop
while gets # . . .end
• Until loop
until emp.salary > 2500 employee_list.add(emp.pop)end
![Page 49: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/49.jpg)
49
Loops as Modifiers
a *= 2 while a < 100
a -= 10 until a < 100
![Page 50: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/50.jpg)
50
Iterators
3.times do print "knock "end# knock knock knock
0.upto(9) do |x| print x, " "end#0 1 2 3 4 5 6 7 8 9
0.step(12, 3) {|x| print x, " " } # 0, 3, 6, 9, 12
![Page 51: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/51.jpg)
51
Exceptions
the_file = File.open(name, "w")begin # Exceptions raised by this code will # be caught by the following rescue clause while data = socket.read(512) the_file.write(data) end
rescue SystemCallError $stderr.print "IO failed: " + $! the_file.close File.delete(name) raiseend
![Page 52: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/52.jpg)
52
ensure and else
f = File.open("testfile")begin # .. processrescue # .. handle errorelse puts "Congratulations-- no errors!"ensure f.close unless f.nil?end
![Page 53: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/53.jpg)
53
retrybegin if @esmtp then @command.ehlo(helodom) else @command.helo(helodom) end
rescue ProtocolError if @esmtp then @esmtp = false retry else raise endend
![Page 54: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/54.jpg)
54
Modules
• Modules allow you to group methods, classes, and constants• Provide unique namespaces• Implement mixins
• Namespaces allow you to partition your application into separate files
• Use the require keyword to reference other modules
![Page 55: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/55.jpg)
55
Mixins
• Ruby does not support multiple inheritance• Instead, it supports mixins• You define methods within a module• You include that module into a class
![Page 56: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/56.jpg)
56
Mixins
module Debug def who_am_i? "#{self.class.name} " + "(\##{self.object_id}): #{self.to_s}" endend
class Employee include Debug . . .endclass Manager < Employee include Debug . . .end
puts "\n\nWho are they?"puts employees[0].who_am_i?puts employees[3].who_am_i?
![Page 57: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/57.jpg)
57
Threadsrequire 'net/http'
pages = %w( www.rubycentral.com www.nealford.com www.pragmaticprogrammer.com )threads = []for page in pages threads << Thread.new(page) { |myPage| h = Net::HTTP.new(myPage, 80) puts "Fetching: #{myPage}" resp, data = h.get('/', nil ) puts "Got #{myPage}: #{resp.message}" }end
threads.each { |aThread| aThread.join }
![Page 58: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/58.jpg)
58
Thread Variables
• Thread has a special facility that allows thread-local variables to be created and accessed by name
• Treat the thread object as if it were a Hashcount = 0arr = []10.times do |i| arr[i] = Thread.new { sleep(rand(0)/10.0) Thread.current["mycount"] = count count += 1 }endarr.each {|t| t.join; print t["mycount"], ", " }puts "count = #{count}"
![Page 59: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/59.jpg)
59
Testing and Rubyrequire 'test/unit/testcase'require 'Employee'
class TestEmployee < Test::Unit::TestCase def setup @emp = Employee.new("Homer", 3000, 2004) end def teardown @emp = nil end
def test_raise_salary_by @emp.salary = 2000 perc = 10; expected_salary = @emp.salary +
(@emp.salary * 0.1 * perc) @emp.raise_salary_by(10) assert(@emp.salary = expected_salary) endend
![Page 60: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/60.jpg)
60
Testing and Ruby
class TestEmployeeList < Test::Unit::TestCase
def setup @list = EmployeeList.new @test_subject =
Employee.new("Homer", 3000, 2004) end def teardown @list = nil @test_subject = nil end def test_add @list.add(@test_subject) assert(@list.delete_last.eql?(@test_subject)) assert(@list.empty?) end
![Page 61: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/61.jpg)
61
Testing and Rubyrequire 'test/unit/testsuite'require 'test/unit/ui/tk/testrunner'require 'test/unit/ui/console/testrunner'require 'TestEmployee'require 'TestEmployeeList'
class TestSuite_AllTests def self.suite suite = Test::Unit::TestSuite.new("HR Tests") suite << TestEmployee.suite suite << TestEmployeeList.suite return suite endend
#Test::Unit::UI::Tk::TestRunner.run(TestSuite_AllTests)Test::Unit::UI::Console::TestRunner.run(
TestSuite_AllTests)
![Page 62: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/62.jpg)
62
Controlling Windows
require 'Win32API'require 'win32ole'
class DailyLogs private @@Home_Dir = "c:\\MyDocuments\\" def get_doc_list docs = Array.new docs << "im\\2005 Weekly Workout Planner.xls" docs << "im\\2005 Workout Log.xls" docs << "trackers\\Master Task List.xls" end
![Page 63: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/63.jpg)
63
Controlling Windows
public def open_daily_logs excel = WIN32OLE.new("excel.application") workbooks = excel.WorkBooks excel.Visible = true get_doc_list.each { |f| workbooks.Open(@@Home_Dir + f, true) } excel.Windows.Arrange(7) end end
DailyLogs.new.open_daily_logs
![Page 64: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/64.jpg)
64
Java vs. Ruby: Java, City.javapublic class City { private String name; private String symposiumName; private int showId;
public City(final String name, final String symposiumName, final int showId) { this.name = name; this.symposiumName = symposiumName; this.showId = showId; }
public String getName() { return name; }
public String getSymposiumName() { return symposiumName; }
public int getShowId() { return showId; }}
![Page 65: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/65.jpg)
65
Java vs. Ruby, Harvester.javapublic class Harvester { public static final String WEB_SITE = "http://www.nofluffjuststuff.com"; public static final String PAGE_NAME = "/show_topics.jsp?showId="; private static final String NAME_REGEX = "Neal\\sFord";
public Harvester() { int count; System.out.println("No Fluff, Just Stuff sessions:"); System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); try { for (Iterator<City> cityItr = createCityList().iterator(); cityItr.hasNext();) { count = 0; City city = cityItr.next(); StringBuffer content = getWebContent(city); Matcher matcher = generateRegexForMatch(content); while (matcher.find()) { count++; } System.out.println(city.getName() + " = " + count); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
![Page 66: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/66.jpg)
66
Java vs. Ruby, Harvester.java private Matcher generateRegexForMatch(final StringBuffer content) { Pattern pattern = Pattern.compile(NAME_REGEX); return pattern.matcher(content); }
private StringBuffer getWebContent(final City city) throws IOException {
URL url = new URL(WEB_SITE + PAGE_NAME + city.getShowId()); HttpURLConnection http = (HttpURLConnection) url.openConnection(); InputStream is = http.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); String line; StringBuffer content = new StringBuffer(1000); while ((line = reader.readLine()) != null) { content.append(line); } return content; }
private List<City> createCityList() { List<City> cityList = new ArrayList<City>(10); cityList.add(new City("Salt Lake", "Salt Lake", 16)); cityList.add(new City("Pacific Northwest", "Seattle", 32)); return cityList; }}
![Page 67: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/67.jpg)
67
Java vs. Ruby, harvester.rbrequire 'net/http'
class City def initialize(symposium_name, city_name, show_id) @city_name = city_name @symposium_name = symposium_name @show_id = show_id end attr_reader :city_name, :symposium_name, :show_idend
def check_city(http, url, city) count = 0 http.request_get(url) { |response| response.read_body { |body| body.scan(/Neal\sFord/) { count += 1 } } } printf("%-20s = %d\n", city, count)end
![Page 68: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/68.jpg)
68
Java vs. Ruby, harvester.rb
Page_Name = '/show_topics.jsp?showId='cities = Array.newcities << City.new('Salt Lake', 'Salt Lake', 16)cities << City.new('Pacific', 'Seatle', 32)
http = Net::HTTP.new('www.nofluffjuststuff.com', 80)
puts "No Fluff, Just Stuff sessions:"puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"cities.each { |city| check_city(http, Page_Name + city.show_id.to_s, city.city_name)}
![Page 69: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/69.jpg)
69
Resources:
The “Pick-Axe” Book
Programming Ruby: The Pragmatic Programmer’s Guide
Dave Thomas, Andy Hunt
Ruby in a Nutshell
Yukihiro Matsumoto, David L. Reynolds (Translator)
![Page 70: Ruby for Java Developers](https://reader036.vdocument.in/reader036/viewer/2022062400/56815a17550346895dc75f78/html5/thumbnails/70.jpg)
70
Resources:
Ruby Developer's Guide
Michael Neumann, Jonothon Ortiz, Robert Feldt, Lyle Johnson
The Ruby Way
Hal Fulton, Guy Hurst