Kategori arşivi: Ruby (Ruby on Rails)

Ruby ve RoR..

Rails için jetty_rails güncellemesi

Merhabalar,

Bir önceki yazımızda rails için jruby kullanımından ve windows üzerinde rails uygulamalarının servis edilmesi hakkında bir yazı yazmıştık. Bu yazıda jetty_rails’in sürümünün biraz eski olduÄŸundan (son güncelleme tarihi 2009-07-08 20:28) bazı problemle karşılaÅŸtığımı yazmıştım.

Bu yazıda sizlere bu problemleri nasıl ortadan kaldıracağımızı anlatmak istiyorum.

1. Öncelikle jetty-rails’i standart gem yöntemleriyle yüklüyoruz.

jruby -S gem install jetty-rails

Rails için jetty_rails güncellemesi yazısına devam et

Rails için yazılım geliştirme ortamı

Merhabalar,

Ne zamandır arkadaşlarım rails için yazılım geliştirme ortamı sorup duruyorlar, aslında ortada çok fazla alternatif olduğu için kafa karışıklığına neden olabiliyor.

Son (bir windows sunucu da host etmek zorunda olduğumuz) projem de redcar + jruby 1.6.3 + rails 3.0.9 + mysql >5 (arabirim olarak mysql workbench) ortamında yazılım geliştirme gerçekleştirdim.

Neden redcar;

  • Netbeans Build-in debugger’ı code-complete özelliÄŸi ile tam bir editör ama 6.9.1’den sonra desteÄŸi yok.
  • Redcar’ın kısa yolları ve “snippet” lerine alışırsanız oldukça hızlı ve efektif ÅŸekilde uygulamanızı geliÅŸtirebilirsiniz.
  • DiÄŸerlerini denemeyin bile :)

Neden MRI deÄŸil de jruby kullandığımı soracak olursanız, cevabı yukarıdaki parantez içerisinde yazdığım küçük cümlecikte saklı. Evet malesef rails için windows üzerinde yüksek TPS deÄŸerlerine eriÅŸebilecek bir sistem kurmak oldukça zor ve problemli. Bu nedenle jruby ile java‘nın bu getirilerinden faydalanmak istedim.

JRuby’nin bu gücünü kullanmak içinde bazı çalışmalarım oldu. GlassFish, Tomcat :) hatta IIS üzerinde koÅŸturup, performans deÄŸerlerini inceledim. Tomcat ve IIS için pek olumlu konuÅŸamayacağım, belki de ayarlarını tam yapamadığım için olabilir ama GlassFish gerçekten iyi bir performans grafiÄŸi çizdi. GlassFish’in tek kötü yanı çok büyük ve gereksiz birçok bileÅŸen içermesi ama elbette bazı projelerin bu bileÅŸenlere ihtiyacı olabilir, bu durumda tercih edilebilecek bir sunum ortamı olabilir.

Benim tercihim ise jetty oldu. jetty_rails adlı bir eklenti ile işler kolaylaşıyor fakat ne yazık ki eklenti oldukça eski bir sürüme ait bu nedenle bazı ufak tefek düzeltmeler yapmamız gerekiyor. Lafı çok uzattık bu düzeltmeleri daha sonra sizlerle paylaşırım.

Son söz olarak, rails uygulamanızı yazarken aşağıdaki maddeleri göz önüne almanızı tavsiye ederim;

  • Rails uygulamanızı kendiniz host etmeyin.
  • Rails uygulamanızı gerçekten kendiniz host etmeyin.
  • Rails uygulamanızı Linux bir sunucuda host edin. Linux için zilyon tane baÅŸarılı alternatifi deneyebilirsiniz.
  • Rails uygulamanızı Windows sunucuda host etmeyin.
  • Rails uygulamanızı Windows sunucuda host etmeyin, gerçekten.
  • Rails uygulamanızı Windows üzerinde host etmek istiyorsanız, jruby uyumlu olmasına özen gösterin. Host etmek istediÄŸiniz zaman duruma göre glassFish veya jetty kullanabilirsiniz.

Kolay gelsin :)

Ruby ile Kyoto Cabinet – 5

Merhabalar,

Birkaç arkadaşım yazıları okuduktan sonra Kyoto Cabinet’in sorgu performansını merak etmiÅŸ. Bunun üzerine küçük bir çalışma ile sorgulama performanslarını sizlerle paylaÅŸmak isterim.

Hemen sonuçları yazmakta fayda görüyorum :)

MySQL üzerinden daha önceki yazılarımda yer alan konfigurasyon ile (engine: Innodb, primary key üzerinden sorgulama yapılıyor.) 100 thread ile 1.000.000 kayit 48.56 sn’de sorgulanmıştır.

KyotoCabinet üzerinden daha önceki yazılarımda yer alan konfigurasyon ile (engine: Hash, ek parametreler DB::OCREATE | DB::GCONCURRENT ve key üzerinden sorgulama yapılmıştır) 100 thread ile 1.000.000 kayit 4.54 sn’de sorgulanmıştır.

Şaka değil gerçek.
Ruby ile Kyoto Cabinet – 5 yazısına devam et

Ruby ile KyotoCabinet – 4

Merhabalar,

Bir KyotoCabinet yazısına daha hoÅŸgeldiniz. Bugün sizlerle MySql’in 100 thread üzerinden “insert” yetenekleri ile kyoto cabinet’inkileri birbirleriyle karşılaÅŸtıracağız. Peki bunu neden yapıyoruz, çünkü bir önceki yazımızda tek thread üzerinden kyoto cabinet üzerine veri yazma iÅŸlemi mysql’a göre ~10 kat daha hızlı olduÄŸunu gördük.

