Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
H AC CO RUBY COACH — Scripting in Ruby — RU BY Hinrich E. G. Bonin1 1 Prof. Dr. rer. publ. Dipl.-Ing. Dipl.-Wirtsch.-Ing. Hinrich E. G. Bonin lehrt Informatik an der Leuphana Universität Lüneburg, Email: [email protected], Adresse: An der Eulenburg 6, D-21391 Reppenstedt, Germany. H 2 Abstract AC “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, and extensible.” (→ file readme.txt) BY CO ‘, ‘, () () () () +--------+ ( o o ) | Ruby | ˆˆ ( @__)___| is | || ( ) | fun! | ++==( )\ +--------+ ( )\\ ( ) vv ( ) __//˜˜\\__ (___) (___) RU Remark: This is a draft document and continues to be revised. The latest version can be found at http://as.uni-lueneburg.de/publikation/rubyall.pdf. Please send comments to: mailto:[email protected] H AC Inhaltsverzeichnis Preface 2 Examples and Exercises 2.1 Cult Programm HelloWorld . . 2.2 Factorial Function fac . . . . . . 2.3 Prime Numbers prime . . . . . . 2.4 Input and Output . . . . . . . . . 2.5 Transaction . . . . . . . . . . . . 2.6 Downloading Web Pages . . . . . 2.7 Several Processes . . . . . . . . . 2.8 Directory Access . . . . . . . . . 2.9 Inheritance . . . . . . . . . . . . 2.10 Singleton Method . . . . . . . . . 2.11 Word Couter . . . . . . . . . . . . 2.12 Shallow Copy . . . . . . . . . . . 2.13 Namespace — module . . . . . 2.14 Mixins — include . . . . . . . 2.15 Serialization — Marshaling . . . . 2.16 Reflection . . . . . . . . . . . . . 2.17 Recursion . . . . . . . . . . . . . 2.18 Simple Continuation . . . . . . . 2.19 Calling Future Code . . . . . . . . 2.20 CGI (Common Gateway Interface) 2.21 Quadric . . . . . . . . . . . . . . 2.22 Biorhythm . . . . . . . . . . . . . 2.23 WIN32OLE — Internetexplorer . 2.24 WIN32OLE — Excel . . . . . . . RU BY CO 1 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 9 10 11 12 13 15 16 17 18 19 20 22 24 25 27 29 31 34 35 37 38 42 46 48 Software Engineering Tools 3.1 ri — Ruby Information at your fingertips 3.2 irb — Interactive Ruby Shell . . . . . . 3.3 ruby-mode — Emacs Mode . . . . . . 3.4 rd-mode — Emacs Mode . . . . . . . . 3.5 eruby — Embedding Ruby in HTML . . 3.6 Framework Ruby on Rails . . . . . . . . 3.7 Eclipse — Plug-In . . . . . . . . . . . . . 3.8 rd2 — formater tool . . . . . . . . . . . 3.8.1 Prerequisite racc tool . . . . . . 3.8.2 rdtool — Installation . . . . . 3.9 DyBASE — Object Oriented DBMS . . . 3.9.1 Application Program Interface . . 3.9.2 Example TestLink.rb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 51 52 53 54 55 56 56 57 60 60 63 65 71 . . . . . . . . 77 77 77 77 77 77 78 79 83 CO AC 3 H INHALTSVERZEICHNIS 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . RU BY A Resources A.1 Web Sites . . . . . . . . . . A.1.1 Ruby . . . . . . . . A.1.2 Java . . . . . . . . . A.1.3 Updates to this Book A.2 Glossary . . . . . . . . . . . A.3 Bibliography . . . . . . . . A.4 About this Document . . . . A.5 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . H CO Preface AC Kapitel 1 , , () () () () +------+ ( . o ) | Easy-| ( @__)_____| to- | ( ) | use! | //( )\\ +------+ //( )\\ vv ( ) vv ( ) __//˜˜\\__ (___) (___) • Simple Syntax • “Normal” Object-Oriented features (ex. class, method calls) • “Advanced” Object-Oriented features (ex. Mix-in, Singletonmethod) RU BY • Operator Overloading • Exception Handling • Iterators and Closures • Garbage Collection • Dynamic Loading of Object files(on some architecture) • Highly Portable(works on many UNIX machines, and on DOS, Windows, Mac, BeOS etc.) A modern object oriented programming language is JavaT M 1 . First let’s compare Ruby with Java: 1 More for example → section A.1.2 p. 77 or → [Arnold / Gosling, 1996]. 5 KAPITEL 1. PREFACE CO AC H 6 Legende: Script RubyCoach.rb →p. 6. Produced with the following command: d:\bonin\rubyScript\code>RubyCoach > ../html/RubyCoach.xml RubyCoach.xml loaded into Microsoft Windows XP [Version 5.1.2600]. BY Abbildung 1.1: Contents of this book Ruby Coach • Ruby’s variable and expressions are not statically typed. • All data (including Integer, String etc.) in Ruby are class instances. • Ruby’s module can be used to share implementation among classes. RU • Ruby is an interpreted language. Ruby program files use the suffix “*.rb”. If you don’t want a console window to be created, use the suffix “*.rbw” instead. Program files may be created using any plain text editor such as Emacs or Eclipse. Script RubyCoach.rb H 7 CO AC # # Contents of Ruby Coach # # Hinrich Bonin # 4-Dec-2003 19-Jul-2007 # class RubyCoach def initialize() @chapter = ["Preface", "Exercises", "Software Engineering Tools", "Resources", "Index" ] end def contents puts "<?xml version=\"1.0\" " + "encoding=\"utf-8\" ?>" puts "<book>" puts "<title>Ruby Coach</title>" @chapter.each { |i| puts "<chapter>#{i}</chapter>" } puts "</book>" end BY end RubyCoach.new.contents # EOF 193.174.33.66 D:/bonin/rubyScript/code/RubyCoach.rb Notation Conventions RU The RUBY COACH uses a typewriter-like font to show source code examples. class Foo def methodA(n) . . . KAPITEL 1. PREFACE H 8 end AC . . . bar = Foo.new . . . end RU BY CO Within the text, Foo#methodA() is a reference to the instance method methodA() of the class Foo. The notation Foo.new or Foo::new is a class method. The notation Foo::EOF is a class constant. The RUBY COACH contains snippets of code. The result is shown after the sign ==>. H AC Kapitel 2 Examples and Exercises CO For an instant I thought Ruby was reading my mind . . . if matz can do that, it IS a powerful language! Hat Fulton (→[Röhrl+, 2002] p. 3) 2.1 Cult Programm HelloWorld Command line Hello World! BY D:\bonin\rubyScript>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] D:\bonin\rubyScript>ruby -e ’puts "Hello World!"’ Hello World! D:\bonin\rubyScript> Script HelloWorld.rb RU # # Simple class example # # Hinrich Bonin # 3-Dec-2003 # class HelloWorld 9 H KAPITEL 2. EXAMPLES AND EXERCISES 10 end o = HelloWorld.new puts o.msg print "Please press Enter-Key." $stdin.gets CO Protocol HelloWorld.log AC attr_reader :msg def initialize @msg = "Hello World!" end d:\bonin\rubyScript>ruby --copyright ruby - Copyright (C) 1993-2003 Yukihiro Matsumoto d:\bonin\rubyScript>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] d:\bonin\rubyScript>ruby ./code/HelloWorld.rb BY Hello World! Please press Enter-Key. d:\bonin\rubyScript> 2.2 Factorial Function fac Script fac.rb RU # # Factorial function # # Hinrich Bonin # 4-Dec-2003 # def fac(n) result = 1 (2..n).each {|i| result *= i} result end # 2.3. PRIME NUMBERS PRIME CO AC H 11 Legende: Ruby Script HelloWorld.rb in Microsoft Windows XP [Version 5.1.2600]. Abbildung 2.1: Running HelloWorld.rb puts fac(20) # # EOF 193.174.33.66 D:/bonin/rubyScript/code/fac.rb BY Protocol fac.log D:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] D:\bonin\rubyScript\code>fac 2432902008176640000 RU D:\bonin\rubyScript\code>ruby -e ’require \’fac\’’ 2432902008176640000 D:\bonin\rubyScript\code> 2.3 Prime Numbers prime Script prime.rb This example uses print. If the output field se- print KAPITEL 2. EXAMPLES AND EXERCISES H 12 AC parator “$,” is not nil, its contents will appear between each field. If the output record separator “$\” is not nil, it will be appended to the output. Objects that aren’t strings will be converted by calling their to s method. Protocol prime.log CO # # Prime Numbers # # Hinrich Bonin # 10-Dec-2003 # a = Array.new for i in 2..17 do a[i] = i unless (2..i-1).find{|j| i % j == 0} end $, = ", " $\ = "\n" print a # # EOF 193.174.33.66 D:/bonin/rubyScript/code/prime.rb BY D:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] D:\bonin\rubyScript\code>prime , , 2, 3, , 5, , 7, , , , 11, , 13, , , , 17 D:\bonin\rubyScript\code> 2.4 Input and Output RU Script inout.rb # # Input & Output # # Hinrich Bonin # 10-Dec-2003 # 2.5. TRANSACTION H 13 Text file myHounds.txt CO Elsa vom Erlenbruch Wulf von Wallesau Xander von Thurewang Xara vom Bremberg AC File.open("myHounds.txt", "r") {|aFile| aFile.each_line {|line| print line if line =˜ /von/ } } File.open("myHounds.txt", "w") {|aFile| aFile.print "Klara von Wolfsburg\n" } # EOF 193.174.33.66 D:/bonin/rubyScript/code/inout.rb Protocol inout.log D:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] BY D:\bonin\rubyScript\code>inout Wulf von Wallesau Xander von Thurewang D:\bonin\rubyScript\code>inout Klara von Wolfsburg D:\bonin\rubyScript\code> 2.5 Transaction RU A code block is just chunk of code between {. . .} or do. . .end. You can associate it with a call to a method. That method can then invoke the block one or more times using the Ruby yield statement. First we show this in action with a simple example running in irb (Interactive Ruby Shell → section 3.2 p. 52). D:\bonin\rubyScript>irb irb(main):001:0> def callBlock yield KAPITEL 2. EXAMPLES AND EXERCISES H 14 AC irb(main):002:1> yield irb(main):003:1> yield irb(main):004:1> end => nil irb(main):005:0> callBlock {puts "Now I know yield."} Now I know yield. Now I know yield. => nil irb(main):006:0> quit D:\bonin\rubyScript> CO Script transaction.rb BY ## # Making the file responsible # for closing itself. # (Block for transaction) # # @author Hinrich Bonin # @version 1.0 # 21-Dec-2003 # class File def File.openProcessClose(*args) f = File.open(*args) yield f f.close() end end File.openProcessClose("myHounds.txt", "r") do |aFile| print while aFile.gets end RU # EOF 193.174.33.66 D:/bonin/rubyScript/code/transaction.rb Text file myHounds.txt → p. 13 Protocol transaction.log 2.6. DOWNLOADING WEB PAGES H 15 D:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] AC D:\bonin\rubyScript\code>transaction Elsa vom Erlenbruch Wulf von Wallesau Xander von Thurewang Xara vom Bremberg D:\bonin\rubyScript\code> 2.6 Downloading Web Pages Downloading three Web pages in parallel: http://as.fhnon.de/index.php3 http://nemo.fhnon.de/index.html http://webrat.fhnon.de/index.jsp Hinrich Bonin 11-Dec-2003 BY # # # # # # # # # # CO Script webpages.rb require ’net/http’ RU urls = %w(as.fhnon.de nemo.fhnon.de webrat.fhnon.de) threads = [] for url in urls threads << Thread.new(url) {|myP| h = Net::HTTP.new(myP, 80) puts "Loading: #{myP}" resp, data = h.get(’/’, nil ) puts "Response for #{myP}/: #{resp.message}" resp, data = h.get(’/index.jsp’, nil ) puts "Response for #{myP}/index.jsp: #{resp.message}" } end threads.each {|aTh| aTh.join} # EOF 193.174.33.66 D:/bonin/rubyScript/code/webpages.rb KAPITEL 2. EXAMPLES AND EXERCISES H 16 AC Protocol webpages.log D:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] D:\bonin\rubyScript\code> 2.7 Several Processes CO D:\bonin\rubyScript\code>webpages Loading: as.fhnon.de Loading: nemo.fhnon.de Loading: webrat.fhnon.de Response for nemo.fhnon.de/: OK Response for webrat.fhnon.de/: Moved Temporarily Response for nemo.fhnon.de/index.jsp: Not Found Response for webrat.fhnon.de/index.jsp: OK Response for as.fhnon.de/: OK Response for as.fhnon.de/index.jsp: Not Found system() BY Protocol processes.log Remark: Interactive Ruby Shell irb → section 3.2 p. 52. One problem with Kernel.system() (short system()) is that the command’s output will simply go to the same destination as your program’s output. D:\bonin\rubyScript\code>irb --version irb 0.9(02/07/03) RU D:\bonin\rubyScript\code>irb irb(main):001:0> result = irb(main):002:0* system("type wordCounter.rb > outfile.txt") => true irb(main):003:0> result => true irb(main):004:0> system("type outfile.txt") # # Counts the words in the text 2.8. DIRECTORY ACCESS H 17 AC # "matz.txt" # Hinrich Bonin . . . irb(main):005:0> ruby --version NameError: undefined local variable or method ‘version’ for main:Object from (irb):5 irb(main):006:0> ‘ruby --version‘ => "ruby 1.8.0 (2003-08-04) [i386-mswin32]\n" irb(main):007:0> exit CO D:\bonin\rubyScript\code> 2.8 Directory Access Script dir.rb Remark: Source code → /ruby/Ruby-1.8.0/samples/dir.rb BY # directory access # list all files but .*/*˜/*.o dirp = Dir.open(".") for f in dirp case f when /ˆ\./, /˜$/, /\.o/ # do not print else print f, "\n" end end dirp.close RU Protocol dir.log D:\bonin\rubyScript>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] D:\bonin\rubyScript>ruby ./code/dir.rb body.tmp code KAPITEL 2. EXAMPLES AND EXERCISES H 18 D:\bonin\rubyScript> 2.9 Inheritance BY Script Hound.rb CO AC emlines2.sty eps head.tmp log material rubyall.aux rubyall.dvi rubyall.idx rubyall.ilg rubyall.ind rubyall.lof rubyall.lot rubyall.pdf rubyall.ps rubyall.tex rubyall.toc run.bat stempel.pro verbfile.sty RU # # Simple inheritance example # # Hinrich Bonin # 3-Dec-2003 # class Mammal def initialize(name,sex) @name = name @sex = sex end def to_s "#{@name} (#{@sex})" end end class Hound < Mammal 2.10. SINGLETON METHOD H 19 AC def initialize(name,sex,performance,race) super(name,sex) @performance = performance @race = race end def to_s "Hound: " + "#{@race} " + super + " --- #{@performance}" end end CO elsa = Hound.new("Elsa vom Erlenbruch", "male" , "SWI", "German Setter") puts(elsa.to_s) # EOF 193.174.33.66 D:/bonin/rubyScript/code/Hound.rb Protocol Hound.log D:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] BY D:\bonin\rubyScript\code>Hound Hound: German Setter Elsa vom Erlenbruch (male) --- SWI D:\bonin\rubyScript\code> 2.10 Singleton Method Script Foo.rb Remark: Source code idea → [Röhrl+, 2002] p. 8 RU # # Singleton Method # # Hinrich Bonin # 7-Dec-2003 # class Foo def method_missing(methId) print "The method ", methId.id2name, H KAPITEL 2. EXAMPLES AND EXERCISES 20 # Method specified for f instance of FOO def f.saySomething print "I like Ruby! \n" end f.saySomething # Not specified for other Foo objects Foo.new.saySomething AC " is not specified.\n" end end f = Foo.new f.saySomething CO # EOF 193.174.33.66 D:/bonin/rubyScript/code/Foo.rb Protocol Foo.log D:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] D:\bonin\rubyScript\code>Foo The method saySomething is not specified. I like Ruby! The method saySomething is not specified. BY D:\bonin\rubyScript\code> 2.11 Word Couter Script wordCounter.rb Remark: Source code idea → [Röhrl+, 2002] p. 7 RU # # Counts the words in the text # "matz.txt" # Hinrich Bonin # 7-Dec-2003 # freq = Hash.new(0) open("matz.txt").read.scan(/\w+/){ |word| freq[word] +=1 } freq.sort.each { |word, number| 2.11. WORD COUTER puts "#{number} : #{word}" } H 21 Text file matz.txt AC # EOF 193.174.33.66 D:/bonin/rubyScript/code/wordCounter.rb Man is driven to create; I know I really love to create things. And while I’m not good at painting, drawing, or music, I can write software. CO It is my hope that both Ruby and this book will serve to make your programming easy and enjoyable. Have fun! Yukihiro Matsumoto, a.k.a. ‘‘Matz’’ Japan, October 2000 Protocol wordCounter.log D:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] RU BY D:\bonin\rubyScript\code>wordCounter 1 : 2000 1 : And 1 : Have 4 : I 1 : It 1 : Japan 1 : Man 1 : Matsumoto 1 : Matz 1 : October 1 : Ruby 1 : Yukihiro 2 : a 2 : and 1 : at 1 : book 1 : both 1 : can 2 : create KAPITEL 2. EXAMPLES AND EXERCISES AC drawing driven easy enjoyable fun good hope is k know love m make music my not or painting programming really serve software that things this to while will write your CO : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : BY 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 1 1 1 1 H 22 D:\bonin\rubyScript\code> 2.12 Shallow Copy Object#clone produces a shallow copy of an object of the class Object. The instance variables of object are copied, but not the objects they reference. RU clone Script shallowcopy.rb ## # Cloning an object # 2.12. SHALLOW COPY class Foo attr_accessor :slot end AC # @author Hinrich Bonin # @version 1.0 # 20-Dec-2003 # H 23 myoriginal = Foo.new myoriginal.slot = "Elsa" puts myoriginal.inspect myclone = myoriginal.clone puts myclone.inspect CO myoriginal.slot[0,4] = "xxxx" puts myoriginal.inspect puts myclone.inspect myclone = myoriginal.clone # Cloning the slot reference myclone.slot = myoriginal.slot.clone myoriginal.slot[0,4] = "Emma" puts myoriginal.inspect puts myclone.inspect BY # EOF 193.174.33.66 D:/bonin/rubyScript/code/shallowcopy.rb Protocol shallowcopy.log D:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] RU D:\bonin\rubyScript\code>shallowcopy #<Foo:0x2897678 @slot="Elsa"> #<Foo:0x2897588 @slot="Elsa"> #<Foo:0x2897678 @slot="xxxx"> #<Foo:0x2897588 @slot="xxxx"> #<Foo:0x2897678 @slot="Emma"> #<Foo:0x28974c8 @slot="xxxx"> D:\bonin\rubyScript\code> H KAPITEL 2. EXAMPLES AND EXERCISES 24 2.13 Namespace — module Script Foo.rb CO ## # Simple namespace example # # @author Hinrich Bonin # @version 1.0 # 21-Dec-2003 # module Foo V = 1 def Foo.f(n) print "Doing Foo::f(#{n})\n" n + V end AC The module mechanism provide a namespace and prevent name clashes. Remark: Module constants are named just like class constants, with an initial uppercase letter. def Foo.g(n) print "Doing Foo::g(#{n})\n" n * V end BY end # EOF 193.174.33.66 # D:/bonin/rubyScript/code/de/fhnon/as/Foo.rb Script Bar.rb RU ## # Simple namespace example # # @author Hinrich Bonin # @version 1.0 # 21-Dec-2003 # module Bar V = 2 def Bar.f(n) print "Doing Bar::f(#{n})\n" n - V end 2.14. MIXINS — INCLUDE end H AC def Bar.g(n) print "Doing Bar::g(#{n})\n" n / V end 25 # EOF 193.174.33.66 # D:/bonin/rubyScript/code/de/fhnon/as/Bar.rb Script main.rb CO ## # Simple namespace example # # @author Hinrich Bonin # @version 1.0 # 21-Dec-2003 # require "de/fhnon/as/Foo" require "de/fhnon/as/Bar" puts Foo.f(Bar.f(Foo.g(Bar.g(Bar::V)))) # EOF 193.174.33.66 D:/bonin/rubyScript/code/main.rb Protocol main.log BY D:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] D:\bonin\rubyScript\code>main Doing Bar::g(2) Doing Foo::g(1) Doing Bar::f(1) Doing Foo::f(-1) 0 RU D:\bonin\rubyScript\code> 2.14 Mixins — include The Ruby include statement makes a reference to a named module. If multiple classes include that module, they’ll all point to the same thing. If you change the definition of a method within a module, all classes that include that module will exhibit the new behavior. include H KAPITEL 2. EXAMPLES AND EXERCISES 26 Script Inside.rb AC ## # Simple mixins example # # @author Hinrich Bonin # @version 1.0 # 21-Dec-2003 # module Inside def show(n) "#{n}: #{self.inspect}" end end Script Innerpart.rb CO # EOF 193.174.33.66 # D:/bonin/rubyScript/code/de/fhnon/as/Inside.rb BY ## # Simple mixins example # # @author Hinrich Bonin # @version 1.0 # 21-Dec-2003 # module Innerpart def show(n) "#{n}: Here is method Innerpart\#show(#{n})!" end end # EOF 193.174.33.66 # D:/bonin/rubyScript/code/de/fhnon/as/Innerpart.rb Script mixins.rb RU ## # Simple mixins example # # @author Hinrich Bonin # @version 1.0 # 21-Dec-2003 # require "de/fhnon/as/Inside" require "de/fhnon/as/Innerpart" class Foo o = Foo.new r = Bar.new z = Baz.new CO class Baz include Inside attr_accessor :x end AC include Innerpart include Inside attr_accessor :x end class Bar include Inside include Innerpart attr_accessor :x end 27 H 2.15. SERIALIZATION — MARSHALING o.x = "Foo value" r.x = "Bar value" z.x = "Baz value" puts o.show(0) puts r.show(1) puts z.show(2) BY # EOF 193.174.33.66 D:/bonin/rubyScript/code/mixins.rb Protocol mixins.log D:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] D:\bonin\rubyScript\code>mixins 0: #<Foo:0x2896400 @x="Foo value"> 1: Here is method Innerpart#show(1)! 2: #<Baz:0x2896340 @x="Baz value"> RU D:\bonin\rubyScript\code> 2.15 Serialization — Marshaling Ruby calls this kind of serialization marshaling. Saving an object and some or all of its components is done using the method Marshal::dump. H KAPITEL 2. EXAMPLES AND EXERCISES 28 Script serial.rb # # Serialization of Objects # = Marshaling # Hinrich Bonin # 8-Dec-2003 # thing, thingBackup = Object.new CO point = Struct.new(’Point’, :x, :y) x = point.new(1,1) y = point.new(7,7) AC Typically, you will dump an entire object tree starting with some given object. Later on, you can reconstitute the object using Marshal::load. rectangle = Struct.new(’Rectangle’, :origin, :corner); r = rectangle.new(x, y) thing = [r, x, y] File.open("serialThing", "w+") do |f| Marshal.dump(thing, f) end BY File.open("serialThing") do |f| thingBackup = Marshal.load(f) end print "Point y backup: ", thingBackup[2], "\n" # EOF 193.174.33.66 D:/bonin/rubyScript/code/serial.rb Protocol serial.log RU d:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] d:\bonin\rubyScript\code>serial Point y backup: #<struct Struct::Point x=7, y=7> D:\bonin\rubyScript\code>dir serialThing 84 serialThing D:\bonin\rubyScript\code> 2.16. REFLECTION H 29 2.16 Reflection Script reflection.rb AC # # Object Space and Reflection # Hinrich Bonin # 8-Dec-2003 # point = Struct.new(’Point’, :a, :b) x = point.new(1,1) y = point.new(7,7) CO print "*** Struct object applies to ", x.methods.length, " methods: ***\n" x.methods.sort.each {|m| print m, "\n" } print "*** Object Space: ***\n" ObjectSpace.each_object(Struct) { |o| print o, "\n" } # EOF 193.174.33.66 D:/bonin/rubyScript/code/reflection.rb Protocol reflection.log D:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] RU BY D:\bonin\rubyScript\code>reflection *** Struct object applies to 74 methods: *** == === =˜ [] []= __id__ __send__ a a= all? any? b b= class clone collect detect RU AC BY display dup each each_pair each_with_index entries eql? equal? extend find find_all freeze frozen? grep hash id include? inject inspect instance_eval instance_of? instance_variable_get instance_variable_set instance_variables is_a? kind_of? length map max member? members method methods min nil? object_id partition private_methods protected_methods public_methods reject respond_to? select send singleton_methods H KAPITEL 2. EXAMPLES AND EXERCISES CO 30 2.17. RECURSION H 31 CO AC size sort sort_by taint tainted? to_a to_s type untaint values values_at zip *** Object Space: *** #<struct Struct::Point a=7, b=7> #<struct Struct::Point a=1, b=1> D:\bonin\rubyScript\code> 2.17 Recursion Script turnround.rb Remark: Equivalent source code in LISP language Scheme →[Bonin, 1991] p. 97 ff. BY ## # Inverting an Array object # # Recursive functions # turnround(a) # invert(a) # # @author Hinrich Bonin # @version 1.0 # 20-Dec-2003 # myarray = ["a", "b", "c", "d"] RU def firstElement(a) return a.first end def restArray(a) b = a.clone b.shift return b KAPITEL 2. EXAMPLES AND EXERCISES end CO print "Turn round an object of type: " + myarray.class.to_s + "\n" print "Using append construction" + "\n" print " Start myarray ==> " + myarray.to_s + "\n" print "turnround(myarray) ==> " + turnround(myarray).to_s + "\n" print " End myarray ==> " + myarray.to_s + "\n" AC def turnround(a) if a.empty? return a else return turnround( restArray(a)).concat([firstElement(a)]) end end H 32 print "\nInverting with more recursivity \n" # Step one: invert the rest array print "Step one ==> " + turnround( restArray(myarray)).to_s + "\n" BY # Step two: delete the first element from step one print "Step two ==> " + restArray( turnround( restArray(myarray))).to_s + "\n" # Step three: invert the result of step two print "Step three ==> " + turnround( restArray( turnround( restArray(myarray)))).to_s + "\n" RU # Step four: add first element (= "a") in result of step three print "Step four ==> " + [ firstElement(myarray) ].concat( turnround(restArray(turnround(restArray(myarray)))) ).to_s + "\n" # Step five: invert result of step four print "Step five ==> " + turnround( 2.17. RECURSION H 33 AC [firstElement(myarray)].concat( turnround( restArray( turnround( restArray(myarray)))) )).to_s + "\n" # Step six: last element print "Step six ==> " + [firstElement( turnround( restArray(myarray)))].to_s + "\n" CO # Step seven: <last element>.concat(turnround( # <array without last element = step four>)) print "Step seven ==> " + [firstElement( turnround( restArray(myarray)))]. concat( turnround( [firstElement(myarray)].concat( turnround( restArray( turnround( restArray(myarray)))) ))).to_s + "\n" RU BY def invert(a) if a.empty? return a else if [restArray(a)].empty? return a else return [firstElement( invert(restArray(a)))].concat( invert([firstElement(a)].concat( invert(restArray( invert(restArray(a))))))) end end end print invert(myarray).to_s # EOF 193.174.33.66 D:/bonin/rubyScript/code/turnround.rb KAPITEL 2. EXAMPLES AND EXERCISES Protocol turnround.log D:\bonin\rubyScript\code>turnround Turn round an object of type: Array Using append construction Start myarray ==> abcd turnround(myarray) ==> dcba End myarray ==> abcd AC d:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] H 34 BY D:\bonin\rubyScript\code> CO Inverting with more recursivity Step one ==> dcb Step two ==> cb Step three ==> bc Step four ==> abc Step five ==> cba Step six ==> d Step seven ==> dcba D:/bonin/rubyScript/code/turnround.rb:101:in ‘invert’: stack level too deep (SystemStackError) from D:/bonin/rubyScript/code/turnround.rb:111: in ‘invert’ 2.18 Simple Continuation Script continuation.rb Remark: The shift method returns the first element of an array and removes it (shifting all other elements down by one). It returns nil if the array is empty. RU callcc The continuation objects hold a return address and execution context, allowing a nonlocal return to the end of the callcc block from anywhere within a program. The instance method call invokes the continuation. The program continues from the end of the callcc block. If no arguments are given, the original callcc returns nil. If one argument is given, callcc returns it. Otherwise, an array containing args is returned. # # Simple continuation example # 2.19. CALLING FUTURE CODE H 35 AC # Hinrich Bonin # 13-Dec-2003 # x = [ "one", "two", "three", "four", "five", "six" ] callcc{|$mycc| puts "Begin of the block" puts "Doing this block" puts "End of the block"} puts "Working!" puts(value = x.shift) CO $mycc.call unless value =˜ /four/ # continues of # the end of the # callcc puts "End of the program" # EOF 193.174.33.66 D:/bonin/rubyScript/code/continuation.rb Protocol continuation.log d:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] RU BY d:\bonin\rubyScript\code>continuation Begin of the block Doing this block End of the block Working! one Working! two Working! three Working! four End of the program d:\bonin\rubyScript\code> 2.19 Calling Future Code Script future.rb # # Calling future code # # Hinrich Bonin # 13-Dec-2003 # foo = 7 $bar = 0 def h(n) callcc{|$mycc| print "Function h ==> ", n, "\n" n = n + 1 } end CO def g(n) print "Function g ==> ", n, "\n" n = n + 1 end AC H KAPITEL 2. EXAMPLES AND EXERCISES 36 def f(n) $bar = $bar + 1 print "Function f ==> ", n, "\n" n = n + 1 end puts f(g(h(foo))) BY print "$bar == " , $bar, "\n" $mycc.call 4 unless $bar == 5 # EOF 193.174.33.66 D:/bonin/rubyScript/code/future.rb Protocol future.log d:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] RU D:\bonin\rubyScript\code>future Function h ==> 7 Function g ==> 8 Function f ==> 9 10 $bar == 1 Function g ==> 4 Function f ==> 5 ==> 4 ==> 5 ==> 4 ==> 5 AC ==> 4 ==> 5 CO 6 $bar == 2 Function g Function f 6 $bar == 3 Function g Function f 6 $bar == 4 Function g Function f 6 $bar == 5 H 2.20. CGI (COMMON GATEWAY INTERFACE) D:\bonin\rubyScript\code> 2.20 CGI (Common Gateway Interface) Script MyCGI.rb RU BY # # Simple CGI example # # Hinrich Bonin # 19-Dec-2003 # require "cgi" cgi = CGI.new("html4") cgi.out{ cgi.html{ cgi.head{ cgi.title{"My CGI test"} } + cgi.body{ cgi.h1{"Common Gateway Interface"} + cgi.form{ cgi.textarea("get_text") + cgi.br + cgi.submit } } } } # EOF 193.174.33.66 D:/bonin/rubyScript/code/MyCGI.rb 37 Protocol MyCGI.log AC D:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] H KAPITEL 2. EXAMPLES AND EXERCISES 38 D:\bonin\rubyScript\code>MyCGI nil=0 > ../html/MyCGI.html D:\bonin\rubyScript\code> HTML File MyCGI.html Content-Type: text/html Content-Length: 341 2.21 Quadric BY CO <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <HTML> <HEAD> <TITLE>My CGI test</TITLE> </HEAD> <BODY><H1>Common Gateway Interface</H1> <FORM METHOD="post" ENCTYPE="application/x-www-form-urlencoded"> <TEXTAREA NAME="get_text" ROWS="10" COLS="70"> </TEXTAREA> <BR> <INPUT TYPE="submit"> </FORM> </BODY> </HTML> RU “This program demonstrates the use of some of the gluQuadric routines. Quadric objects are created with some quadric properties and the callback routine to handle errors. Note that the cylinder has no top or bottom and the circle has a hole in it.” (→ /ruby/doc/samples/opengl/) Script quadric.rbw Remark: Source code → /ruby/doc/samples/opengl/quadric.rbw # * # * OpenGL(R) is a registered trademark of Silicon Graphics, Inc. # */ 2.21. QUADRIC H 39 $startList = nil; AC # #/* # * quadric.c # * This program demonstrates the use of some of the gluQuadric* # * routines. Quadric objects are created with some quadric # * properties and the callback routine to handle errors. # * Note that the cylinder has no top or bottom and the circle # * has a hole in it. # */ require "opengl" require "glut" require "mathn" CO #void CALLBACK errorCallback(GLenum errorCode) #{ # const GLubyte *estring; # # estring = gluErrorString(errorCode); # fprintf(stderr, "Quadric Error: %s\n", estring); # exit(0); #} BY def init mat_ambient = [ 0.5, 0.5, 0.5, 1.0 ]; mat_specular = [ 1.0, 1.0, 1.0, 1.0 ]; mat_shininess = [ 50.0 ]; light_position = [ 1.0, 1.0, 1.0, 0.0 ]; model_ambient = [ 0.5, 0.5, 0.5, 1.0 ]; GL.ClearColor(0.0, 0.0, 0.0, 0.0); GL.Material(GL::FRONT, GL::AMBIENT, mat_ambient); GL.Material(GL::FRONT, GL::SPECULAR, mat_specular); GL.Material(GL::FRONT, GL::SHININESS, mat_shininess); GL.Light(GL::LIGHT0, GL::POSITION, light_position); GL.LightModel(GL::LIGHT_MODEL_AMBIENT, model_ambient); RU GL.Enable(GL::LIGHTING); GL.Enable(GL::LIGHT0); GL.Enable(GL::DEPTH_TEST); #/* Create 4 display lists, each with a different quadric object. # * Different drawing styles and surface normal specifications # * are demonstrated. # */ $startList = GL.GenLists(4); qobj = GLU.NewQuadric(); # # KAPITEL 2. EXAMPLES AND EXERCISES H 40 gluQuadricCallback(qobj, GLU_ERROR, (GLvoid (CALLBACK*) ()) errorCallback); AC GLU.QuadricDrawStyle(qobj, GLU::FILL); #/* smooth shaded */ GLU.QuadricNormals(qobj, GLU::SMOOTH); GL.NewList($startList, GL::COMPILE); GLU.Sphere(qobj, 0.75, 15, 10); GL.EndList(); GLU.QuadricDrawStyle(qobj, GLU::FILL); #/* flat shaded */ GLU.QuadricNormals(qobj, GLU::FLAT); GL.NewList($startList+1, GL::COMPILE); GLU.Cylinder(qobj, 0.5, 0.3, 1.0, 15, 5); GL.EndList(); CO GLU.QuadricDrawStyle(qobj, GLU::LINE); #/* all polygons wireframe */ GLU.QuadricNormals(qobj, GLU::NONE); GL.NewList($startList+2, GL::COMPILE); GLU.Disk(qobj, 0.25, 1.0, 20, 4); GL.EndList(); GLU.QuadricDrawStyle(qobj, GLU::SILHOUETTE); #/* boundary only GLU.QuadricNormals(qobj, GLU::NONE); GL.NewList($startList+3, GL::COMPILE); GLU.PartialDisk(qobj, 0.0, 1.0, 20, 4, 0.0, 225.0); GL.EndList(); end BY display = Proc.new { GL.Clear(GL::COLOR_BUFFER_BIT | GL::DEPTH_BUFFER_BIT); GL.PushMatrix(); GL.Enable(GL::LIGHTING); GL.ShadeModel(GL::SMOOTH); GL.Translate(-1.0, -1.0, 0.0); GL.CallList($startList); RU GL.ShadeModel(GL::FLAT); GL.Translate(0.0, 2.0, 0.0); GL.PushMatrix(); GL.Rotate(300.0, 1.0, 0.0, 0.0); GL.CallList($startList+1); GL.PopMatrix(); GL.Disable(GL::LIGHTING); GL.Color(0.0, 1.0, 1.0); GL.Translate(2.0, -2.0, 0.0); GL.CallList($startList+2); */ 2.21. QUADRIC GL.PopMatrix(); GL.Flush(); } AC GL.Color(1.0, 1.0, 0.0); GL.Translate(0.0, 2.0, 0.0); GL.CallList($startList+3); H 41 CO reshape = Proc.new {|w, h| GL.Viewport(0, 0, w, h); GL.MatrixMode(GL::PROJECTION); GL.LoadIdentity(); if (w <= h) GL.Ortho(-2.5, 2.5, -2.5*h/w, 2.5*h/w, -10.0, 10.0); else GL.Ortho(-2.5*w/h, 2.5*w/h, -2.5, 2.5, -10.0, 10.0); end GL.MatrixMode(GL::MODELVIEW); GL.LoadIdentity(); } BY #/* ARGSUSED1 */ keyboard = Proc.new {|key, x, y| case (key) when 27 exit(0); end } RU #int main(int argc, char** argv) #{ GLUT.Init GLUT.InitDisplayMode(GLUT::SINGLE | GLUT::RGB | GLUT::DEPTH); GLUT.InitWindowSize(500, 500); GLUT.InitWindowPosition(100, 100); GLUT.CreateWindow($0); init(); GLUT.DisplayFunc(display); GLUT.ReshapeFunc(reshape); GLUT.KeyboardFunc(keyboard); GLUT.MainLoop(); # return 0; #} Protocol quadric.log D:\bonin\rubyScript>ruby --copyright KAPITEL 2. EXAMPLES AND EXERCISES BY Legende: Source code → p. 38 CO AC H 42 Abbildung 2.2: Running quadric.rbw ruby - Copyright (C) 1993-2003 Yukihiro Matsumoto D:\bonin\rubyScript>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] D:\bonin\rubyScript>ruby ./code/quadric.rbw RU D:\bonin\rubyScript> 2.22 Biorhythm Script biorhythm.rb Remark: Source code → /ruby/doc/Ruby-1.8.0/samples/biorhythm.rb 2.22. BIORHYTHM H AC biorhythm.rb $Release Version: $ $Revision: 1.9 $ $Date: 2003/05/05 14:02:14 $ by Yasuo OHBA(STAFS Development Room) probably based on: Newsgroups: comp.sources.misc,de.comp.sources.os9 From: [email protected] (Frank Kaefer) Subject: v41i126: br - Biorhythm v3.0, Part01/01 Message-ID: <[email protected]> Sender: [email protected] (Kent Landfield) Organization: Sterling Software Date: Tue, 1 Feb 1994 07:06:16 GMT Posting-number: Volume 41, Issue 126 Archive-name: br/part01 Environment: basic, dos, os9 include require require require CO # # # # # # # # # # # # # # # # # # 43 Math "date.rb" "parsearg.rb" "parsedate.rb" : : : : : : use default values.\n" use system date; use specified date.\n" specifies your birthday.\n" show values or graph.\n" graph range (only in effect for graphs).\n" help\n" BY def usage() print "Usage:\n" print "biorhythm.rb [options]\n" print " options...\n" print " -D YYYYMMDD(birthday) print " --sdate | --date YYYYMMDD print " --birthday YYYYMMDD print " -v | -g print " --days DAYS print " --help end $USAGE = ’usage’ def printHeader(y, m, d, p, w) print "\n>>> Biorhythm <<<\n" printf "The birthday %04d.%02d.%02d is a %s\n", y, m, d, w printf "Age in days: [%d]\n\n", p end RU def getPosition(z) pi = Math::PI z = Integer(z) phys = (50.0 * (1.0 + sin((z / 23.0 - (z / 23)) * 360.0 * pi / 180.0))).to_i emot = (50.0 * (1.0 + sin((z / 28.0 - (z / 28)) * 360.0 * pi / 180.0))).to_i geist =(50.0 * (1.0 + sin((z / 33.0 - (z / 33)) * 360.0 * pi / 180.0))).to_i return phys, emot, geist end def parsedate(s) ParseDate::parsedate(s).values_at(0, 1, 2) end KAPITEL 2. EXAMPLES AND EXERCISES H 44 def name_of_week(date) Date::DAYNAMES[date.wday] end (YYYYMMDD) : ") CO if $OPT_D dd = Date.today bd = Date.new(*parsedate($OPT_D)) ausgabeart = "g" else if $OPT_birthday bd = Date.new(*parsedate($OPT_birthday)) else STDERR.print("Birthday unless (si = STDIN.gets.chop).empty? bd = Date.new(*parsedate(si)) end end if !bd STDERR.print "BAD Input Birthday!!\n" exit() end AC # # main program # parseArgs(0, nil, "vg", "D:", "sdate", "date:", "birthday:", "days:") BY if $OPT_sdate dd = Date.today elsif $OPT_date dd = Date.new(*parsedate($OPT_date)) else STDERR.print("Date [<RETURN> for Systemdate] (YYYYMMDD) : ") unless (si = STDIN.gets.chop).empty? dd = Date.new(*parsedate(si)) end end dd ||= Date.today RU if $OPT_v ausgabeart = "v" elsif $OPT_g ausgabeart = "g" else STDERR.print("Values for today or Graph (v/g) [default g] : ") ausgabeart = STDIN.gets.chop end end if ausgabeart == "v" printHeader(bd.year, bd.month, bd.day, dd - bd, name_of_week(bd)) print "\n" phys, emot, geist = getPosition(dd - bd) printf "Biorhythm: %04d.%02d.%02d\n", dd.year, dd.month, dd.day printf "Physical: %d%%\n", phys printf "Emotional: %d%%\n", emot 2.22. BIORHYTHM H 45 AC printf "Mental: %d%%\n", geist print "\n" else if $OPT_days display_period = $OPT_days.to_i elsif $OPT_D display_period = 9 else STDERR.printf("Graph for how many days [default 10] : ") display_period = STDIN.gets.chop if display_period.empty? display_period = 9 else display_period = display_period.to_i - 1 end end CO printHeader(bd.year, bd.month, bd.day, dd - bd, name_of_week(bd)) print " P=physical, E=emotional, M=mental\n" print " -------------------------+-------------------------\n" print " Bad Condition | Good Condition\n" print " -------------------------+-------------------------\n" (dd - bd).step(dd - bd + display_period) do |z| phys, emot, geist = getPosition(z) BY printf "%04d.%02d.%02d : ", dd.year, dd.month, dd.day p = (phys / 2.0 + 0.5).to_i e = (emot / 2.0 + 0.5).to_i g = (geist / 2.0 + 0.5).to_i graph = "." * 51 graph[25] = ?| graph[p] = ?P graph[e] = ?E graph[g] = ?M print graph, "\n" dd = dd + 1 end print " -------------------------+-------------------------\n\n" end Protocol biorhythm.log D:\bonin\rubyScript\code>ruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] RU D:\bonin\rubyScript\code>biorhythm --help Usage: biorhythm.rb [options] options... -D YYYYMMDD(birthday) : use default values. --sdate | --date YYYYMMDD : use system date; use specified date. --birthday YYYYMMDD : specifies your birthday. -v | -g : show values or graph. --days DAYS : graph range (only in effect for graphs). --help : help >>> Biorhythm <<< The birthday 1945.05.08 is a Tuesday Age in days: [21390] : : : : : : : : : : P=physical, E=emotional, M=mental -------------------------+------------------------Bad Condition | Good Condition -------------------------+------------------------..............E..........P......................M.. ...................E.....|......P................M. .........................E............P...........M .........................|.....E...........P......M .........................|..........E..........P.M. .........................|...............E.....M.P. .........................|..................ME....P .........................|..............M.......EP. .........................|..........M........P...E. .........................|......M........P........E -------------------------+------------------------- D:\bonin\rubyScript\code> CO 2003.11.30 2003.12.01 2003.12.02 2003.12.03 2003.12.04 2003.12.05 2003.12.06 2003.12.07 2003.12.08 2003.12.09 AC D:\bonin\rubyScript\code>biorhythm -D 19450508 --sdate -v H KAPITEL 2. EXAMPLES AND EXERCISES 46 2.23 WIN32OLE — Internetexplorer BY Methods that aren’t known to WIN32OLE (such as visible or gohome) are passed on to the WIN32OLE#invoke method, which sends the proper commands to the server. Script internetexplorer.rbw RU # # A fresh copy of Internet Explorer # # Hinrich Bonin # 12-Dec-2003 # require ’win32ole’ ie = WIN32OLE.new(’InternetExplorer.Application’) ie.visible = true ie.gohome # EOF 193.174.33.66 D:/bonin/rubyScript/code/internetexplorer.rbw Protocol internetexplorer.log d:\bonin\rubyScript\code>irb --version irb 0.9(02/07/03) d:\bonin\rubyScript\code>irb BY CO AC H 2.23. WIN32OLE — INTERNETEXPLORER Legende: Source code → p. 42 RU Abbildung 2.3: Running biorhythm.rb 47 H KAPITEL 2. EXAMPLES AND EXERCISES 48 d:\bonin\rubyScript\code>internetexplorer d:\bonin\rubyScript\code> 2.24 WIN32OLE — Excel AC irb(main):001:0> require ’win32ole’ => true irb(main):002:0> WIN32OLE::VERSION => "0.5.4" irb(main):003:0> exit # # Using Microsoft Excel # # Hinrich Bonin # 12-Dec-2003 # require ’win32ole’ CO Script excel.rbw Remark: Source code idea → /ruby/ProgrammingRuby.chm, section: Ruby and Microsoft Windows, Windows Automation, An Example # -4100 is the value for the Excel constant xl3DColumn. ChartTypeVal = -4100; # Create the chart BY # Creates OLE object to Excel excel = WIN32OLE.new("excel.application") excel[’Visible’] = TRUE; workbook = excel.Workbooks.Add(); excel.Range("a1")[’Value’] = 3; excel.Range("a2")[’Value’] = 2; excel.Range("a3")[’Value’] = 1; excel.Range("a1:a3").Select(); excelchart = workbook.Charts.Add(); excelchart[’Type’] = ChartTypeVal; RU # EOF 193.174.33.66 D:/bonin/rubyScript/code/excel.rbw Protocol excel.log d:\bonin\rubyScript\code>irb --version irb 0.9(02/07/03) d:\bonin\rubyScript\code>irb irb(main):001:0> require ’win32ole’ => true 2.24. WIN32OLE — EXCEL CO AC H 49 Legende: Source code → p. 48 Abbildung 2.4: Running excel.rbw BY irb(main):002:0> WIN32OLE::VERSION => "0.5.4" irb(main):003:0> exit d:\bonin\rubyScript\code>excel RU d:\bonin\rubyScript\code> BY CO AC H KAPITEL 2. EXAMPLES AND EXERCISES RU 50 H AC Kapitel 3 CO Software Engineering Tools 3.1 ri — Ruby Information at your fingertips Ruby information at your fingertips (ri) displays documentation for the named classes or methods. All names can be abbreviated to their minimum non-ambiguous size. The program files ri and refdoc.rb are copyright (c) 2001 Dave Thomas, The Pragmatic Programmers, and are released under the same terms as Ruby. D:\bonin\rubyScript>ri --version ri 1.8a BY D:\bonin\rubyScript>ri Bignum This is a test ’ri’. Please report errors and omissions on http://www.rubygarden.org/ruby?RIOnePointEight RU ------------------------------------------------------class: Bignum < Integer ------------------------------------------------------Bignum objects hold integers outside the range of Fixnum. Bignum objects are created automatically when integer calculations would otherwise overflow a Fixnum. When a calculation involving Bignum objects returns a result that will fit in a Fixnum, the result is automatically converted. For the purposes of the bitwise operations and [], a Bignum is treated as if it were an infinite-length bitstring with 2’s complement representation. While Fixnum values are immediate, Bignum objects are not---assignment and parameter passing work with references to objects, not the objects 51 ri KAPITEL 3. SOFTWARE ENGINEERING TOOLS CO AC H 52 Legende: Simple examble in the Interactive Ruby Shell. themselves. BY Abbildung 3.1: irb — Interactive Ruby Shell RU ------------------------------------------------------<=>, ==, Arithmeticoperations, Bitoperations, [], abs, div, divmod, eql?, modulo, quo, remainder, size, to_f, to_s ------------------------------------------------------D:\bonin\rubyScript> 3.2 irb — Interactive Ruby Shell The Ruby module irb lets you enter Ruby programs interactively and see the results immediately. The figure 3.1 p. 52 shows a simple example. 3.3. RUBY-MODE — EMACS MODE BY CO AC H 53 Legende: Ruby file Hound.rb in editor GNU Emacs 21.2.1. Abbildung 3.2: ruby-mode — Editor Emacs 3.3 ruby-mode — Emacs Mode RU 1. Step: load-library C:\Programme\ruby\lib\ruby-mode.el Remark: You type ESC , than x and than the characters above. 2. Step: enable ruby-mode Remark: You type ESC , than x and than ruby-mode. The figure 3.2 p. 53 shows a simple example. KAPITEL 3. SOFTWARE ENGINEERING TOOLS BY CO AC H 54 Legende: RDtool file Hound.rd in editor GNU Emacs 21.2.1. Abbildung 3.3: rd-mode — Editor Emacs 3.4 rd-mode — Emacs Mode The figure 3.3 p. 54 shows a simple example. Installing rd2 → section 3.8 p. 57. RU 1. Step Copying rd-mode.el into the Emacs lib-path, for example: D:\bonin\rubyScript\rdtool\rdtool-0.6.14\utils\rd-mode.el into: C:\Programme\ruby\lib\ 2. Step Updating the Emacs load file emacs, for example: C:_emacs with the following lines: 55 H 3.5. ERUBY — EMBEDDING RUBY IN HTML AC ;; Unterstützung für rd-mode (setq load-path (cons "c:/programme/ruby/lib/" load-path)) (require ’rd-mode) 3. Step: enable rd-mode Remark: You type ESC , than x and than rd-mode. 3.5 eruby — Embedding Ruby in HTML Protocol myeruby.log CO D:\bonin\rubyScript>eruby --version ruby 1.8.0 (2003-08-04) [i386-mswin32] eRuby version 1.0.4 D:\bonin\rubyScript>eruby < ./html/myinput.erb > ./html/myoutput.html D:\bonin\rubyScript> Input file myinput.erb RU BY <?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <!-- Hinrich Bonin 15-Dec-2003 --> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" > <head> <title>My eRuby</title> </head> <body> <p>eRuby is <% n = 100; print "#{n}% scripting fun!" %></p> </body> </html> Output file myoutput.html <?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <!-- Hinrich Bonin 15-Dec-2003 --> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" > 3.6 Framework Ruby on Rails Ruby on Rails (RoR1 ) is a full-stack framework for developing databasebacked web applications according to the Model-View-Control pattern. RoR takes full advantage of Ruby. RoR has two guiding principles: CO RoR AC <head> <title>My eRuby</title> </head> <body> <p>eRuby is 100% scripting fun!</p> </body> </html> H KAPITEL 3. SOFTWARE ENGINEERING TOOLS 56 1. less software and Less software means the programmer writes fewer lines of code to implement an application. Keeping the code small means faster development and fewer bugs. RoR was created by David Heinemeier Hansson in July 2004. RoR is an open source Web 2.0-Framework released under MIT license. RoR is all about infrastructure so it’s a great fit for practically any type of web application — software for collaboration, community, e-commerce, content management, statistics etc. (→ http://www.rubyonrails.org/, visited 22-Apr-2007) 3.7 Eclipse — Plug-In RU Web 2.0 BY 2. Convention over Configuration. Convention over configuration means an end to verbose XML configuration files — there aren’t any in Rails! Instead of configuration files, a Rails application uses a few simple programming conventions that allow it to figure out everything through reflection and discovery. The application code and the running database already contain everything that Rails needs to know. Eclipse consits of the following key components (→ [Gamma / Beck, 2004] p. 6.): • Core: 1 German: ≈ Ruby auf dem rechten Weg 3.8. RD2 — FORMATER TOOL H 57 Eclipse Architecture PDE (Plug-In Development Environment) AC JDT (Java Development Tools) Platform Legende: PDE CO extends the JDT with the support for developing plugins. JDT add a full-featured Java IDE to Eclipse Platform defines the common programming-language-neutral infrastructure. Source → [Gamma / Beck, 2004] p. 5. Tabelle 3.1: Eclipse — The Three Layers – The run-time component defines the plug-in infrastructure. It discovers the available plug-ins on start-up and manages the plug-in loading. Runtime – A workspace manages one or more top-level projects. A project consits of file and folders that map onto the underlying file system. Workspace BY • UI (User Interface): SWT – JFace — A set of smaller UI frameworks built on top of SWT supporting common UI tasks. JFace – The workbench defines the Eclipse UI paradigm. It centers around editors, views, and perspectives. Workbench RU – The SWT (Standard Widget Toolkit) provides graphics and define a standard set of widgets. 3.8 rd2 — formater tool Installing the formater tool rd2 on Windows: → http://www.dets-home.de/it-writings/Install rd2 winnt.html (online 19-Dec-2003). KAPITEL 3. SOFTWARE ENGINEERING TOOLS BY CO AC H 58 Legende: Ruby Plug-Ins (org.rubypeople.rdt.core (0.3.2) etc., copyright RubyPeople, Inc. 2002) in Eclipse Platform (version 2.1.1). RU Abbildung 3.4: ruby-plug-ins — Eclipse 3.8. RD2 — FORMATER TOOL BY CO AC H 59 Legende: Script prime.rb →p. 11 in Eclipse Platform (version 2.1.1). RU Abbildung 3.5: Script prime.rb — Eclipse H KAPITEL 3. SOFTWARE ENGINEERING TOOLS 60 3.8.1 Prerequisite racc tool AC The tool racc is a LALR(1) parser generator. It is written in Ruby itself, and generates Ruby program. For Ruby 1.8.0: Take racc for Windows from: ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ext/racc-1.4.4-all-i386-mswin32-1.8.zip (online 19-Dec-2003) Extract this archive in a temporary directory (below referred to as instsrc) racc.bat 1. Copy racc.bat from directory instsrc/bin to $ruby home/bin 2. Goto instsrc/lib/ruby/site ruby/1.8 4. Goto instsrc/doc/ruby CO 3. Copy directory racc to $ruby home/lib/ruby/site ruby/1.8 5. Copy subdir racc-1.4.4-all to $ruby home/doc/ruby To test it, type: d:\bonin\rubyScript>racc --version racc version 1.4.4 d:\bonin\rubyScript> BY 3.8.2 rdtool — Installation Fetch the rdtool tarball (e. g. rdtool-0.6.11.tar.gz) from: http://www.ruby-lang.org/en/raa-list.rhtml?name=RDtool (online 19-Dec-2003) and extract it in a temporary directory (in the following referred to as instsrc). 1. Open a DOS-box (cmd.exe) and go to instsrc RU rd2.bat 2. Execute: racc rd/rdblockparser.ry Note: Your $ruby home/bin should be in your path, then racc will be found. 3. Execute: racc rd/rdinlineparser.ry 4. Copy the directory instsrc/rd to $ruby home/lib/ruby/site ruby/1.8 5. Copy the file ../rd2 to $ruby home/bin 3.8. RD2 — FORMATER TOOL H 61 6. Goto $ruby home/bin and create a file rd2.bat containing: AC @echo off "$ruby_home\bin\ruby.exe" "$ruby_home\bin\rd2" %1 %2 %3 %4 %5 %6 %7 %8 %9 (Note: You have to replace $ruby home with the actual path to your Ruby installation). To test it, copy a rd-file, open the DOS-Box, go to this directory and call: CO D:\bonin\rubyScript>rd2 --version RDtool -- rd2 0.6.13 RDtool Framework -- Document Tree 0.6.13 RDtool Framework -- Visitor 0.6.13 D:\bonin\rubyScript>rd2 ./code/Hound.rd > ./html/Hound.html D:\bonin\rubyScript> RD-File Hound.rd RU BY # # Simple inheritance example # # Hinrich Bonin # 3-Dec-2003 # =begin = My Hound Application == Written in Ruby === A Simple rd2 Example ==== H. Bonin 3-Dec-2003 Ruby-Example with * inheritance * String ** super ** #{@xxx} class Mammal def initialize(name,sex) @name = name KAPITEL 3. SOFTWARE ENGINEERING TOOLS H 62 AC @sex = sex end def to_s "#{@name} (#{@sex})" end end CO class Hound < Mammal def initialize(name,sex,performance,race) super(name,sex) @performance = performance @race = race end def to_s "Hound: " + "#{@race} " + super + " --- #{@performance}" end end elsa = Hound.new("Elsa vom Erlenbruch", "male" , "SWI", "German Setter") puts(elsa.to_s) BY # EOF 193.174.33.66 D:/bonin/rubyScript/code/Hound.rb =end Produced HTML-File Hound.html RU <?xml version="1.0" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Untitled</title> </head> <body> <h1><a name="label-0" id="label-0">My Hound Application</a></h1> <!-- RDLabel: "My Hound Application" --> <h2><a name="label-1" id="label-1">Written in Ruby</a></h2> <!-- RDLabel: "Written in Ruby" --> <h3><a name="label-2" id="label-2">A Simple rd2 Example</a></h3> <!-- RDLabel: "A Simple rd2 Example" --> 63 H 3.9. DYBASE — OBJECT ORIENTED DBMS BY CO AC <h4><a name="label-3" id="label-3">H. Bonin 3-Dec-2003</a></h4> <!-- RDLabel: "H. Bonin 3-Dec-2003" --> <p>Ruby-Example with</p> <ul> <li>inheritance</li> <li>String</li> <li>* super</li> <li>* #{@xxx}</li> </ul> <p>class Mammal</p> <pre>def initialize(name,sex) @name = name @sex = sex end def to_s "#{@name} (#{@sex})" end</pre> <p>end</p> <p>class Hound < Mammal</p> <pre>def initialize(name,sex,performance,race) super(name,sex) @performance = performance @race = race end def to_s "Hound: " + "#{@race} " + super + " --- #{@performance}" end</pre> <p>end</p> <p>elsa = Hound.new("Elsa vom Erlenbruch", "male" ,</p> <pre>"SWI", "German Setter")</pre> <p>puts(elsa.to_s)</p> RU </body> </html> 3.9 DyBASE — Object Oriented DBMS DyBASE2 is very simple OODBMS (Object Oriented Database Man2 DyBASE Web-Site: http://www.garret.ru/k̃nizhnik online 18-Dec2003 OODBMS KAPITEL 3. SOFTWARE ENGINEERING TOOLS BY CO AC H 64 RU Legende: Script Hound.rd →p. 61 applied to RDtool rd2 (version 0.6.13). Abbildung 3.6: Script Hound.rd — rd2 65 H 3.9. DYBASE — OBJECT ORIENTED DBMS AC agement System for languages with dynamic type checking. The specific of such languages is that types of class instance variables are not known at compiler time. Moreover the same instance variable can be used to store integers and string and later be assigned reference to some other object. So it means that database could not keep information about object format in class descriptor and should store type for each instance variable. DyBASE provides APIs to the most popular scripting languages with OO extensions: PHP, Ruby and Python. Add to your ruby-path the fowllowing files: CO C:\Programme\ruby\bin\dybasedll.dll C:\Programme\ruby\lib\ruby\1.8\dybase.rb C:\Programme\ruby\lib\ruby\1.8\dybaseapi.dll from the download file dybase-013.zip. 3.9.1 Application Program Interface Persistent class Persistent class is common root for all persistent capable objects. It provides method for loading and storing object. load() Explicitly load object. This method check if objects needs to be loaded, and if so load it from the storage. BY isLoaded() Check if object is already loaded or explicit invocation of load() method is required. Returns: True if object is loaded, False otherwise isPersistent() Check if object is persistent (was assigned persistent OID). Returns: True if object is persistent, False otherwise isModified() Check if object was modified during current transaction Returns: True if modify method was invoked for the object within current transaction, False otherwise RU store() Store the object in the storage. If object is not yet persistent it is first made persistent by assigning persistent OID. If object references some other non-persistent object then they recursively made persistent and also stored in the storage. But referenced persistent objects are not recursively stored. You should invoke store method explicitly for each changed persistent object. modify() Mark object as modified. This object will be automatically stored to the database during transaction commit. KAPITEL 3. SOFTWARE ENGINEERING TOOLS H 66 getStorage() Get storage in which object is stored. Returns: Storage in which object is stored or Null if object is not persistent. deallocate() Deallocate object in the storage. This method doesn’t affect AC instance of the object in application memory — it is deallocated in normal way by language runtime. If you are using garbage collector, there is no need in invocation of this method. CO sharedLock(nowait=false) Lock persistent object in shared mode. Other threads will be able to set their shared locks on this objects, but not exclusive lock can be set until this lock is released. Upgrading of the lock is not possible (thread having read lock can not upgrade it to exclusive lock). It is done to prevent possible deadlocks caused by lock updates. But locks are reentrant - so thread can request the same lock many times (and correspondent number of unlocks is needed to release the lock). Locking the object doesn’t prevent other threads from accessing the object — it only has influence on sharedLock and exclusiveLock methods. So programmer should set proper lock before accessing the object in multithreaded application. If object is concurrently accessed by several threads in read-only mode, then explicit locking of this object is not needed, because language API provides consistent retrieving of objects itself. Only persistent object (object which were assigned to the storage either implicitly by saving some other persistent object referencing this object, either explicitly by Storage.makeObjectPersistent method. Parameters nowait — optional parameter specifying whether request should wait until lock is available or fail if lock can not be granted immediately. Returns: true if lock is successfully granted false if lock can not be granted within specified time. RU BY exclusiveLock(nowait=false) Lock persistent object in exclusive mode. Only one thread can lock object in exclusive mode at each moment of time. Shared or exclusive lock requests of other threads will be blocked until this lock is released. shared locks on this objects, but not exclusive lock can be set until this lock is released. This lock is reentrant, so thread owning the lock can successfully retrieve the lock many times (and correspondent number of unlocks is needed to release the lock). Locking the object doesn’t prevent other threads from accessing the object - it only has influence on sharedLock and exclusiveLock methods. So programmer should set proper lock before accessing the object in multithreaded application. Only persistent object (object which were assigned to the storage either implicitly by saving some other persistent object referencing this object, either explicitly by Storage.makeObjectPersistent method. Parameters nowait — optional parameter specifying whether request should wait until lock is available or fail if lock can not be granted immediately. Returns: true if lock is successfully granted false if lock can not be granted within specified time. unlock() Remove granted lock. If lock was requested several times by one thread, then correspondent number of unlocks is needed to release the lock. Index class The index class provides access to the objects by key. Keys of any scalar or string type are supported. But in one index can contains keys only of one type. Index class extends Persistent class and so it is normal Persistent object. Index can be unique (duplicated keys are prohibited) or not unique. 67 H 3.9. DYBASE — OBJECT ORIENTED DBMS drop() Delete index. This method removes all entries from index and deallocate index object. clear() Remove all entries from the index. This method doesn’t deallocate in- AC dexed objects. insert(key, value) Insert object in index. Parameters key — key with type matching with type of the index value — persistent capable object to be associated with this key. This object is automatically made persistent (if it isn’t persistent yet). Returns: true if object was successfully inserted in index, false if index is unique and such key already exists in index. CO set(key, value) Set object for the specified key. If such key already exists in the index, previous association of this key will be replaced. Parameters key — key with type matching with type of the index value — persistent capable object to be associated with this key. This object is automatically made persistent (if it isn’t persistent yet). remove(key, value=Null) Remove object from index. Parameters key — key with type matching with type of the index value — optional reference to the persistent object removed from the index. If index is unique, this parameter can be skipped. Returns: true if object was successfully removed from the index, false if there is no object with such key in index. BY get(key) Get object associated with specified key. Parameters key — key with type matching with type of the index. Returns: Null if there is no object with such key in the index, object itself if there is only one object with such key in the index, array of object if there are more than one object with such key in the index find(low=null, lowInclusive=true, high=null, highInclusive=true) Get objects which keys belongs to the specified range. Parameters low — low boundary for key value, if Null than there is no low boundary. lowInclusive — if low boundary is inclusive or not high — high boundary for key value, if Null than there is no high boundary. highInclusive — if high boundary is inclusive or not Returns: Array of selected objects or Null if there are no object with key belonging to the specified range iterator(low=null, lowInclusive=true, high=null, highInclusive=true, ascent=true) Get iterator for objects in RU the index. Objects will be traversed in key ascending order. Details of iterator’s implementation depends on particular language. Parameters low — low boundary for key value, if Null than there is no low boundary. lowInclusive — if low boundary is inclusive or not high — high boundary for key value, if Null than there is no high boundary. highInclusive — if high boundary is inclusive or not ascent — iteration order: if true, then objects will be traversed in key ascending order Returns: Usually this method returns iterator object, but in some languages it is possible to pass block of code which will be executed for each selected object. KAPITEL 3. SOFTWARE ENGINEERING TOOLS H 68 Storage class AC Storage is class is the main class of DyBASE API. It provides access to the database storage. Storage(pagePoolSize = 4*1024*1024, objectCacheSize = 1000) Storage constructor. Parameters pagePoolSize — database page pool in bytes (larger page pool usually leads to better performance) objectCacheSize — this parameter is used only by some of languages API and specify maximal number of objects in application object cache. Not all languages APIs maintain such cache. Returns: Storage object. It is not opened and you should invoke open method explicitly. CO open(path) Storage constructor. Parameters path — path to the database file Returns: true if storage is successfully opened, false otherwise. Some language APIs do not return false, but throw exception in case of failure. close() Close the storage. If there is opened transaction, it will be first committed. commit() Commit current transaction. Transaction is automatically started once you update the database first time. BY rollback() Rollback current transaction. All changes done by current transaction are undone. Attention! Rollback of transaction did not restore original values of application objects. It just clears object cache. You should not use any variable referencing persistent object after rollback, but instead of it use Storage.getRootObject method and traverse objects from the root. getRootObject() Get storage root object. Returns: Loaded storage root object or Null if root was not yet specified. setRootObject(root) Specify new storage root object. Previous root object (if exists) is NOT deallocated. Parameters: root — new storage root object which is automatically made persistent. RU deallocateObject(obj) Deallocate persistent object from the storage. If object is not persistent, this method has no effect. Parameters: obj — persistent object. makeObjectPeristent(obj) Explicitly make object persistent. Object is automatically made persistent when persistent object containing reference to this object is stored (persistency by reachability). But sometimes you may need to force assignment OID and storage reference to the object. It can be done by makePerisistent method. This method doesn’t actually store object in the storage, just assign OID to it. Parameters: obj — object to be made persistent, if it is already persistent = method as no effect. 69 H 3.9. DYBASE — OBJECT ORIENTED DBMS AC This method is usually invoked by Persistent.store() method. storeObject(obj) Make object persistent if it is not yet persistent and store it in the storage. Parameters: obj — stored object. This method is usually invoked by Persistent.modify() method. modifyObject(obj) Mark object as modified. This object will be automatically stored to the database during transaction commit. Parameters: obj - modified object. loadObject(obj) Load object from the storage. This method is usually invoked by Persistent.load() method. Parameters: obj — loaded object. CO createStrIndex(unique = True) Create index for keys of string type. Parameters: unique — whether duplicated keys are allowed or not (by default not allowed) Returns: Index object createIntIndex(unique = True) Create index for keys of integer type. Parameters: unique — whether duplicated keys are allowed or not (by default not allowed) Returns: Index object createLongIndex(unique = True) Create index for keys of long integer type. Not all languages supports long (64-bit integer) type and so do not provide such method. Parameters: unique — whether duplicated keys are allowed or not (by default not allowed) Returns: Index object BY createBoolIndex(unique = True) Create index for keys of boolean type. Not all languages supports boolean type and so do not provide such method. Parameters: unique — whether duplicated keys are allowed or not (by default not allowed) Returns: Index object createRealIndex(unique = True) Create index for keys of floating point type. Parameters: unique — whether duplicated keys are allowed or not (by default not allowed) Returns: Index object RU resetHash() Reset object hash. Each fetched object is stored in objByOidMap hash table. It is needed to provide OID-¿instance mapping. Since placing object in hash increase its access counter, such object can not be deallocated by garbage collector. So after some time all persistent objects from the storage will be loaded to the memory. To solve the problem almost all languages with implicit memory deallocation (garbage collection) provides weak references. But in some of them weak references are not supported and sometime implementation of weak references is very inefficient. So to prevent memory overflow you should use resetHash() method. This method just clear hash table. After invocation of this method, you should not use any variable referencing persistent objects. Instead you should invoke getRootObject method and access all other persistent objects only through the root. KAPITEL 3. SOFTWARE ENGINEERING TOOLS H 70 AC gc() Explicit start of garbage collector. Garbage collector will collect only committed object, so there is no need to invoke garbage collector more than once within one transaction. Garbage collection can be used together with explicit deallocator by Persistent.deallocate method. But when you are using garbage collector, you should be careful with keeping references to the persistent objects in local variables. If there are no references to such object from other persistent object (so it is not reachable from root object), then garbage collector can deallocate such object. If you then try to access or update this object using reference stored in local variable, you will get on error. CO setGcThreashold(maxAllocatedDelta) Set garbage collection threshold. By default garbage collection is disable (threshold is set to 0). If it is set to non zero value, GC will be started each time when delta between total size of allocated and deallocated objects exceeds specified threshold OR after reaching end of allocation bitmap in allocator. Parameters: maxAllocatedDelta — delta between total size of allocated and deallocated object since last GC or storage opening BY sharedLock(obj, nowait=false) Lock object in shared mode. Other threads will be able to set their shared locks on this objects, but not exclusive lock can be set until this lock is released. Upgrading of the lock is not possible (thread having read lock can not upgrade it to exclusive lock). It is done to prevent possible deadlocks caused by lock updates. But locks are reentrant - so thread can request the same lock many times (and correspondent number of unlocks is needed to release the lock). Locking the object doesn’t prevent other threads from accessing the object - it only has influence on sharedLock and exclusiveLock methods. So programmer should set proper lock before accessing the object in multithreaded application. If object is concurrently accessed by several threads in read-only mode, then explicit locking of this object is not needed, because language API provides consistent retrieving of objects itself. Parameters: obj — locked object nowait — optional parameter specifying whether request should wait until lock is available or fail if lock can not be granted immediately. Returns: true if lock is successfully granted false if lock can not be granted within specified time. RU exclusiveLock(obj, nowait=false) Lock object in exclusive mode. Only one thread can lock object in exclusive mode at each moment of time. Shared or exclusive lock requests of other threads will be blocked until this lock is released. shared locks on this objects, but not exclusive lock can be set until this lock is released. This lock is reentrant, so thread owning the lock can successfully retrieve the lock many times (and correspondent number of unlocks is needed to release the lock). Locking the object doesn’t prevent other threads from accessing the object — it only has influence on sharedLock and exclusiveLock methods. So programmer should set proper lock before accessing the object in multithreaded application. Parameters: obj — locked object nowait — optional parameter specifying whether request should wait until lock is available or fail if lock can not be granted immediately. Returns: true if lock is successfully granted false if lock can not be granted within specified time. unlock(obj) Remove granted lock. If lock was requested several times by one thread, then correspondent number of unlocks is needed to release the lock. Parameters: obj — unlocked object. 3.9.2 Example TestLink.rb H 3.9. DYBASE — OBJECT ORIENTED DBMS #!/usr/local/bin/ruby AC Source Code in the download file dybase-013.zip. =begin = Example: Supplier-Order-Detail database This example illustrates usage of one-to-many link in dybase =end require "dybase" include Dybase CO def input(prompt) begin print(prompt) s = gets() if s == nil break end s = s.strip() end until s.length != 0 s end BY class Detail<Persistent def initialize(name, weight, color) @name = name @color = color @weight = weight @orders = [] end attr_reader :name, :color, :weight, :orders end RU class Supplier<Persistent def initialize(name, address) @name = name @address = address @orders = [] end attr_reader :name, :address, :orders end class Order<Persistent def initialize(detail, supplier, quantity, price) 71 KAPITEL 3. SOFTWARE ENGINEERING TOOLS H 72 @detail = detail @supplier = supplier @quantity = quantity @price = price end db = Storage.new if db.open(’testlist.dbs’) root = db.getRootObject() if root == nil root = Root.new(db) db.setRootObject(root) end CO class Root<Persistent def initialize( db) @suppliers = db.createStrIndex @details = db.createStrIndex end attr_reader :suppliers, :details end AC end attr_reader :detail, :supplier, :quantity, :price RU BY while true puts ’------------------------------------------’ puts ’1. Add supplier’ puts ’2. Add detail’ puts ’3. Add order’ puts ’4. Search suppliers’ puts ’5. Search details’ puts ’6. Suppliers of detail’ puts ’7. Deails shipped by supplier’ puts ’8. Exit’ cmd = input(’> ’) if cmd == ’1’ name = input(’Supplier name: ’) address = input(’Supplier address: ’) supplier = Supplier.new(name, address) root.suppliers.insert(name, supplier) db.commit() elsif cmd == ’2’ name = input(’Detail name: ’) weight = input(’Detail weight: ’).to_f color = input(’Detail color: ’) detail = Detail.new(name, weight, color) root.details.insert(name, detail) db.commit() H 3.9. DYBASE — OBJECT ORIENTED DBMS 73 RU BY CO AC elsif cmd == ’3’ supplierName = input(’Supplier name: ’) supplier = root.suppliers.get(supplierName) if supplier == nil puts ’No such supplier’ retry end detailName = input(’Detail name: ’) detail = root.details.get(detailName) if detail == nil puts ’No such detail’ retry end quantity = input(’Quantity: ’).to_i price = input(’Price: ’).to_i order = Order.new(detail, supplier, quantity, price) detail.orders << order supplier.orders << order detail.store() supplier.store() db.commit() elsif cmd == ’4’ supplierName = input(’Supplier name prefix: ’) suppliers = root.suppliers.find(supplierName, true, supplierName + "\xFF", false) if suppliers == nil puts ’No such suppliers found’ else for supplier in suppliers puts supplier.name + "\t" + supplier.address end end elsif cmd == ’5’ detailName = input(’Detail name prefix: ’) details = root.details.find(detailName, true, detailName + "\xFF", false) if details == nil puts(’No such details found’) else for d in details puts d.name + "\t" + d.weight.to_s + "\t" + d.color end end elsif cmd == ’6’ detailName = input(’Detail name: ’) detail = root.details.get(detailName) if detail == nil puts ’No such detail’ else KAPITEL 3. SOFTWARE ENGINEERING TOOLS for order in detail.orders puts order.supplier.name end H 74 end db.close() puts ’End of session’ RU BY end CO AC end elsif cmd == ’7’ supplierName = input(’Supplier name: ’) supplier = root.suppliers.get(supplierName) if supplier == nil puts ’No such supplier’ else for order in supplier.orders puts order.detail.name end end elsif cmd == ’8’ break else puts ’Invalid command’ end 75 BY CO AC H 3.9. DYBASE — OBJECT ORIENTED DBMS Legende: Script TestLink.rb →p. 71 in Eclipse Platform (version 2.1.1). RU Abbildung 3.7: Script TestLink.rb — DyBASE BY CO AC H KAPITEL 3. SOFTWARE ENGINEERING TOOLS RU 76 H CO Resources AC Anhang A A.1 Web Sites A.1.1 Ruby Ruby homepage and downloads Yukihiro Matsumoto: → http://www.ruby-lang.org/en/ (visited 28-Nov2003) “Matz” Ruby on Rails → http://www.rubyonrails.org (visited 22-Apr-2007) BY Programming Ruby — The Pragmatic Programmer’s Guide → file://localhost/C:/Programme/ruby/ProgrammingRuby.chm (visited 03-Dec-2003) A.1.2 Java RU James Gosling / Bill Joy /Guy Steele /Gilad Bracha; The Java Language Specification, Second Edition → http://java.sun.com/docs/books/jls/second edition/html/j.title.doc.html (visited June 2002) A.1.3 Updates to this Book http://as.uni-lueneburg.de/ruby/updates.html (visited December 2003) A.2 Glossary JDT Java Development Tools 77 OODBMS Object Oriented Database Management System PDE Plug-In Development Environment RoR Ruby on Rails AC SWT Standard Widget Toolkit UI User Interface BY CO Bibliography RU A.3 H ANHANG A. RESOURCES 78 H AC Literaturverzeichnis [Arnold / Gosling, 1996] Ken Arnold / James Gosling; The Java Programming Language (Addison-Wesley) 1996. CO [Bonin, 1991] Hinrich E. G. Bonin; Software-Konstruktion mit LISP, Berlin New York (Walter de Gruyter), 1991. (german) [Gamma / Beck, 2004] Erich Gamma / Kent Beck; Contributing to Eclipse — Principles, Patterns, and Plug-Ins, Boston etc. (Addison-Wesley) 2004, the eclipse series, series editors: Erich Gamma / Lee Nackman / John Wiegand, ISBN 0-321-20575-8. [Röhrl+, 2002] Armin Röhrl / Stefan Schmiedl / Clemens Wyss; Programmieren mit Ruby; eine praxisorientierte Einführung, Heidelberg (dpunkt.verlag GmbH), 2002, ISBN 3-89864-151-1 (german). BY [Thomas / Hunt, 2002] David Thomas / Andrew Hunt; Programmieren mit Ruby, deutsche Übersetzung von Reder Translations, München u. a. (Addison-Wesley), 2002, ISBN 3-8273-1965-X (german). [Wirdemann / Baustert] Wirdemann, R. / Baustert, T. ; Rapid Web Development mit uby on Rails, München, Wien (Hanser) 2006. A.4 About this Document The following software is used to produce this document: Editor: GNU Emacs 21.3.1; JEdit 4.1 pre 5 RU Layout: TeX, Version 3.14159 (Web2c 7.3.7x), LaTeX2e <2000/06/01>; Document Class: book 2001/04/21 v1.4e Standard LaTeX document class Hardcopy: Corel CAPTURE 10; Corel PHOTO-PAINT 10 (version 10.427) Figure: Microsoft Visio 2000 SR1 (6.0.2072) Index: makeindex, version 2.13 [07-Mar-1997] (using kpathsea) DVI→PS: LATEX-File (Device Independent) to Postscript: dvips(k) 5.90a Copyright 2002 Radical Eye Software (www.radicaleye.com) 79 PS→PDF: Postscript file to PDF-File: Adobe Acrobat Distiller 8.0 RU BY CO AC Security: Adobe Acrobat 8.0 Professional H LITERATURVERZEICHNIS 80 H AC Abbildungsverzeichnis 1.1 Contents of this book Ruby Coach . . . . . . . . . . . . . . . . . . . 2.1 2.2 2.3 2.4 Running HelloWorld.rb Running quadric.rbw . . Running biorhythm.rb . Running excel.rbw . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 42 47 49 3.1 3.2 3.3 3.4 3.5 3.6 3.7 irb — Interactive Ruby Shell . . . ruby-mode — Editor Emacs . . . rd-mode — Editor Emacs . . . . . ruby-plug-ins — Eclipse . . . . . . . Script prime.rb — Eclipse . . . . Script Hound.rd — rd2 . . . . . Script TestLink.rb — DyBASE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 53 54 58 59 64 75 . . . . . . . . RU BY CO . . . . 81 6 ABBILDUNGSVERZEICHNIS RU BY CO AC H 82 H AC Tabellenverzeichnis 3.1 Eclipse — The Three Layers . . . . . . . . . . . . . . . . . . . . . . RU BY CO A.5 Index 83 57 BY RU H AC CO Index 84 H callcc, 34, 35 case, 17 CGI, 37 cgi.body, 37 cgi.br, 37 cgi.form, 37 cgi.h1, 37 cgi.head, 37 cgi.html, 37 cgi.out, 37 cgi.submit, 37 cgi.textarea(), 37 cgi.title, 37 class, 9, 18 clear(), 67 clone, 22, 31 close, 17 close(), 14, 68 Code Notation, 7 Comment, 18 commit(), 68, 71 concat(), 31 Configuration, 56 Convention, 56 Corel CAPTURE, 79 PHOTO-PAINT, 79 createBoolIndex(), 69 createIntIndex(), 69 createLongIndex(), 69 createRealIndex(), 69 createStrIndex(), 69 CO ’, 9, 15 ::, 8 <, 18 <<, 15 <=>, 51 ==, 51 ==>, 8 =∼, 12 [], 51 #, 8 $, 11 $\, 11 ‘, 16 AC Index BY abs, 51 Acrobat, 80 Distiller, 80 Adobe Acrobat, 80 Distiller, 80 Arithmeticoperations, 51 Arnold, Ken, 79 Array, 31 ascent, 67 attr accessor, 22 attr reader, 9 RU Baustert, T., 79 Beck, Kent, 79 Bignum, 51 Bitoperations, 51 Bonin, Hinrich E. G., 79 Book web-site, 77 Bracha, Gilad, 77 Date, 42 deallocate(), 66 call, 34, 35 85 AC Gamma, Erich, 79 gc(), 70 get(), 15, 67 getRootObject(), 68, 71 gets, 9 getStorage(), 66 GL.ClearColor(), 38 GL.Enable(), 38 GL.Light(), 38 GL.LightModel(), 38 GL.Material(), 38 glut, 38 GNU Emacs, 79 gohome, 46 Gosling, James, 77, 79 Hansson, David Heinemeier, 56 high, 67 highInclusive, 67 Hunt, Andrew, 79 id2name, 19 in, 15, 17 include, 26 Index, 66 Inheritance, 18 initialize, 9, 18 insert(), 67 inspect, 22 Integer, 51 InternetExplorer.Application, 46 irb, 13, 16 irb, 52 irb, 52 isLoaded(), 65 isModified(), 65 isPersistent(), 65 iterator(), 67 RU BY -e, 9 each, 29 each line, 12 each object(), 29 Eclipse, 56–57 example prime, 59 JFace, 57 Ruby plug ins, 58 Ruby Plug-In, 56 Runtime, 56 SWT, 57 three layers, 57 UI, 57 Workbench, 57 Workspace, 56 else, 17 Emacs GNU, 79 ruby-mode, 53 empty?, 31 end, 9, 17, 18 eql?, 51 eruby, 55 excel.application, 48 exclusiveLock(), 66, 70 exit(), 42 typewriter-like, 7 for, 15, 17 Fulton, Hal, 9 CO deallocateObject(), 68 def, 9, 18 Dir.open(.), 17 div, 51 divmod, 51 do, 14, 28 drop(), 67 dvips, 79 DyBASE, 63–74 example TestLink, 75 dybase.rb, 65 dybaseapi.dll, 65 dybasedll.dll, 65 File.open(), 28 find(), 67 Fixnum, 51 Font H INDEX 86 JDT, 57, 77 INDEX LATEX, 79 load(), 65 loadObject(), 69 low, 67 lowInclusive, 67 puts, 9, 18 quo, 51 racc.bat, 60 Rails, 56 rd-mode, 54 rd2, 57–63 rd2.bat, 60 RDtool example Hound, 64 Reflection, 56 remainder, 51 Remark, 18 remove(), 67 require, 15, 25, 26, 38 resetHash(), 69 return, 42 ri, 51 Röhrl, Armin, 79 rollback(), 68 RoR, 56, 78 Ruby Eclipse, 56 Emacs, 53 eruby, 55 Help, 51 HTML, 55 Interactiv Shell, 52 ruby-mode, 53 Runtime Eclipse, 56 AC JEdit, 79 JFace Eclipse, 57 join, 15 Joy, Bill, 77 H 87 BY CO makeObjectPeristent(), 68 Marshal.dump(), 28 Marshal.load(), 28 mathn, 38 Math::PI, 42 Matsumoto, Yukihiro, 21, 77 Matz, 9, 21, 77 message, 15 method missing(), 19 methods, 29 Microsoft Visio, 79 Mixins, 25 modify(), 65 module, 24, 26 modulo, 51 Nackman, Lee, 79 net/http, 15 Net::HTTP.new(), 15 new, 9, 18 nowait, 70 RU objectCacheSize, 68 ObjectSpace, 29 OODBMS, 65, 78 open(), 12, 14, 68 opengl, 38 pagePoolSize, 68 PDE, 57, 78 Persistent class, 65 print, 9, 11, 12, 14, 17 printf, 42 Schmiedl, Stefan, 79 Script Biorhythm, 42 biorhythm, 47 Calling Future Code, 35 Continuation, 34 Directory Access, 17 Excel, 48 excel.rbw, 49 Factorial, 10 HelloWorld, 9 Inheritance, 18 to s, 51 AC UI, 78 Eclipse, 57 unique, 69 unless, 34 unlock(), 66, 70 $USAGE, 42 usage(), 42 visible, 46 Visio Microsoft, 79 CO %w, 15 Web 2.0, 56 when, 17 while, 14 Wiegand, John, 79 win32ole, 46, 48 WIN32OLE.new(), 46, 48 WIN32OLE::VERSION, 46, 48 Wirdemann, R., 79 Workbench Eclipse, 57 Workspace Eclipse, 56 Wyss, Clemens, 79 RU BY Input-Output, 12 Internetexplorer, 46 Mixins, 25 MyCGI, 37 Namespace, 24 Prime Numbers, 11 Processes, 16 Quadric, 38 quadric, 42 Reflection, 29 RubyCoach, 6 Serialization, 27 Shallow copy, 22 Single Method, 19 TestLink, 71 Transaction, 13 turnround, 31 Web Pages, 15 Word Counter, 20 set(), 67 setGcThreashold(), 70 setRootObject(), 68, 71 sharedLock(), 66, 70 shift, 31, 34 size, 51 sort, 29 Source code Notation, 7 STDERR, 42 $stdin, 9 Steele, Guy, 77 Storage, 68, 71 store(), 65 Struct.new(), 28, 29 super(), 18 SWT, 78 Eclipse, 57 system(), 16 TEX, 79 Thomas, Dave, 51 Thomas, David, 79 Thread.new(), 15 today, 42 to f, 51 H INDEX 88 yield, 14 Yukihiro Matsumoto, 21, 77 INDEX RU BY CO AC H 89