Camping Tutorial

Başlangıç

Yeni bir text dosya açın ve nuts.rb adını verin. İçin de şunu yazın:

1
Camping.goes :Nuts

Kaydedin , sonra komut satırında şunu girin:

1
$ camping nuts.rb

Şuna benzer bir mesaj almalısınız:

1
** Camping running on 0.0.0.0:3301

Bunun anlamı, Camping server şimdi makinanızın 3301 portunda çalışmaya başladı. Tarayıcınızı açın ve http://localhost:3301/ adresine gidin.

camping_1.png

Burada bir hata yok. Camping server çalışıyor ama size ne göstereceğini bilmiyor. Öyleyse kendisine öğretelim.


Merhaba Saat

Peki, Camping kurulu ve çalışıyor. Çalışır durumda tutun, Camping server çalışırken dosyalarda düzenleme yapabilirsiniz, otomatik olarak yüklenecektir. Server'ı durdurmak isterseniz Control-C basın.
Haydi birşeyler gösterelim, nuts.rb dosyası alt kısmına şunu ekleyin :

1
2
3
4
5
6
7
8
9
Camping.goes :Nuts

module Nuts::Controllers
class Index < R '/'
def get
Time.now.to_s
end
end
end

Dosyayı saklayın ve tarayıcı penceresini tazeleyin. Tarayıcınız zamanı gösterecektir, şöyle bişey :

camping_2.png

 


Görseli Düzenlemek

Camping microframework kodumuzu MVC (Model-View-Controller) paternine uygun parçalamamıza olanak sağlar. Haydi Nuts uyuglamamıza bir görsel ekleyelim. module Nuts::Controllers'i şöyle değiştirin:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Camping.goes :Nuts

module Nuts::Controllers
class Index < R '/'
def get
@time = Time.now
render :sundial
end
end
end


module Nuts::Views
def layout
html do
head do
title { "Nuts And GORP" }
end
body { self << yield }
end
end

def sundial
p "The current time is: #{@time.strftime('%H:%M:%S')}"
end
end

Dosyayı kaydedip tarayıcınızda sayfayı tazeleyin. Şöyle bir mesaj çıkacaktır :

camping_3.png

Ve sayfamızın title barında şimdi Nuts And GORP yazıyor.

Burda gördüğünüz gibi kontrolörümüzden render :sundial komutunu veriyoruz. Bu aynen anlaşıldığı manaya geliyor, views modulündeki sundial metodu çıktısını yayınlıyor. Ayrıca layout adında özel bir metod da çağırdık, adından da anlaşıldığı gibi bu sayfanın yerleşim kalıbı oluyor ve markaby formatında bizim sundial metod çıktımız bunun içinde gösteriliyor. Eüer HTML ile haşır neşirseniz görseldeki ifadelerin HTML tag isimlerine benzerliğini farketmişsinizdir. Bu yapı HTML'i Ruby kullanarak yazmayı sağlayan Markaby yapısıdır. Zaten Markaby gem yüklü olmadan Camping server çalıştırırsanız bu sayfayı göstermeye kalktığınızda Markaby gem yüklü olmadığını belirten bir hata mesajı alırsınız, bu durumda klasik sudo gem install markaby ile yüklemelisiniz! Ben denerken 1.9.2 versiyon Ruby'de hata mesajı aldım. "undefined method to_s" şeklinde bir takip sonrasında hatanın çıkarıldığı markaby/builder.rb" dosyasının 280 nolu satırının üzerinde Ruby versiyon sorgulaması vardı. O sorgulamaya göre versiyon 1.9.1 den büyükse hata mesajı veriyordu, o satırı versiyon 1.9.5 ten büyükse hata ver deyip atlatınca sorun kalktı ama sonra başka ne çıkar bilemem, pansıman tedbir.

Gördüğünüz gibi kontrolör üzerinden herhangibir şeyi cevap olarak dönebilirsiniz ve bu cevap tarayıcınıza gönderilir. Fakat buna daha sonra dönelim ve routing (yönlendirme)
yapılarını inceleyelim.