Bu durum, tüm transactional tablolarımızı kyoto cabinet’e taşımamıza neden olmasa bile, yazılım geliÅŸtirirken kullandığımız bir çok “log” tablolarını taşımamızın kapısını aralar diye düşünüyorum. Yazılım geliÅŸtirirken bu kayıtları için bir log tablosuna veya dosyaya yazarız. Fakat dosyaya attığımız kayıtları tekrar okumak veya istediÄŸimiz kayıda eriÅŸmek istediÄŸimizde problemlerle karşılaÅŸtığımız için genelde “log” tablolarını tercih ederiz. Ä°ÅŸte bu tercihlerimizde, eÄŸer bu testten de baÅŸarı ile geçerse, log iÅŸlemleri için (hatta belki daha fazlası için) mysql yerine kullanılabilir.

Veya tecrübe ile sabit, web sistemlerinin session yönetimi ve loglaması için kullanılabilir. Aklınıza bir soru gelebilir, çünkü session tablosunda sorgu atmak için kullandığımız tek alan SessionId’dir. Yani ID üzerinden yapacağımız tüm iÅŸlemlerde bu veri tabanı yapılarının klasik veri tabanı yapılarına göre çok daha hızlı olduÄŸunu unutmayalım.
Ruby ile KyotoCabinet – 4 yazısına devam et

Ruby ile KyotoCabinet – 3

Merhabalar,

Bir önceki yazımızda Ruby üzerinden KyotoCabinet’e 1.000.000 (1 milyon) veri giriÅŸini çok kısa bir sürede tamamlamıştık. Daha sonra içime bir kurt düştü, acaba mysql’de durum nasıldı? Yani aynı koÅŸullar altında mysql veri tabanına 1.000.000 kayıdı kaç sn içerisinde yazabilecektim?

Makinanın özelliklerini bir önceki yazımızda vermiştim.

Bu iÅŸlemin testi için öncelikle kendimize oldukça hızlı olduÄŸuna inandığım, KyotoCabinet’in Ruby arabiriminde olduÄŸu gibi C dili ile yazılmış MySQL/Ruby bir arabirim kütüphanesi buldum ve 2.8.2 versiyonunu kurdum. Bununla beraber MySQLClient versiyonunun 5.1.41 olduÄŸunu söylemeliyim.

Daha sonra key, value tutacağımız bir veri tabanı oluşturdum. Öncelikle MyISAM motorunu kullanan bir tablo oluşturdum ve testlerimi bu tablo üzerinde yaptım.

CREATE TABLE `kyoto_cabinet`.`simple_table` (
  `key` CHAR(12) UNICODE NOT NULL,
  `value` CHAR(12) UNICODE NOT NULL,
  PRIMARY KEY (`key`)
)
ENGINE = MyISAM
CHARACTER SET utf8 COLLATE utf8_turkish_ci;

Ruby ile KyotoCabinet – 3 yazısına devam et

Ruby ile KyotoCabinet – 2

Merhabalar,

Bir önceki yazımıza kaldığımız yerden devam ediyoruz. Bu sefer Kyoto Cabinet’in insert (kayıt ekleme) performansını inceleyeceÄŸiz.

Öncelikle bu bir performans çalışması olduğu için makinamın özelliklerini verelim;
– 2 x AMD Athlon x64 3800+
– 2 G Ram
– Ubuntu 10.04 LTS
– FileSystem ext4
– Ruby 1.8.7 (2010-01-10 patchlevel 249)
– KyotoCabinet 1.2.2
– KyotoCabinet ruby kütüphanesi 1.14

En azından bu özelliklerle yapılan bir test sizleri kodu kendi makinanıza alıp denemeniz için cezbedebilir. Sonuçta bir önceki yazıdan kurulum işlemleri uygulayıp sonrasında aşağıda belirteceğim kod parçasını uygulayacaksınız. Sonuçları benimle paylaşabilirsiniz.

require 'kyotocabinet'
include KyotoCabinet

DB::process('subscribers.kch') { |db|
  # resmi sitede yer alan örneklerde set_encoding olarak gösteriliyor fakat aslında tune_encoding olmalı.
  db.tune_encoding('utf-8')

  # Telco sektöründe çalıştığımız için, numara bir MSISDN'e benziyor degil mi :)
  start_number = 905000000000

  start_time = Time.now
  puts "sira;gecen_sure;toplam_gecen_sure"
  100.times { |index|
    first_loop_start_time = Time.now
    10000.times {
      start_number += 1

      # Evet alt satirda KyotoCabinet üzerinde "Insert" islemi yapıyoruz.
      db[start_number] = start_number
    }
    loop_elapsed = Time.now.to_f - first_loop_start_time.to_f
    total_elapsed = Time.now.to_f - start_time.to_f
    puts index.to_s + ";" + loop_elapsed.to_s + ";" + total_elapsed.to_s
  }

  puts "1.000.000 kayit eklenmistir. Toplam süre: " + (Time.now.to_f - start_time.to_f).to_s
}

ruby kyoto_test01.rb > output.csv ile çalıştırırsanız çıktı dosyasını bir office programında açar ve performans analizinizi daha hızlı yapabilirsiniz. Unutmadan uygulamayı Netbeans veya Scite gibi editörlerin üzerinden çalıştırmayın toplamda benim makinamda 3 sn gibi fazlalıklara neden oldular.

İşte benim makinam üzerindeki sonuçların bir özeti;
Ruby ile KyotoCabinet – 2 yazısına devam et

Ruby ile KyotoCabinet

Merhabalar,

