24 Eylül 2011 Cumartesi

Ruby On Rails Bölüm 2 İlişkisel Veritabanı

Merhaba,

http://volkanaltan.blogspot.com/2011/09/ruby-on-rails-bolum-1.html Burda yapılanları unutup tekrar projemizi oluşturup alanları yeniden gönül rahalığı ile doğru bir şekilde oluşturalım. İlk yazı başlangıç problemleriyle geçen bir yazı olduğu için kod yazmanın tadına varamadık burda ilkinden edindiğimiz tecrübeler ile daha hızlı ilerleyeceğiz.

Kaynak kod: cms

İşlemlerin detayları hakkında bilgimiz olduğu için (hangi dizinden yapıldığı gibi) sadece komutları topladım.
Ayrıca burda fazladan tablolar ve güncelleştirmeler olabilir bu sebepten dökümana sadık kalmanızı tavsiye ediyorum.
rails new cms -d mysql
#bir önceki yazıdan database.yml dosyası bilgilerini alıp buraya girdim
rails generate scaffold Content site_id:integer parent_id:integer category_id:integer title:string description:text status:boolean
rails generate scaffold ContentCategory title:string status:boolean
rails g scaffold Site parent_id:integer title:string url:string folder_name:string host_name:string status:boolean
rails g scaffold Language code:string
rails g scaffold ContentTranslation language_id:integer content_id:integer field_name:string content:text status:boolean
rake db:create
rake db:migrate
rails server


Yukardaki komutları çalıştırdığınızda ContentCategory isimli bir tablo değil content_categories isimli bir tablo oluştuğunu göreceksiniz. Çoğul isimlendirmeyi sizin yerinize Rails hallediyor.

Yukarda yapmaya çalıştığımız sistemi biraz anlatmaya çalışayım böylece ne yaptığımızdan haberimiz olsun :)

1. Yapacağımız sistem de tek kod altında çalışan bir sürü site olacak.
2. Her sitenin kendine ait birden fazla domaini olabilir.
3. Her site içeriğinin (content) birden fazla içerik kategorisiyle ilişkisi olabilir. (ContentCategory)
Ama bu ilişkileri şimdilik ayrı bir tabloda tutmayacağım.
4. Her içerik birden fazla dile sahip olabilir. Bunun için ContentTranslate var. field_name alanına title gibi bir field, content alanında ise bu field a ait içerik bilgisi barındırılacak. Her içeriğin birden fazla field_name ve content alanı olabilecek.
Ayrıca Dil tanımlamasıda burda yapılacak. Yani field_name'i title olan bir kayıt için Türkçe ve İngilizce olarak 2 kayıt girilecek.


Aşağıdaki şekilde browser ile data girişi yapabiliyor olmamız gerek. Sorun varsa ilk makaleye dönüp burayı kontrol edin.
http://localhost:3000/sites http://localhost:3000/sites/new
http://localhost:3000/contents http://localhost:3000/contents/new
http://localhost:3000/content_translates ..
http://localhost:3000/translates ..

Önce veritabanı ilişkileri olmaksızın direk console üzerinden data girişi yapalım.

[volkan@volkans-MacBook]~/Development/rubyonrails/cms% rails console
Loading development environment (Rails 3.1.0)
ruby-1.9.2-p290 :001 >


ruby-1.9.2-p290 :002 > site1 = Site.create(:title => "deneme sitesi", :url =>"deneme.com", :folder_name => "denemecom", :host_name => "deneme.com,test.deneme.com", :status => true)
(0.3ms) BEGIN
SQL (0.4ms) INSERT INTO `sites` (`created_at`, `folder_name`, `host_name`, `parent_id`, `status`, `title`, `updated_at`, `url`) VALUES ('2011-09-27 18:05:27', 'denemecom', 'deneme.com,test.deneme.com', NULL, 1, 'deneme sitesi', '2011-09-27 18:05:27', 'deneme.com')
(0.7ms) COMMIT
=> #


Oluşturduğumuz kayda erişip bir kaç ufak deneme yapalım.
ruby-1.9.2-p290 :005 > site1.title
=> "deneme sitesi"
ruby-1.9.2-p290 :006 > site1.title.length
=> 13
ruby-1.9.2-p290 :007 > site1.title.reverse
=> "isetis emened"
ruby-1.9.2-p290 :008 >