Yönlendirmeler

Büyük ihtimal önceki sayfadaki acayip R '/' deyimini farkettiniz. Bu Ruby'nin bizim microframework'umuzda kullanılan ve kontrolöre nasıl erişileceğini belirten yönlendirmelerin standart dışı bir ifadesi.

Bu yönlendirmeler çok güçlçdçrler ama biz şimdi en basitinden başlayacağız.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

module Nuts::Controllers
# localhost:3301/welcome/yo/my/site adresi
class Words < R '/welcome/to/my/site'
def get
"You got here by: /welcome/to/my/site"
end
end

# localhost:3301/nuts/1 veya nuts/234 vs. sayı metoda parametre oluyor
class Digits < R '/nuts/(\d+)'
def get(number)
"You got here by: /nuts/#{number}"
end
end

# slash ( / ) içermeyen herşeyi seçmek
class Segment < R '/gorp/([^/]+)'
def get(everything_else_than_a_slash)
"You got here by: /gorp/#{everything_else_than_a_slash}"
end
end

# bir sayı arkasından herşey (localhost:3301/5/hasan gibi)
class DigitsAndEverything < R '/nuts/(\d+)/([^/]+)'
def get(number, everything)
"You got here by: /nuts/#{number}/#{everything}"
end
end
end




Bunları nuts.rb dosyasına ekleyin ve tüm kontrolörlere ulaştığınızı test edin.

Ayrıca dikkat ettiyseniz parantez içinde tanımlanan şeyler metoda parametre olarak aktarılıyor ve istediğiniz gibi kullanabilirsiniz.

Basit (ama akıllı) Yönlendirmeler

Bir de şunları deneyin:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Camping.goes :Nuts

module Nuts::Controllers

class Index
def get
"Buraya '/' ile geldiniz."
end
end

class WelcomeToMyPage
def get
"Buraya '/welcome/to/my/page' ile geldiniz."
end
end

class NutsN
def get(number)
"Buraya '/nuts/#{number}' ile geldiniz."
end
end

class GorpX
def get(everything_else_than_a_slash)
"Buraya '/gorp/#{everything_else_than_a_slash}' ile geldiniz."
end
end

class NutsNX
def get(number, everything)
"Buraya '/nuts/#{number}/#{everything}' ile geldiniz."
end
end
end




R-parçasını çıkarınca sistem aklınızdan geçeni okumaya başlar. Her zaman başarılı olamasa da uygulamanızı ne kadar basitleştiriyor gördünüz.


Dünyayı Modellemek

Şimdi birşeyler öğrenmeye başladınız , biraz oynayabilecek seviye bile oldunuz. Fakat sonraki adıma geçiş zamanı : Verileri saklamak.

Tekrar baştan başlayalım :

1
2
3
4
5
6
7
Camping.goes :Nuts

module Nuts::Models
class Page < Base
end
end

Apaçık belli ki bir kontrolörümüz olmadığı için bu bir iş yapmayacaktır. Fakat bunun yerine ne yaptığımızı inceleyelim.

Page adında bir modelimiz var. Bunun anlamı wiki sayfalarını saklayıp sonradan yayınlayabiliriz. Gerçekte, ne kadar model istersek üretebiliriz. Kullanıcılar için bir tane olmasını istemez misiniz? ve bir tane de blog yazıları için ? Pekala, sanırım nasıl yapılacağına dair fikriniz oldu.

Ancak bizim modelin birşeyi eksik : iskeleti! yani yapısı.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

Camping.goes :Nuts

module Nuts::Models
class Page < Base

end

class BasicFields < V 1.0
def self.up
create_table Page.table_name do |t|
t.string :title
t.text :content
# bununla created_at ve updated_at sütunları oluşur
t.timestamps
end
end

def self.down
drop_table Page.table_name
end
end
end