Uzun bir aradan sonra kendimde tekrar yazı yazabilecek enerjiyi bulabildim. Nasıl mı? Aslında ben de bilmiyorum. Yeni doğan kızım Nil (evet, artık benim bir kızım var, kendisi daha 22 günlük :) ) nedeniyle evde çok neşeli bir telaşımız var ama yine de bir cumartesi akşamı ben bu yazıyı yazabiliyorum.

Ayrıca bugünün cumartesi olması ve ÅŸu saatlerin de akÅŸam olması ve artık bir kızımın olması nedeniyle ilk kez akÅŸam gezintileri için “benden geçmiÅŸ” demek zorunda hissettim kendimi. :)

Neyse konumuza dönelim, konumuz Kyoto Cabinet‘in ruby’de kullanılması olacak. Öncelikle

Kyoto Cabinet nedir;
Aslında bilenler var ise Kyoto Cabinet, Tokyo Cabinet gibi, Memcache gibi yüksek performanslı non-relational (türkçe çevirisi için ‘iliÅŸkisiz’ den daha iyi fikri olan söylesin) veri tabanı sistemidir. Limitleri oldukça yüksektir ve performans konusunda gerçekten dudaklarınızıda uçuklatabilir. Kesinlikle oracle, mysql veya postgre gibi relational (iliÅŸkili) veri tabanı sistemleri ile kıyaslanmamadır. Bu elma ile armut kıyaslanması gibi olur.

Kyoto Cabinet aslında “Key” ve “Value” ikilisini bir veri tabanında (bir dosyada) tutmak ve yönetmek için yapılandırılmış bir kütüphanedir. Bir dosya üzerinde yer alan Key ve Value alanları farklı uzunluklara sahip ve farklı tiplere sahip olabilir. Ayrıca bu kayıtları B-Tree veya Hash olarak tutabilmektedir.

Peki hemen aklınıza bir soru gelebilir. Nedir bu B-Tree ve Hash denen arkadaşlar? Sayfaları ziyaret edin, kullanın öğnenin diyorum başka da birşey demiyorum. Yaptığınız işe göre, kullanmanız gereken algoritmaya göre seçeceğiniz yapı yazılım performasını etkileyen en büyük unsur olacaktır. Ve malesef bunların bir tanesi hepsini dövmüyor/dövemiyor.

Hadi Kyoto Cabinet kuralım
0- Linux’da çalışıyor. Benim kullandığım ubuntu üzerinden kurulumu anlatacağım.
Ruby ile KyotoCabinet yazısına devam et

Diziler (Uzmanlar için)

Merhabalar,

Uzun süredir herhangi bir yazı yazmıyordum, arkadaÅŸlar arasında konuÅŸurken “neden yazmıyorsun” gibi sorulara maruz kaldım, “eee dedim yazacak pek bir ÅŸey kalmadıki, ben ruby veya yazılım ile ilgili konularda yazıyorum” dedim. “eÄŸer herhangi bir konuda istek gelir ise o konuda yazarım ama, ÅŸimdilik böyle bir konu yok” dedim. Dedim de hemen cevabı yapıştırdılar suratımın orta yerine.. “Ruby dizileri gerçekten basit tutmuÅŸ, herhalde hız için.. Lisp veya fonksiyonel programlama dileri kadar esnek deÄŸil” dediler.. “Eneee” dedim :) bana yazı yazacak konu çıktı.

Şimdi öncelikle biraz konu ile ilgili kendimizi motive edelim; Neden dizi işlemleri bu kadar önemli ? Ya da diğer işlerden farkı ne olabilir ki ?

Öncelikle bir konuya açıklık getirmek gerekir, günümüzde yazılan programlar içerisinde pek çok durumda dinamik veya durağan veri kümeleri ile işlemler yapılıyor. Bu işlemler, yazdığımız programlar içerisinde performansı etkileyen en önemli etken olarak karşımıza çıkıyor. Ve günümüzdeki daha fazla veri üzerinden daha doğru bilgi edinme anlayışı nedeni ile dizilerin boyutları gün geçtikce artıyor ve üzerlerinde yapılan işlemler gün geçtik fazlalaşıyor, bu performans etkeni daha da önemli hale geliyor. Yanlış anlaşılma olmasın, burada bahsettiğim performans Şişirme Veri Girişi adlı yazıda bahsettiğim veri yoğunluğunun artması ile beraber ortaya çıkan performans kötüleşmesi.

Diziler üzerinde yapılacak işlemlerde öncelikle iki ana başlıkta değerlendirilmelidir;
1- Kolay kullanım,
2- En iyi algoritmanın kullanılması.

Ä°kinci maddenin neden gerekli olduÄŸu konusunda fazla söze gerek yok ama, birinci maddenin neden gerekli olduÄŸu konusunda aklınızda sorular olabilir, bu soruları ortadan kaldırmak için ÅŸu ÅŸekilde bir açıklama yapabilirim. “Diziler üzerinde yaptığınız optimizasyonlar, algoritma seçimleri veya memory optimizasyonları” gerçekten zor ve uygulanması oldukça tartışmalı olabilir. ÖrneÄŸin google’ın java dili için çıkardığı “Google Collections Library” buna örnek olarak gösterilebilir. Kolay kullanım ve entegrasyon yazılımcılar tarafından her zaman tercih edilir.

Peki Ruby tüm bunların karşısında bize güzel silahlar veriyor. Aslında tüm Ruby iÅŸlemlerinde olduÄŸu gibi performans basitliÄŸin gerisinde kalmış, yüzlerce kez söylediÄŸim gibi “yazılımın çalışma hızı sonsuza giderken, geliÅŸtirme süresi sıfıra gitmeli” felsefesine ters deÄŸil.

