Exception terjadi ketika aliran program terinterupsi karena error. Penanganan exception pada Ruby mirip dengan C++ dan Java.
| C++ | Java | Ruby |
|---|---|---|
| try {} | try{} | begin/end |
| catch {} | catch {} | rescue |
| finally | ensure | |
| throw | throw | raise |
Ketika terjadi error, baris selanjutnya tidak akan dieksekusi. Ruby akan menangkap error tersebut dengan rescue, dan akhirnya menjalankan instruksi ensure.
deffoostr="Hello world"str.barputs"This line is ignored"rescueNoMethodError=>eprint"Catching: " + e.to_srescueExceptionprint"Problem found!"ensureputs" -- This is it"endfoo# => Catching: undefined method `bar' for "Hello world":String -- This is itKita bisa melemparkan exception kapan saja dengan raise.
defgoo(n)ifn < 0raiseStandardError,"Negative number"elseputs"It's positive"endenddefhoogoo(-1)puts"It is printed?"rescueException=>eprint"Exception: " + e.to_sendhoo# => Exception: Negative numberSelain menggunakan keyword rescue dan raise, kita bisa juga menggunakan method catch
dan throw pada Ruby. Penggunaan argumen catch dan throw pada Ruby ini berbeda
dengan di Java, meskipun namanya sama.
defprint_me(n)putsnthrow:doneifn <= 0print_me(n-1)endcatch(:done)doprint_me(5)endPenggunaan throw dan catch di ruby sangat jarang dilakukan dan sebaiknya dihindari
Setiap method di ruby dapat menerima block sebagai argumen terakhir, sekalipun dalam definisi method tersebut tidak mencantumkan argumen block.
Untuk mengecek apakah terdapat sebuah argumen block, panggil block_given? dalam sebuah method.
Sedangkan untuk mengeksekusi block tersebut dapat menggunakan yield.
deffooifblock_given?yieldyieldelseputs'No block here'endendfoo{print'Hello '}# => Hello Hellofoo# => No block hereyield dapat menerima argumen yang akan diteruskan ke block yang dieksekusi
deffooyield([1,2,3])endfoodo |array|
putsarrayendRuby memungkinkan kita menyimpan procedure atau Proc sebagai objek lengkap dengan konteksnya.
Penggunaan block pada Ruby itu relatif sederhana. Meskipun demikian,
kita mungkin perlu punya beberapa block yang berbeda dan menggunakannya berkali-kali.
Untuk menghindari kode yang repetitif tersebut, kita bisa menyimpannya sebagai procedure
atau Proc, sebagai objek yang lengkap dengan konteksnya. Perbedaan antara block dan
Proc adalah block merupakan suatu Proc yang tidak bisa disimpan dan merupakan solusi sekali pakai.
deffoolabel=procdoprint"counting"endcount=Proc.newdo[1,2,3,4,5].eachdo |i| printiendputsendlabel.callprint" - "count.callendfoo# => counting - 12345Di Ruby, lambda merupakan suatu method yang menciptakan objek Proc yang terkait dengan konteks saat ini dan melakukan pengecekan parameter ketika dipanggil.
Berbeda dengan Proc, lambda akan mengecek jumlah argumen yang dioper.
deffoo(code)one,two=1,2code.call(one,two)endfoo(Proc.new{ |a,b,c| puts"a = #{a}, b = #{b}, c = #{c.class}"})# => a = 1, b = 2, c = NilClassfoo(lambda{ |a,b,c| puts"a = #{a}, b = #{b}, c = #{c.class}"})# => ArgumentError: wrong number of arguments (2 for 3)Untuk mem-pass suatu proc atau lambda sebagai argumen suatu method, variabel proc/lambda tersebut diberi prefix &
print_item=procdo |item|
putsitemend[1,2,3].each &print_itemObject merupakan root dari hierarki kelas di Ruby. Semua method dari kelas Object akan tersedia di seluruh kelas kecuali di-override secara eksplisit. Selengkapnya ada di http://www.ruby-doc.org/core/classes/Object.html
Metaprogramming merupakan pemrograman yang memanipulasi program lainnya atau bahkan dirinya sendiri, atau mengerjakan hal-hal yang biasanya dilakukan pada compile time, pada waktu runtime. Kemampuan suatu objek untuk memanipulasi dirinya sendiri ini sering disebut sebagai reflection.
Metaprogramming di ruby memanfaatkan sifat ruby yang sangat dinamis. Beberapa teknik yang sering digunakan dalam metaprogramming di ruby antara lain:
Salah satu bentuk metaprogramming adalah monkey patching, yaitu memodifikasi runtime code dari suatu bahasa yang dinamis tanpa mengubah source code aslinya.
Contoh yang sangat menarik dalam monkey patching di ruby adalah dengan melakukan overwrite kelas yang
sudah didefinisikan sebelumnya, termasuk kelas yang built-in (bawaan) ruby seperti Fixnum.
Kelas dalam ruby dapat dibuka dan didefinisikan ulang kapanpun kita mau. Dengan demikian kita dapat
dengan mudah mengubah behaviour dari suatu object sesuai keinginan kita.
Dibawah ini adalah contoh monkey patching yang sangat berbahaya. Di sini kita membuka kembali kelas Fixnum
yang merupakan kelas bagi angka integer bawaan ruby. Kemudian kita mendefinisikan ulang method + untuk
selalu me-return angka 42 kapanpun.
classFixnumdef +(x)42endend3 + 4# => 42Kita bahkan juga bisa meng-override semua objek dengan cara meng-override kelas Object yang merupakan
hirarki kelas tertinggi, sehingga semua objek akan terpengaruh.
Contoh berikut ini menambahkan atribut timestamp bagi semua object, sehingga setiap object akan menyimpan waktu ketika object tersebut diinisiasi.
classObjectattr_accessor:timestampendclassClassalias_method:old_new,:newdefnew(*args)result=old_new(*args)result.timestamp=Time.nowresultendendclassFooendFoo.new.timestampKetika kita mengirimkan pesan ke objek, objek akan mengeksekusi method pertama yang ditemukannya pada
method lookup path dengan nama yang sama persis dengan pesan. Jika tidak ditemukan,
ia akan melemparkan exception NoMethodError, kecuali kalau kita sudah menyediakan sebuah method bernama method_missing.
method_nissing dapat kita override sesuai dengan keinginan kita. Misalnya kita dapat meng-override method_missing
sehingga jika kita memanggil method yang tidak tersedia, object tersebut akan memberi kita peringatan.
classFoodefmethod_missing(m, *args, &block)puts"method #{m} is not defined. Please define it first."endendFoo.new.bar# => method bar is not defined. Please define it first.Dasar dari semua input/output di Ruby adalah kelas IO, di mana merepresentasikan stream input/output data dalam bentuk byte. Standard stream mencakup stdin (keyboard), stdout (display ke layar) dan stderr (error output). Parameter pertama konstruktor kelas IO adalah nomer file descriptor, sedangkan parameter keduanya merupakan mode I/O. Ada beberapa macam mode I/O, antara lain: r, r+, w, w+, a, a+, b
| Stream | File Descriptor |
|---|---|
| stdin | 0 |
| stdout | 1 |
| stderr | 2 |
ios=IO.new(1,"w")ios.puts"Hello IO"# => Hello IOios.fileno# => 1ios.to_i# => 1ios.closeDi Ruby, kita bisa memanipulasi file dan folder dengan menggunakan method-method dari kelas Dir dan File.
Buat dan hapus folder:
Dir.mkdir("/tmp/ruby_basic",777)dir=Dir.pwdputsdirDir.rmdir("/tmp/ruby_basic")Buat dan hapus file:
file=File.new("aaaa.txt","w")File.rename("aaaa.txt","bbbb.txt")File.delete("bbbb.txt")Pemrosesan file per baris pada Ruby:
file=File.open("Readme.md")ifFile::exists?("Readme.md")file.eachdo |line| print"#{file.lineno}. ",lineendunlessfile.closed?file.close