Şimdi modelimizin ilk versiyonuna sahip olduk. Şöyle deniyor:

  Eğer versiyon 1.0'a çıkmak istiyorsan,
    Page modelinin tablosunu üret,
    bu tablonun sütun isimleri şunlar,
      "title" string tipinde,
      "content" daha büyük olan text tipinde,
      "created_at" time tipinde kaydın üretildiği zaman,
      "updated_at" time tipinde kaydın enson değiştirildiği zaman.
   
  Versiyon 1.0'ı geri almak isterseniz,
    Page modelinin tablosunu sil.
   
İşte buna migration (birleştirme) denir. Ne zaman yeni bir model eklemek isterseniz bunların altına yeni bir migration ekleyeceksiniz ve versiyon numarasını artıracaksınız. Tüm bu migration'lar diğerinin üzerine LEGO blokları gibi eklenerek devam eder.

Şimdi geriye Camping'e bizim migrationumuzu kullanmasını istemek kaldı. Bunları nuts.rb'nin en altına ekleyin.

1
2
3
4
 
def Nuts.create
Nuts::Models.create_schema
end


Camping Server çalışınca otomatik olarak Nuts.create çağrılır. Buraya hertürlü başlangıçta çalışmasını istediğiniz kodu koyabilirsiniz, ama şimdi sadece migration çağırma  rutini koyuyoruz. Camping Server'ı çalıştırın ve ekrana bakın :

1
2
3
4
5
6
-- create_table("nuts_schema_infos")
-> 0.0370s
== Nuts::Models::BasicFields: migrating ======================================
-- create_table("nuts_pages")
-> 0.0250s
== Nuts::Models::BasicFields: migrated (0.0260s) =============================

Tekrar başlatın ve hiçbirşey olmadığını görün. Tekrar başlatınca artık yapacak migration kalmadı çünkü. Peki bu tablolar nereye konuyor? diye sordunuz galiba. Evet bu tablolar işletim sisteminizin kullanıcı klasöründe ".camping.db" adında bir sqlite3 veritabanı dosyası içinde yerleştirilir. Şimdi gidip o dosyayı bulun bir sqlite3 gezgini programla açın ve içindeki tabloları inceleyin.

Devam etmeden önce bir şey daha, modellerinizi herzaman migrationlarınızdan önce yerleştirin.


Modelimizi Kullanmak

Haydi konsol ile modelimizin çalışmasını test edelim.

1
2
3
$ camping -C nuts2.rb
** Starting console
irb(main):001:0>

Şimdi sizden bir giriş yapmanız bekleniyor ve siz girişinizi yapıp enter basınca hemen cevabı gelecek. Ben yaptıklarım&ı buraya yazıyorum, siz de kendi kayıtlarınızı üretebilirsiniz.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
irb(main):001:0> Page = Nuts::Models::Page
=> Nuts::Models::Page(id: integer, title: string, content: text, created_at: dat
etime, updated_at: datetime)

irb(main):002:0> hiking = Page.new :title => "Hiking"
=> #<Nuts::Models::Page id: nil, title: "Hiking", content: nil, created_at: nil,
updated_at: nil>

irb(main):003:0> hiking.content = "You can also set values like this."
=> "You can also set values like this."

irb(main):004:0> hiking.save
=> true


irb(main):005:0> page = Page.find_by_title("Hiking")
=> #<Nuts::Models::Page id: 1, title: "Hiking", content: "You can also set values
 like this.", created_at: "2011-03-19 17:13:32", updated_at: "2011-03-19 17:13:32"

irb(main):005:0> page = Page.find(1)
=> #<Nuts::Models::Page id: 1, title: "Hiking", content: "You can also set values
 like this.", created_at: "2011-03-19 17:13:32", updated_at: "2011-03-19 17:13:32"

irb(main):006:0> page.title
=> "Hiking"

irb(main):007:0> page.content
=> "You can also set values like this."

irb(main):009:0> page.created_at
=> Sat Mar 19 17:13:32 +0200 2011

irb(main):010:0> page.updated_at
=> Sat Mar 19 17:13:32 +0200 2011

irb(main):011:0> Page.find_by_title("Fishing")
=> nil