data = [1,2,4,8,12,5,7,3,0,13,10,11,3]

# For..In
data.each { |x| puts "x=#{x}" }

# data içerisindeki tüm elemanları tek tek verilen 
# blok içerisindeki işlemden geçirir ve sonuçlardan yeni bir dizi üretir.
puts data.collect { |x| x + x }

# For..In :) ile indexleri verir.. :) pek çok programlama dilinde 
# karşılığı bulunmaz.
data.each_with_index { |x, index| puts "#{index}. eleman = #{x}" }

# 5'den büyük ilk kayıdı bulur.
puts data.detect { |x| x > 5 }

# 5'den küçük olanları true_data değişkenine, 
# diÄŸerlerini false_data deÄŸiÅŸkenine dizi olarak atar.
true_data, false_data = data.partition { |x| x < 5 }
puts true_data
puts false_data

# 5'den küçük olanları diziden çıkartır ve geri döner.
puts data.reject { |x| x < 5 }

# Varsayılan sıralama işlemi
puts data.sort

# Belirlenmiş kritere göre sıralama işlemi (string olarak sıralama)
puts data.sort_by { |x| x.to_s }
# veya
puts data.sort_by { |x| (x+5)/x }

Kolay gelsin.. :)

Regular Expression

Merhabalar,

Bugün yeni gelen bilgisayar masamın ÅŸerefine bir yazı yazmak istiyordum ama öyle boÅŸu boÅŸuna yazı yazamayacağım için arada sizlere regular expression’dan bahsetmek istiyorum :)

Öncelikle sizlerin de yazılım hayatınıza baÅŸlayalı 5~10 yılı geçtiyse artık etraf koddan geçilmez hale gelir. Her yerde baÅŸka kodlar, hepsinize siz yazmışsınızdır ama.. “kardeÅŸim ne yazmışım yaa, bu kadar da olmaz ki”.. dersiniz. Daha sonrasında kendinizi birÅŸeyler araken ve en önemlisi bulumazken bulacaksınız.. “ahh nereye koymuÅŸtum bunu salak ÅŸeyi..” dersiniz.. tekrar dersiniz.. ama bunu söylemenin bir etkisi yoktur, gene bulamazsınız.. gene bulamazsınız.

Ya da size bir iÅŸ verirler. RegEx (Regular Expression) kullanmanız gerekir.. Gerekir gerekir gerekmez demeyin. Örnek vermek gerekir ise, geçen gün Zodazone Türkiye’de belirli bir tabloda yer alan açıklama bilgilerini deÄŸiÅŸtirilmesi istendi üstlerden bir yerlerden (ne biliyim muhasebeden falan iÅŸte..).

Bize bir ofis dökümanı içerisinde tekil kod bilgisini ve yanında yeni açıklamasını gönderdiler.. Onlar oturmuÅŸ kasmış… hatta uÄŸraÅŸmış sabahlara kadar 150 civarındaki açıklamayı kafa patlatmışlar, düşünmüşler, taşınmışlar.. ve deÄŸiÅŸtirmiÅŸler.. Tabii ne zennetiniz sadece bunun için maaÅŸ alan adamlar bile mevcut.

Ehh tabii bu Tankut kardeÅŸiniz oturup, 150 tane açıklama alanını tek tek yapacak hali yok. Deli miyim ben :) söz meclisten dışarı efenim :) Neyse ÅŸimdi bu dökümanı gönderdiler ya içerisinde sadece açıklama bilgisi bulunmuyor ki, kim bilir hangi düzenle yazdılar bu dökümanı diye bir düşünün bakalım.. Regular Expression olmadan adım atamazsın adım….

Neyse öncelikle güzel güzel açıklayalım bu RegEx nedir, ne değildir ?
RegEx, karakter yığınları içerisinde özel belirtilen karakter veya karakter kümelerini bulmak, diğerlerinden ayırmak için kullanılan oldukça gelişmiş bir kütüphanedir. Kullanımı biraz zordur, hemen kısa sürede alışmanız zor olabilir.

Öncelikle RegEx tanımlarını ve anahtar kelimelerini tanıyalım; (Kitap yazmıyoruz burada ona göre.. tüm özelliklerini yazmıyorum sadece çok kullandıklarımı)

Anahtar kelimeler:
^ : Satır başını ifade eder.
\n : Enter karakteri için kullanılır.
\t : Tab karakteri için kullanılır
[…] : Örnek: [aeıioöuü] sadece sesli harfleri bulunur. ‘[]’ karakterleri içerisinde yer alan herhangi bir karaktere uyanları getirir.
[^…] : Örnek: [^aeıioöuü] sadece sessiz harfleri bulunur. ‘[^]’ karakterleri içerisinde yer alan herhangi bir karaktere uymayanları getirir.
. : Yeni satır (\n) karakteri hariç herhangi bir karakteri ifade eder. Tek karakteri
\w : Herhangi bir alfanumeric veya numeric karakteri iÅŸaret eder. a..z, A..Z, 0..9
\W : \w’nin tersidir.
\d : \d herhangi numeric karakter.
\D : \d’nin tersi.
\ : bir sonraki karakter özel bir anlam ifade ediyorsa, bu özelliği iptal eder.

Destekleyiciler
? : Bir önceki karakterden bir tane var ise bulur.
+ : Bir önceki karakterden bir ve birden fazla var ise.
* : Bir önceki karakterden 0 ve birden fazla var ise.
{n} : Bir önceki karakterden n adet olanları bulur.
(…) : Gruplama iÅŸlemi yapar. ‘()’ içerisine yazılanlar grup olarak deÄŸerlendirilir.
| : ‘OR’ iÅŸlemi için kullanılır, 2 farklı RegEx bu ÅŸekilde baÄŸlanabilir.