İçerik girişi

ruby-1.9.2-p290 :008 > content1 = Content.create(:site_id => 1, :category_id => 1, :title => "ilk icerik", :description => "aciklama")
(0.2ms) BEGIN
SQL (0.3ms) INSERT INTO `contents` (`category_id`, `created_at`, `description`, `parent_id`, `site_id`, `title`, `updated_at`) VALUES (2, '2011-09-27 18:13:25', 'aciklama', NULL, 2, 'ilk icerik', '2011-09-27 18:13:25')
(0.6ms) COMMIT
=> #


Şimdi site_id 1 olan kayıtları çağıralım.
ruby-1.9.2-p290 :008 > Site.find(1).contents
Site Load (0.5ms) SELECT `sites`.* FROM `sites` WHERE `sites`.`id` = 1 LIMIT 1
NoMethodError: undefined method `contents' for #


Ama görüldüğü üzere hataların ardı arkası kesilmedi. Çünkü şu anda bu ilişkiler tanımlanmamış.
önce exit yapıp console dan çıkalım.

ilk olarak bu dosyayı düzenleyelim.
app/models/site.rb

sites tablosuna bağlı birden fazla content olabilir. bunu has_many komutu ile tanımlıyoruz. Aynı zamanda özel olarak tanımlama yapabiliriz mesela Sites'a bağlı content çağrıldığında sadece şunları çağır gibi.
Bu özel tanımlama için conditions komutu kullanılıyor.

:conditions => ['status = ?', true]


class Site < ActiveRecord::Base   has_many :contents,            :foreign_key => "site_id"
end



app/models/content.rb

Bu dosyada ise ihtiyaçları tanımlıyoruz. Yani bu tablo şuna ihtiyaç duyar gibi.

class Content < ActiveRecord::Base   belongs_to :sites   has_many :content_translations   end 


Burda aynı zamanda çeviri tablosunuda tanımladık.

Şimdi tekrar console geçip aynı komutu yazalım.

-------------------------------Ara kod---------------------------------
Ben burda contents için status alanını oluşturmamıştım o nedenle hata verdi. Tabi yukarda var çünkü güncelledim :) Kısa güncelleştirmeler için şöyle yapıyorum.
rails g migration AlterContent

Dosyanın içini şu şekilde doldurdum
class AlterContent < ActiveRecord::Migration   def up     add_column :contents, :status, :boolean   end    def down     remove_colmn :contents, :status, :boolean   end end 


rake db:migrate

-------------------------------Ara kod Bitiş---------------------------------
ruby-1.9.2-p290 :001 > Site.find(1).contents
Site Load (0.5ms) SELECT `sites`.* FROM `sites` WHERE `sites`.`id` = 1 LIMIT 1
Content Load (0.4ms) SELECT `contents`.* FROM `contents` WHERE `contents`.`site_id` = 1 AND (status = 1)
=> []


Görüldüğü üzere Status = 1 eklenmiş. Bunu gördük site.rb dosyasından bu kısmı kaldırıyorum.
çıkıp tekrar girmemiz gerek. (Artık çıkıp tekrar girme gerektiği konusunu hatırlatmayacağım bunu aklınızda tutun :) )
ruby-1.9.2-p290 :001 > Site.find(1).contents
Site Load (0.5ms) SELECT `sites`.* FROM `sites` WHERE `sites`.`id` = 1 LIMIT 1
Content Load (0.4ms) SELECT `contents`.* FROM `contents` WHERE `contents`.`site_id` = 1
=> [#]


İlişkisini tanımladığımız tablolarda tek hamleyle aşağıdaki gibi istediğimiz kadar kayıt oluşturabiliriz.
Buda işleri hızlandırmada bize yardımcı olacak bir unsur.
ruby-1.9.2-p290 :003 > site = Site.create(:title => "site 4")
ruby-1.9.2-p290 :004 > content = site.contents.create(:title => "icerik 4")
(0.2ms) BEGIN
SQL (0.4ms) INSERT INTO `contents` (`category_id`, `created_at`, `description`, `parent_id`, `site_id`, `status`, `title`, `updated_at`) VALUES (NULL, '2011-09-27 19:28:03', NULL, NULL, 4, NULL, 'icerik 4', '2011-09-27 19:28:03')
(0.9ms) COMMIT
=> #

ruby-1.9.2-p290 :007 > content.content_translations.create(:language_id => 1, :field_name => "[title-1]", :content => "title1 in basligi")


Sanırım olayın mantığı anlaşıldı. Aynı şekilde hiç yeni site oluşturmadan kayıt çekip onun üstünden gitmek istersek
aşağıdaki komut işimizi görecek. Gerisi yukardaki gibi devam ediyor.
ruby-1.9.2-p290 :008 > site2 = Site.find(2)


Kaynak kod: cms

12 yorum:

f.tma dedi ki...
Bu yorum yazar tarafından silindi.
f.tma dedi ki...

merhaba ben proje yapmaya çalışıyorum ruby on rails de okulumuzun sitesini yapmamız gerekiyor biz netbeans ı kurduk ama proje açamıyoruz bize yardımcı olabilirmisiniz çok az şüremiz kaldı.teşekkür ederim

Volkan dedi ki...

Merhaba,

Burda hazır bir poje var. Bunu kullanarak rahatlıkla devam edebilirsiniz...

https://github.com/kebab-project/kebab-revolution

f.tma dedi ki...

http://rubyforge.org/frs/download.php/69035/rubyinstaller-1.9.1-p378-rc2.exe normal bir program kuruyormuş gibi kuruyoruz kendisini C:\ruby19 diye bir klasore atar.

ardından sistem özelliklerinde ortam değişkenlerini açıyoruz Path kısmını buluyoruz c:\Ruby19\bin olarak ekliyoruz command console girip ruby i yazıyoruz.şu hatayı alıyoruz ruby iç yada dış komut çalıştırılabilir program yada toplu iş dosyası olarak tanınmıyor. bu hatayı aldığım için ilerleyemiyorum

Volkan dedi ki...

Yeniden başlatmanız gerek. Yoksa windows tanımaz...

f.tma dedi ki...

biz Ruby yi console ekranından kurmayı başardık sqlite3 ile oldu ama mysql ile olmadı şimdi netbeans yda aptana gibi bir program mı kullanıcaz yoksa console ekranından devam mı edicez bunu ile ilgili kısa bir bilgi verirseniz çok sevinirim https://github.com/kebab-project/kebab-revolution burayı inceledik dosyayı direk atarak çalıştırabilirmiyiz acaba
teşekkürler

Volkan dedi ki...

Kod yazmak için IDE iyi olur. Netbeans ücretsiz onu deneyebilirsiniz. Ayrıca başlangıç kurulum bilgileri için şuraya bakabilirsiniz. Ayrıca yine bu sitede bir çok Türkçe bilgi bulunmakta. http://www.gelistiricigunlugu.com/ruby-de-degiskenler-ve-veri-turleri-2/ http://www.gelistiricigunlugu.com/ruby-on-rails-te-api-yazalim/

f.tma dedi ki...

netbeansi windowsa nasıl kurucam java eklentisi istiyor onuda kuruyorum ama bazı yerlerde hata veriyor

Volkan dedi ki...

Hatayı görmeden yorum yapamam. Ama ben Windows'ta kullandım. Hiç sorun yaşamadım. Sorun çıktığı yerde bilgisayarı yeniden başlat :) Biraz uğraşman gerekiyor... Aldığın hata mesajlarını google yaz arat uğraş. Çoğu sorunun cevabı internette var.

Kolay gelsin.

f.tma dedi ki...

tesekür ederim :)

f.tma dedi ki...

bna gönderdiğiniz uygulamayı çalıştıramıyorum evolution-d18d766>rails s
←[31mgit://github.com/onurozgurozkan/paypal-recurring.git (at master) is not che
cked out. Please run `bundle install`←[0m bu hatayı alıyorum nedn acaba çözümünüde bulamadım...

Volkan dedi ki...

Bundan sonrası için onlardan yardım alsanız daha iyi olur. Dökümanları felan okuyun iyice.

Kolay gelsin.