# Page.create kaydı otomatik olarak kaydeder.
irb(main):012:0> Page.create(:title => "Fishing", :content => "Go fish!")

irb(main):013:0> Page.count
=> 2



Şimdi 2 sayfamız var: Birinin başlığı Hiking diğerinin Fishing.


Derleyip toplamak

Ne dersiniz bu harika sayfaları tarayıcımızda göstersek öok güzel olmaz mı?
nuts.rb dosyasını şöyle düzenleyin:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

module Nuts::Controllers
class Pages
def get
# Sadece sayfa etiketlerini seç.
@pages = Page.all(:select => "title")
render :list
end
end

class PageX
def get(title)
@page = Page.find_by_title(title)
render :view
end
end
end

module Nuts::Views
def list
h1 "Tüm Sayfalar"
ul do
@pages.each do |page|
li do
a page.title, :href => R(PageX, page.title)
end
end
end
end

def view
h1 @page.title
self << @page.content
end
end

Burada ilk helper metodu görüyoruz:

1
R(PageX, page.title)

Bu bir ayrılmış yönlendirici dir ve kontrolör üzerinden bir URL üretir. Camping az sayıda ama etkili helper metodlarla gelir, kendi metodlarınızı da tanımlayabilirsiniz. Camping::Helpers konusu bunu anlatıyor.

Burada kendinizi geliştirmek için yapabileceğiniz şeyler var. Bazıları şöyle:




Son Rötuşlar

Uygulamamızda koca bir çatlak var. Yeni sayfa ekleyemiyor ve edit edemiyoruz. Haydi bunu nasıl yapacağımızı görelim:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

module Nuts::Controllers
class Pages
def get
# Sadece sayfa etiketlerini seç.
@pages = Page.all(:select => "title")
render :list
end
end

class PageX
def get(title)
if @page = Page.find_by_title(title)
render :view
else
redirect PageXEdit, title
end
end

def post(title)
# Eğer yoksa yenisini üret:
@page = Page.find_or_initialize_by_title(title)
# Süper! dimi? Bu şu satırla aynı:
# @page = Page.find_by_title(title) || Page.new(:title => title)

@page.content = @input.content
@page.save
redirect PageX, title
end
end

class PageXEdit
def get(title)
@page = Page.find_or_initialize_by_title(title)
render :edit
end
end
end


Bu kodların kemik noktası PageX kontrolörö post metodunda yatar. Bir kullanıcı linke tıklayınca ya da adres girince get metoduna gider. Ama bir form oluşturur ve orda veriyi toplayıp gönderirseniz post metoduna ulaşırsınız.

Kullanabileceğiniz başka isimler de var fakat her zaman çalışmayabilir. Bu yüzden aceleci olmayın ve bir süre daha get ve post ile devam edin. Nasıl çalıştığını ilerde göstereceğiz.

Ayrıca @input.content kullanımı dikkatinizi çekmiştir. @input hash yapısı formlardaki gibi ve (/posts?page=50) URL'sindeki gibi gönderilen parametreleri içerir.

Burada bir tane de edit görseli bulunuyor. Kendiniz daha iyi bir görsel yapabilirsiniz. Bununla bildiğiniz bir yapıyı birleştirmeye çalışın.

1
2
3
4
5
6
7
8
9
10
11
12

module Nuts::Views
def edit
h1 @page.title
form :action => R(PageX, @page.title), :method => :post do
textarea @page.content, :name => :content,
:rows => 10, :cols => 50
br
input :type => :submit, :value => Gönder!"
end
end
end



Phew!

Son birkaç dakikada birhayli ilerlediniz ve bir dinlenmeyi hakettiniz, ancak tekrar bir gözden geöirme yapalım :

Maalesef kitap burada son buluyor. Camping'i takip etmeye devam edin. Belgenin orjinalini https://github.com/camping/camping adresinde bulabilirsiniz.


Tuxweet - Twitter - Rstat.us - Github - Identi.ca - ujk7107@gmail.com