Opsiyonlar:
i : Büyük küçük harfe duyarlı olmaz.
m : Karakter katarını birden çok satırmış gibi düşünür.
s : Karakter katarını tek satırmış gibi düşünür.

Kolay gelsin.. :)

Hpricot Örneği

Merhabalar,

GeçmiÅŸ zaman olurki bir proje için internette yayınlanan videoların kaç kez görüntülendiÄŸini öğrenmek isteyen arkadaÅŸlar ile tanıştım, çok ısrar ettiler yaptım. Bazı siteler için süper basit ve hızlı olurken bazıları için uzun sürdü ama 5 site için görüntüleme bilgilerini 2 saat gibi uzun bir sürede yapmayı baÅŸardım. Öff bee çok uzun sürmüş harbiden… ÅŸimdi yazınca daha da uzun geldi… aman aman bir daha yapmam valla… bu nedenle sizler de tekrar tekrar uÄŸraÅŸmayın diye bu Tankut kulunuz bu yazıyı yazıyor. Sırf sizler için, reklamları tıklamanız için deÄŸil, adımı aÄŸzınızda sakız yapmanız için deÄŸil.. sadece siz uÄŸraÅŸmayın diye.. heyttt bee hizmet etmeye geldik diye siyasi bir yaklaşım içerisinde bulunan ve hiç birÅŸey yapmayanlar utansın..

Öfff öff gene gereksiz yazdım işte örnekler :)

Öncelikle bulduÄŸumuz gösterim sayılarını (view count) html veya “,” gibi karakterler ayırmak için bir methoda ihtiyacımız var. Ä°ÅŸte ‘remove_char’ methodu tam bu noktada isteklerimizi karşılıyor.

def remove_char(number)
  ret = ''
  number.to_s.split(//).each do |char|
    ret += char if char.to_i.to_s == char
  end
  ret
end

Öncelik google kardeÅŸimizin olsun, google kardeÅŸimiz video url’i aslında frame’lerden oluÅŸuyor. Ve gösterim sayısının (video view count) bulunduÄŸu frame’i üstün araÅŸtırmalarımın sonucunda buldum… :) url’de ‘videoplay’ yerine ‘videohosted’ yazıyorsunuz oldu bitti maÅŸallah :).

require 'open-uri'
require 'hipricot'

# Sassy Girl (Chun-Hyang) Episode 5
video_url = 'http://video.google.com/videoplay?docid=1197987351381288347'
google_video = Hpricot(open(video_url.gsub('videoplay','videohosted')))
temp = google_video.search("//table[@id='statsshowmore']")
google_video_view = Hpricot(temp.innerHTML).search("//td")
view_count = remove_char(google_video_view[0]).to_i
puts view_count

Sonraki örneÄŸimiz myspace’den olsun…

# Internet People!
require 'open-uri'
require 'hipricot'

video_url = 'http://vids.myspace.com/index.cfm?fuseaction=vids.individual&VideoID=2057681175'
myspace_video = Hpricot(open(video_url))
temp = myspace_video.search("//div[@class='userinfo']")
myspace_video_view = Hpricot(temp.innerHTML).search("//span")
view_count = remove_char(myspace_video_view[2]).to_i
puts view_count

Vur patlasın çal yahoo’dan gelsin örnek..!

# Eastern Promises
require 'open-uri'
require 'hipricot'

video_url = 'http://video.yahoo.com/video/play?vid=1145798&fr=&cache=1'
yahoo_video = Hpricot(open(video_site.url))
temp = yahoo_video.search("//div[@class='vd']")
yahoo_video_view = Hpricot(temp.innerHTML).search("//span[@class='bold']").inner_text
view_count = remove_char(yahoo_video_view).to_i
puts view_count

En son youtube kardeşe bakalım; ama bir saniye youtube kardeşle uğraşmaya gerek yok.. :)
“gem install youtube” yazın evinize gelsin :)

require 'youtube'

Kolay gelsin..

** Düzeltme kodlar muhtemelen artık çalışmıyordur. Sadece örnek olması açısından değerlendirin lütfen.

Dosya İşlemleri (Karşılaştırma)

Merhabalar,

Öncelikle karşılaştırma derken, nasıl bir karşılaştırma yapacağımızı anlatmalıyım. Performans işlemleri karşılaştırma kriterlerim içerisinde bulunmuyor, bundan hiç bahsetmeyeceğim. Ama kodun okunabilirliği, hızlı yazılması, hatalara karşı ne kadar duyarlı olduğu ve tabii ki en önemlisi tekrar kullanabilirliği.

Aslında bu son nokta yani ‘tekrar kullanılabilirlik’ baÅŸlı başına bir yazı konusu ama buna ÅŸimdilik pek deÄŸinmeyeceÄŸim. BaÅŸlıkta yazdığı gibi dosya iÅŸlemlerini karşılaÅŸtıracağım.

Arşılaştırmayı sadece VBScript, JScript ve Ruby arasında yapacağım, neden mi ? hali hazırda yapmıştım da ondan.. bu yazıyı yazacağım diye oturup program yazmadım. Önce programları yazdım, sonra yazıyı yazmak aklıma geldi. Bu nedenle neden diye sormayın. :)

Ama belki daha sonraki zamanlarda Java ve C# versiyonlarının karşılaştırmalarını da eklerim.

Öncelikle sizlere problemden bahsedeyim.

Belirli bir server üzerinde ps ve txt (post script ve text) dosyaları online bir uygulama tarafından oluÅŸturuluyor, daha sonrasında online uygulama üzerinden kullanıcı bu dosyaları temizlemeyi unutuyor ve dosya sisteminin ÅŸiÅŸmesi ile beraber performans problemleri ortaya çıkıyor. Bu nedenle dosyaların gün bazında ömürlerinin olmasına ve ömrünü doldurmuÅŸ olan dosyalarında sistem tarafından silinmesine, silme iÅŸlemi esnasında log almasını ve bu loglarında aynı ömür kuralına tabii olmasını istiyoruz… iÅŸte bu program bu iÅŸi yapacak.. günde bir kez çalışacak ve bu iÅŸlemi yapacak. Microsoft Windows sistemde çalışmasını istediÄŸimiz için VBScript ve JScript’de (JavaScript’in bire bir aynı klonu) ve platform bağımsız olan Ruby’de yazıldı. Ä°ÅŸte Ruby örneÄŸi;
Dosya Ä°ÅŸlemleri (KarşılaÅŸtırma) yazısına devam et

Ruby’de MesajlaÅŸma ve Methodlar

Merhabalar,

Bu yazımı aslında takip ettiÄŸim bir kaç sitede yayınlanan blogları gördükten sonra yazma gereÄŸi duydum. BahsettiÄŸim bloglarda yer alan yazılar aslında basit anlamda Ruby’nin temel özelliklerinden bahsediyorlarda fakat bu yazılara çok farklı tepkiler geldi. Bu tepkiler içerisinde çok ÅŸaşıranlar.. hadi ya ben bunu bilmiyordum diyenler.. yaa demek böyle birÅŸey varmış ama bu kötü vs..vs.. Ben de bu yorumları inceledikten sonra bu yazıyı yazmaya karar verdim.

Aslında konumuz Ruby’de sınıfların yapısı, özellikleri ile Ruby’nin sınıfları, kütüphaneleri ve bizim Component dediÄŸimiz ÅŸeyleri nasıl gördüğüdür.

Öncelikle OO (Object Oriented) tüm dillerde olduÄŸu gibi Ruby’nin sınıf tanımı Java’nın veya C#’ın sınıf tanımı ile aynıdır. Peki o zaman farklılık nerede :) ayrıntılarda.. ÅŸeytanın gizli olduÄŸu yerde :)

public class HelloWorld extends ExampleSupport {

    private String execute() throws Exception {
        setMessage(getText(MESSAGE));
        return SUCCESS;
    }
}

Yukarıda belirtilen örnekte olduÄŸu gibi execute isimli methodumuz private tanımlanmış, yani sadece HelloWorld sınıfı içerisinden kullanılabilir. Neden çünkü private…

peki bir de bunun benzerini Ruby’de gerçekleÅŸtirelim;

class HelloWorld < ActiveSupport
    private
    def execute
        SetMessage(GetText(MESSAGE))
        return SUCCESS;
    end
end

Yukarıdaki iki örnek birbirlerinin aynısı. Ama diyorum ya şeytan bu ayrıntılarda gizli elbetteki.. :) Tahmin ettiğiniz gibi Java dilinde herhangi bir esneklik yok tabiki.. private tanımladın.. private.. yok öyle yanar döner method tanımlama olayları...

Peki ya Ruby'de private olarak tanımlanmış bir methodu public yapabilirmiyiz.. elbette yaparsınız; private yerine public yazarsınız.. taaa taa oldu.. :) Diğer bir yöntem;

Parçalı sınıf (Partial Class) yönetimi ile yapılabilir.

class HelloWorld
    public
    def execute_public
        execute
    end
end

peki başka nasıl olur bu iş.. mesajlaşma ile olur.. şöyleki aslında bir methodu çağırmanın tek yöntemi o methodu direkt olarak çağırmak değildir. Ayrıca Reflection dediğimiz kavram ile de çağrılabilir (Java dünyasında da oldukça kullanılır).

helloWorld = HelloWorld.new
helloWorld.execute # Hata üretir.. execute halen private bir methodtur...
helloWorld.execute_public # Çalışır :)
helloWorld.send("execute") # Çalışır.. problem çıkarmaz.. Sınıfa execute adlı bir method çalıştırmasını söyler.
helloWorld.instance_eval("execute") # Çalışır.. problem çıkarmaz..

Görüldüğü gibi.. yazılımcıdır tüm kodların hakimi.. yoktur programlama dilinin mecburiyetleri.. :P

En son olarak benim tercih ettiğim yöntem; tabii private yerine public yazmak yerine.. :)

class HelloWorld
    public :execute
end

Yukarıda belirtilen bu yordam ile.. execute methodu artık public olmuştur.. hayırlı uğurlu olsun.. :D

Kolay gelsin..!

Ruby Değişken Özellikleri

Merhabalar,

Öncelikle bu kadar uzun bir süre yazı yazmak ilginç oluyor. Bir aydan fazla bir süredir, nokta koymadığım bu günlüğe birşeyler yazmak biraz yabancı geldi açıkcası.

Bu yazıyı yazmam için beni birazcıkta olsa gaza getiren sevgili Mehmet DURAN kardeşime buradan teşekkür etmek isterim.. şak şakk şakk şakk.. javaayyyyy diyorum sana Mehmet.. :)

Öncelikle bu yazıdaki konumuzu belirteyim; Ruby programlama dilinde değişkenlerin nasıl tanımlandığı ve değişkenler üzerinde tip dönüşümlerinin nasıl olduğu.

Ruby’de deÄŸiÅŸkenler tanımlanırken herhangi bir ÅŸekilde tip belirtmenize gerek yoktur. Ä°sterseniz Java veya C#’da yaptığınız gibi yapabilirsiniz ama o zaman biraz ayıp olur.. yuhananırsınız.. ohaa artık diyenler olabilir. Şöyledir yani;

intValue = 5
strValue = 'Hobaaa'
arrValue = []
hashValue = {}
regValue = \.*\
classValue = MyClass.new

Öncelikle programlama dillerinde değişken tiplerinin dönüşümü ve bu tiplerin ele alınmasını iki soru altında toplanabiliriz; Bu sorular
1. Tipler arasındaki dönüşüm nasıl gerçekleşir?
2. Değişken üzerinde işlem yaparken tip önemlimidir?

Öncelikle 1. soruyu ele alalım; “1. Tipler arasındaki dönüşüm nasıl gerçekleÅŸir?”
El cevap: EÄŸer deÄŸiÅŸkeninizi bir tipten öteki tipe hödöö hödöö diye gönderiyorsanız, kullandığınız dil dinamik tip dönüşümüne sahiptir demektir. EÄŸer hödö hödöö diye deÄŸil de, daha efendi bir ÅŸekilde (örnek: ‘String.valueOf(55)’) yapıyorsanız duraÄŸan tip dönüşümüne sahipsiniz demektir. DeÄŸiÅŸkenlerinizi bir tipten öteki tipe deÄŸiÅŸtiremiyorsanız, ohaaa sizin o kullandığınız ÅŸey programa dili deÄŸil çin iÅŸkencesi demektir.

Programlama dillerine göre dinamik ve durağan tip dönüşümüne sahip olan diller;
Dinamik: Ruby, Python..vb.
DuraÄŸan: Java(yyyy), C#….vb.

Ä°kinci soruyu ele alırsak; “2. DeÄŸiÅŸken üzerinde iÅŸlem yaparken tip önemlimidir?”
El cevap: EÄŸer siz bir karakter ile sayiyi toplamak isterseniz veya benim bir deÄŸerim var ama inan ben bile bilmiyorum ne olduÄŸunu öyle yanar dönerli birÅŸey iÅŸte.. (Basic’den Variant, C’den void) diyebiliyor iseniz, sizin için deÄŸiÅŸkenin tipi pekde önemli deÄŸildir. Yani deÄŸiÅŸkenler ile deÄŸiÅŸken tipleri arasındaki baÄŸlantı ‘zayıf’tır. Her deÄŸiÅŸkenin veya her iÅŸlemin tipi olmasına gerek yoktur, diyebilirsiniz. Ama dersenizki ‘hadeee canım, tipsiz tipsiz deÄŸiÅŸkenmi olur, tipli adamın tipsiz deÄŸiÅŸkeni olmaz’ derseniz, tüm deÄŸiÅŸkenleriniz ile deÄŸiÅŸken tipleri arasında ‘güçlü’ bir baÄŸlantınız var demektir.

Güçlü: Ruby, Java(yyyy), C#, C++…vb.
Zayıf: C, Basic, Java(yyy)Script….vb.

Peki Ruby’de bunlar nasıl oluyor da oluryor diyeceksiniz ÅŸimdi; Ä°ÅŸte böyle oluyor..;

intValue = 5
puts 5 + intValue # problem yok.
puts "5" + intValue # büüürrrstt nereye biraderr..
puts "5" * "5" # bürrsttt yok daha neler..
# bir string(a) ile numarayı(b) çarptığınızda, ruby sizin a'yi b kez tekrarlamak istediğinizi zanneder.
puts "5" * intValue # Olur, bunun ruby'de karşılığı vardır.

Kolay gelsin..!

JRuby 1.0 RC3

Merhabalar arkadaÅŸlar,

Küçük bir yazı olacak, sadece sizlere JRuby’nin 1.0 Release Candidate 3 sürümünü duyurmak için bu yazıyı yazıyorum. Evet doÄŸru duydunuz, JRuby takımı Microsoft’tan daha hızlı davranarak (yarış halen bitmedi, gerçi ortada bir yarış var mı onu da bilmiyorum ama :) ) RC3’de olsa 1.0 sürümünü dünyaya *nihayet* duyurdu.

Åžimdi aklınızda soru iÅŸaretleri olabilir, Hemen sizlere JRuby’nin ne olduÄŸunu anlatmaya çalışayım. Aslında sizler normal Ruby uygulamalarınızı yazıyorsunuz, çalıştırıyorsunuz..vs..vs. Fakat sonra canınız sıkılıyor, neden sıkılıyor bilmiyorum ama birden Ruby’de yazdığınız kodların Ruby’nin doÄŸal ortamında deÄŸil de, Java Virtual Machine (JVM) üzerinde çalışmasını istiyorsunuz, nedenleriz ÅŸunlar olabilir;
– Performans amaçlı olabilir (bu konu tartışılır)
– Ruby’nin çalışmadığı fakat java’nın çalıştığı bir ortamda çalıştırmak için (Hangi ortam o ?? belki vardır, bilen varsa yazsın…)
– Müşterinizi ‘ben programı Java’da yazdım’ diye kandırmak için :)

galiba en geçerli neden bu sonuncusu :).

Ama sonuçta güzel, hoÅŸ ve desteklenmesi gereken bir olay. Ruby dili çok güzel ve akıcı bir yapıya sahip neden JVM’yi kullanmak istiyenler bu güzel dili kullanmaktan mahrum kalsınlar ki.. ciddiyim, espiri falan yapmıyorum, tamamiyle destekliyorum.

Rails kullanıcılarına önemli bir not, RoR altyapısı tamamiyle Ruby’de yazıldığı için JRuby yoluyla JVM üzerinde de dolayısı ile Java Application Server’lar üzerinde çalışabilir hale gelmiÅŸtir. Özellikle saÄŸlam veri tabanı özelliklerini kullanan uygulamalarda bu sayede hız artışı saÄŸlanabilir. (Henüz 1.0 RC3’ü inceleyemedim ama bazı kısıtlardan bahsediliyor fakat kesin bir ÅŸey söyleyemiyorum.)

Kolay gelsin…

Ruby ile Struct

Merhaba arkadaÅŸlar,

Bugünkü yazımızda Struct ve OpenStruct yapılarından bahsedeceÄŸiz. “Bu yapılara neden ihtiyacımız var ?”, “Var olan ‘class’ yapısı veya bu iÅŸlemlere benzer olan ‘Array’ ve ‘Hash’ yapılarını neden kullanmıyoruz ?”, “Bu kadar fazla öğrenmemiz gereken sınıf, yapı ve iÅŸlev varken neden bir de başımıza bu ikisi çıktı ?”, ve son olarak “Ne iÅŸimiz var kardeÅŸim Struct ile falan, bunlar boÅŸ iÅŸ.. ne yapacan öğrenip de..!?” gibi soruları cevaplamak gerekir. Ama tüm bu sorulardan önce ben neden bu yazıyı yazıyorum onu anlatmalıyım sanırım. Bu yazıyı bu linkte yer alan bir yazıyı gördükten sonra yazmaya karar verdim. Bu yazıda blog sahibi arkadaÅŸ Ruby on Rails’de ActionMailler kullanımı sırasında kullanmış, çok da güzel kullanmış. Ben de kendi kendime ‘Ben de bunu bizimkilerle paylaÅŸayım’ dedim. Ä°yi ettim di mi ? ettim ettim.. :)

Hatta ve hatta çok da güzel bir snippet’da mevcut. Bir göz atmanızı tavsiye ederim.

‘Struct’ ruby içerisinde yer alan ‘Class’ benzeri bir yapı, aslında Class’dan türemiÅŸ farklı bir yapı. Şöyleki normalde yeni bir ‘class’ yaratmak istediÄŸimiz de

class YeniSinif
attr_reader ...
attr_writer ...
attr_accessor ...

def ...
end

...
end

ÅŸeklinde ‘YeniSinif’ı yaratır ve bu sınıftan nesneler üretmeye baÅŸlayabiliriz. Struct, sadece veri taşımak için tasarlandığı için ÅŸu ÅŸekilde bir tanımlamaya ihtiyaç duyar;

# Temel Struct tanımı...
Adres = Struct.new(:posta_kodu, :sehir, :ilce, :semt, :mahalle, :apt_no, :apt_isim, :daire)

anlaşılacağı üzere, herhangi bir ÅŸekilde eriÅŸim belirleyicisi tanımlanamaz (private, protected, public gibi) tüm üyeler public’dir. Önemle belirtmem gerekirki, bu yeni oluÅŸturduÄŸum ‘Adres’ bir nesne deÄŸildir, bir sınıftır yani yeni bir türdür(type). Peki biz neden ruby içerisinde yeni bir tür(type) yaratmak istedik ? Örnekten de anlaşılacağı gibi, normal hayatta adres bilgisinde posta kodu, ÅŸehir, ilçe…vb bilgiler birbirlerinden ayrılamazlar ve mantıksal anlamda da bir birliktelikleri vardır. Elbette kullanmazsak programlarımızda çok büyük problemler çıkmaz ama bazı durumlarda bize çok büyük kolaylıklar saÄŸlayabilir; örnek vermek gerekir ise; Struct kullanmadan adres yapısının kopyalanması;

yeni_posta_kodu = posta_kodu
yeni_sehir = sehir
yeni_ilce = ilce
yeni_semt = semt
...
...

peki Adres diye bir tür kullansaydık ve işlemleri bu tür üzerinden yürütseydik;

yeni_adres = adres.clone # Bu kadar.. :)

ÅŸeklinde küçücük bir kod parçası ile bu iÅŸlemi yapabilirdik. Peki hemen aklınıza gelebilir, zaten sınıf(class) yapısı mevcut ben struct yerine class kullanamazmıyım ? Elbette kullanabilirsin, class, struct’ın yapabileceÄŸi tüm özelliklere sahip temel ve en genel yapıdır. Struct sadece verileri tutmak için yapılmış ve bu iÅŸ üzerine yönelmiÅŸ class’ın alt sınıfıdır. Yukarıda da bahsettiÄŸim snippet incelenecek olursa, bu konu daha rahat anlaşılır diye tahmin ediyorum.

Peki “Struct sadece verileri tutmak için yapılmış ve bu iÅŸ üzerine yönelmiÅŸ class’ın alt sınıfıdır” dedik, bu veri tutma iÅŸinde bizlere hangi özellikleri vermektedir. Struct, class’lardan farklı olarak bizlere bir Array veya Hash nesnesine eriÅŸir gibi içerisinde yer alan özelliklere eriÅŸimimizi saÄŸlayabilir. Şöyleki;

adres = Adres.new()
# veya
# adres = Adres.new(34300, "Ä°stanbul", "Fatih", "CerrahpaÅŸa", "ZZZZ ZZZ ZZZZ ZZ", 1, "Gonca", 18)
adres.posta_kodu = 34300
adres.sehir = "Ä°stanbul"
puts adres[:posta_kodu] # 34300
puts adres["sehir"] # Ä°stanbul
puts adres[1] # Ä°stanbul
puts adres.members # üyelerin isimlerini verir.
puts adres.values # üyelerin değerlerini verir.

adres.each_pair do |key,value| 
	puts key.to_s + ":" + value.to_s
end

Bir sonraki yazımda OpenStruct’u anlatmaya çalışacağım… :)

Kolay gelsin :)