Selam Rails versiyon 7 çıktığından beri çok ilgilenemedim. Orjinal Getting Started dökümanından bir başlangıç yapayım dedim. Burada onu paylaşacağım.
Daha önce Windows 10'da Rails 7 kurulumunu sizinle paylaşmıştım. Kurulum için oraya bakabilirsiniz, ben direk uygulamaya geçiyorum.
Rails 7 Bir Blog Uygulaması Üretmek
Rails jeneratörler (generators) adı verilen bir çok yararlı terminal komutu içerir. Bunlardan biri yeni uygulama üretmek için kullanılır ve bize yeni bir Rails uygulamasında olması gereken tüm dosyaları üreterek kolayca başlangıç yapmamızı sağlar.
Ben Windows 10 işletim sistemi kullandığım için Rails 7 için en iyi yöntem olan Ubuntu Terminalinde çalışıyorum. Yeni uygulamamızı üretmek için çalışma klasörümüzde bir terminal açıp şu satırı girelim:
Bu komut blog adında bir klasör içinde yeni bir Rails 7 uygulamasının tüm gereken dosyalarını oluşturacak ve bundle komutunu çalıştırarak gerekecek tüm gem dosyalarını sisteme ekleyecektir.
Terminalde bir hata mesajı olmadan işlem bittiğini gördükten sonra uygulamamızı denemeye hazırız. Önce uygulama klasörüne girmek için
yazalım. Ben VSCode uygulaması kullanıyorum editör olarak. Editörde uygulama klasörünü açmak için terminalde
komutu çalıştırınca Code editörü açılır, solda uygulama klasörümüz içine yerleştirilmiş bir çok klasör ve dosya gçrürüz.
Başlangıç seviyesinde bir uygulama için en çok app, config ve db klasörü içindeki dosyalara muhatap olacağız.
- app klasöründe uygulama lojiği kodları bulunur. Tüm görseller , arka plan kodları, veri tabanı işleme kodları vs.
- config klasöründe uygulamamızın yapılandırmasına ait dosyalar var. Şu seviyede en çok adreslemeleri kullanacağız.
- db klasöründe ise veri tabanı ile ilgili dosyalar var.
Rails 7 Web Server Çalıştırılması
Geliştirme amacıyla yerelde bilgisayarımızda çalışan bir web server gerekiyor. Bu amaçla Rails 7 ile birlikte gelen server komutunu kullanabiliriz. Blog klasörümüzdeyken terminalde şu komutu girersek deneme serverimiz çalışacaktır.
ya da kısaca yazılan şekli
Server çalışır ve terminalde şuna benzer mesajlar verir
Puma server geliştirici modunda (development) çalışmaya başladı ve bizi http://127.0.0.1:3000 adresinde dinliyor.
Bundan sonra server'ı durdurmak istemiyorsanız yeni bir terminal açıp oradan devam etmenizi tavsiye derim.
Şimdi tarayıcımızda http://127.0.0.1:3000 web adresini açarsak bu yereldeki server'ın yayınladığı blog uygulamamızı görebiliriz.
Bu Rails 7 default sayfası. Bu sayfadan başka bir şeyler ekleyelim şimdi.
Rails 7 İlk Sayfamız
Bir şeyler gösterebilmek için bize sırayla bir bağlantı adresi (route), bir kontrolör (controller) ve onun içinde bir aksiyon (action) ve bir görsel (view) gerekiyor.
Önce bağlantı adresi ile başlayalım. Adres yönlendirmeleri /config/routes.rb dosyasında yapılır. Dosyayı editörde açalım.
Burada en başa şunu ekleyelim.
Bu satır bize "/articles" adresine (yerel server için http://127.0.0.1:3000/articles) yapılan bir GET başvurusunu articles kontrolörü index aksiyonuna bağlanıyor.
Terminalde mevcut adres bağlantılarını görmek için
komutu girersek, bize tüm bağlantıların listesini verir. Sadece articles kontrolörü için tanımlanmış adresleri görsek daha iyi olacak.
Kontrolör ve aksiyonu eklemek için Rails 7 jeneratör komutlarından birini kullanacağız. Terminalde
-skip-routes opsiyonu kullandık çünkü routes.rb içinde ilaveyi biz daha önce yaptık. Bu komut bizim için birçok yeni dosya üretecek.
En önemlisi kontrolör dosyası app/controllers/articles_controller.rb
Kontrolörümüzün adı ArticlesController ve ApplicationController ana sınıfından kalıtım yoluyla türetiliyor. Aksiyonlar ise kontrolör sınıfı içine metodlar olarak konur. index aksiyonumuz şu anda hiç bir şey yapmıyor. Ayrıca başka bir görsele yönlendirilmediği durumda bir aksiyon çağrılınca app/views klasörü içinde aynı isimde bir görsel dosyası arar. Az evvel terminalde çalıştırdığımız jeneratör komutu bizim için kontrolör ve aksiyon kodu yanında bir de örnek görsel üretti burada, app/views/articles/index.html.erb dosyası. Bu dosya içindeki geçici görsel kodları silelim ve şunu yazalım.
Şimdi http://127.0.0.1:3000/articles sayfasını tarayıcıda açalım.
Rails 7 Uygulama Ana Sayfasını Değiştirmek
Halihazırda http://127.0.0.1:3000 sayfası Rails 7 default sayfasını göstermeye devam ediyor. Diyelim az evvel tasarladığımız sayfayı ana sayfa olarak bu adreste göstermek istiyoruz. Bunun için routes.rb içinde belirtmeliyiz.
root "articles#index" komutu ana sayfayı articles kontrolörü index aksiyonuna bağlar.
Rails 7 MVC Yapısı
Adres bağlamaları, kontrolörler, aksiyonlar ve görselleri gördük şimdiye kadar. Bütün bunlar MVC (Model View Controller) web uygulama yapısının parçaları. Veritabanına bağlı bir web sitesi yaparken kullanılan bir tekniktir. Model veritabanındaki tablolar ve onlara ait işlemleri içerir. View az önce gördüğümüz görselleri içerir. Controller da uygulama lojiğini içerir.
İki tanesini gördük üçüncüye yani Model'e geçelim. Model kod olarak, veriyi temsil eden bir Ruby sınıfıdır. Ek olarak Rails'in ActiveRecord özelliğini kullanarak uygulamamız ve veritabanı arasındaki etkileşimi sağlar. Bir model tanımlamak için Rails model jeneratörünü kullanırız. Article modelimizi oluşturmak için terminalde şu satırı girelim:
Daha önce rails server komutunun kısa hali rails s kullanılabilir demiştik. rails generate komutunun da kısaltılmışı rails g yani yukarıdaki satırı
olarak da yazabiliriz. Bu komut bize yine bir kısım yeni dosya üretir.
En başta db/migrate klasöründe veritabanına articles adında ve istediğimiz sütunlara sahip bir tablo eklemek için kod bulunuyor. Terminalden modeli üretirken ismini Article olarak verdik. Burada İngilizce isim vermemizin sebebi Rails'in bir çok kolaylık sunması. Model ismini tekil veriyoruz çünkü model veri tablomuzdaki tek bir kaydın yapısını tarif ediyor. Birçok Article kaydının bulunduğu tabloya ise articles olarak çoğul isim veriliyor. Migration (birleştirme) dosyası başında dosyanın üretildiği tarih saat bilgisi olduğu için sizde farklı olacaktır ama _create_articles.rb kısmı aynı olacaktır. Şimdi bu dosya içine bakalım.
Migrasyon dosyaları içnde veritabanında yapılabilecek bir çok modifikasyon olabilir. Burada ise articles tablosunu oluşturmak için kod bulunuyor. string olan title ve text olan body sütunlarını zaten biz terminalde model üretirken istedik (title:string body:text opsiyonları ile). t.timestamps komutu ile Rails tablomuza kayıtların ilk girildiği ve değiştirildiği zamanlar için sütun ekliyor.
db klasörü içinde bulunan development.sqlite3 dosyası, uygulamamızın bu anda kullandığı veritabanı dosyası. Bu dosya içinde neler olduğunu VSCode editöründe görebiliriz. Ancak şimdi açarsak içinin boş olduğunu görürüz.
articles tablomuzun üretilmesi için terminalde veritabanı migrasyonlarını çalıştıran şu komutu girmeliyiz.
Komut bize şu çıktıyı verir
Şimdi development.sqlite3 dosyasını VSCode editörde tekrar açarsak şunu görürüz.
Bizim istediğimiz articles tablosu dışında Rails kendi kullanımı için başka tablolar da eklemiş. Tablomuzda bizim belirtmediğimiz sütunlar var. İlki id sütunu , bu sütun tablomuzun anahtar sütunu her yeni eklenen kayıt için bu sütuna da tamsayı ve diğer kayıtlardan farklı bir değer verilir. id sütunu Rails tarafından üretilen her model tablosuna otomatik olarak eklenir. Migrasyon dosyasına Rails tarafından default olarak eklenen t.timestamps satırı da sondaki iki sütunu yani created_at ve updated_at sütunlarını ekler. created_at söz konusu kaydın ilk eklendiği zamanı içerir, updated_at ise en son modifikasyon yapılan zamanı içerir. Bu bilgileri daha sonra kullanabiliriz. Örneğin Twitter'da paylaşımların başlığı yanında ne kada zaman önce paylaşıldığı yazıyor, o bilgi buna benzer bir sütundan alınır.
Code editör dışında tablo yapımızı az evvelki terminal komutumuz sonrası üretilen db/schema.rb dosyasında da görebiliriz.
Bu dosya bize veritabanımızda kullandığımız tabloların en son güncel ayarlarını gösterir. Her migrasyon sonrası bu dosya en son hale güncellenir.
title sütunu için string ve body sütunu için text bilgi var dedik. İkisi de yazı ama string daha küçük yazılar için text ise örneğin bu makalede benim yazdıklarım gibi çok uzun yazılar için tercih edilir.
created_at ve updated_at sütunları datetime tipinde veriler ve her kaydın mutlaka bu sütunlarda bir değere sahip olması gerekiyor. null: false şeklinde verilen opsiyon bu sütuna verilecek değer null olamaz, illaki bir değer girilmeli yoksa veriyi kaydetmem diyor. Neyse ki bu sütunları Rails otomatik dolduruyor ve bizim bir şey yapmamıza gerek yok.
Rails 7 Modeli Kullanarak Veritabanı ile Etkileşim
Tablomuzda henüz bir kayıt bulunmuyor. Article modelini kullanarak manuel yollarla veritabanı üzerinde çalışabilmek için Rails Konsol uygulamasını kullanabiliriz. Terminalde şunu girelim:
ya da kısaca
Bu bize uygulamamıza ait bilgileri içeren bir irb oturumu açacaktır.
Bu konsolda yeni bir Article nesnesini şöyle tanımlarız
Tabi hepsini tek satırda yazıp enter basalım, ben burada rahat görünsün diye iki satıra böldüm
Yeni bir Article nesnesi üretildi. İçinde ne olduğunu görmek istersek
Dikkat edersek id, created_at ve updated_at sütunlarında henüz bir değer yok. Sadece bizim verdiğimiz değerler var. Çünkü article nesnemiz daha veritabanına kaydedilmedi, şimdilik hafızada bir nesne. id sütunu tablomuzun anahtar sütunu olduğu için kayıt yapılırken veritabanı tarafından otomatik olarak bir değer verilecek. Diğer zaman değerlerini ise Rails biz kaydetmesi için komut verdiğimiz andaki zaman değeri ile dolduracak.
article nesnesini veritabanına kaydetmek için save metodunu kullanırız.
komut çalışınca yapılan işin bir açıklaması gelir
Gördüğümüz gibi Rails bir SQL sorgu satırı oluşturuyor ve article nesnesi içinde verdiğimiz bilgileri veritabanına kaydediyor. Dikkat edersek Rails created_at ve updated_at değerlerini otomatik olarak girmiş. Siz de bu değerlerden bu yazıyı ne zaman yazdığımı görüyorsunuz. id değerini ise veritabanı eğer gönderdiğimiz veriyi kabul eder ve kaydederse otomatik verecek. En alt satırda article.save metodundan dönen değer true olarak görünüyor. Bu bize veritabanına kayıt işleminin başarı ile bittiğini gösteriyor. Şimdi article nesnemize bir daha bakalım,
İlk kayıt olduğu için veritabanı id değerini 1 olarak girmiş. VSCode editöründe de development.sqlite3 dosyasını açarsak tablomuzda yeni gelen kaydı göreceğiz.
Bir kaydı tablodan bulmak için find metodunu parametresinde id değeri olacak şekilde girerek kullanırız.
Bu bize id değeri 1 olan, az önce eklediğimiz ve tablomuzdaki tek kayıt olan kaydı verecektir.
Gördüğümüz gibi Rails yine bir SQL sorgusu hazırlayarak işimizi görüyor. Bütün diğer özellikleri geçsek bile Rails'in veritabanında sorgulama yaparken işimizi bu kadar basitleştirmesi bile kullanmamız için yeterli sebep.
Tablomuzdaki tüm kayıtları getirmek için all metodunu kullanırız.
Article.all metodu bize tablomuzda kayıtlı tüm kayıtları getirecektir. Dönen cevap bir array (köşeli parantez içinde) ama tek bir kaydımız olduğu için şimdilik 1 tane array elemanı var içinde. Kayıtlar arttıkça id: 2 , id: 3 falan gibi elemanlar da eklenecek aynı sorgu cevabına.
Article.all ve Article.find metodlarını bizim ürettiğimiz article oluşum nesnesi ile karıştırmayalım. Tek bir kayıt değil tüm articles tablosu üzerinde işlem yapıyoruz. Bunlar modelimiz olan Article sınıfının metodları. Article sınıfı ActiveRecord sınıfından kalıtım yoluyla üretildiği için bu metodları bize ActiveRecord sınıfı sağlıyor aslında.
Aslında kendi ürettiğimiz nesneye a1 falan bir isim de verebilirdik. Bu kadar kafa karıştırmazdı o zaman. Ancak programcılıkta genel kuraldır, sınıf isimleri büyük harfle başlar o sınıftan üretilen nesne isimleri de sınıf isminin küçük harfle başlayanı olur. Birden fazla nesne üreteceksek de article1 , article2 gibi isimlendirme yapmak genel teamüldür. Tecrübeli bir yazılımcı büyük harfle başlayanın sınıf ismi , küçük harfle başlayanın nesne ismi olduğunu bilir.
Rails 7 Tablo Kayıtlarını Sayfamızda Göstermek
Az önce konsolda eklediğimiz kaydı web sayfamızda gösterelim. Önce gösterilecek kayıtları veritabanından okumak için kontrolör içinde aksiyon kodumuza ilave yapmalıyız.
@articles adında bir oluşum değişkenine az önce Rails konsolda kullandığımız Article.all metodu ile tablomuzdaki bütün kayıtları okuyoruz. Artık bu değişken adı ile görsellerde kullanabiliriz.
index aksiyonunun görseli bildiğimiz gibi index.html.erb dosyası. Bu dosya içeriğini şöyle değiştirelim.
.erb uzantılı dosyalar içinde <% ve %> işaretleri arasında Ruby kodları çalıştırabiliriz.
Bir döngü bloğu oluşturuyor. Kontrolörde @articles içine burada listelemek istediğimiz tüm kayıtları okumuştuk. Bu döngü her bir kayıt için döngü yapıyor.
Bu kod biraz deüişik, <%= ve %> arasında yazılmış. Bu şekil yazılırsa blok içindeki Ruby kodun çalışması sonucu oluşan değer o bulunulan noktaya yazılır. Tam bulunduğu yere o andaki kaydın title değerini yazar. Dikkat edelim bu kod sayfaya yazmıyor aslında HTML sayfa kaynağı içinde tam bulunduğu yere yazıyor. Eğer bulunduğu yer HTML kodu içinde gösterilen bir şeyse o zaman sayfada görünür.
Daha iyi anlamak için çalıştırıp görelim, yani dosyayı kaydedip tarayıcıda sayfayı yenileyelim.
Sayfa kaynağına bakarsak (tarayıcıda), body kısmında yani görünen kısımda şunu görürüz.
Burada bizim kodlarımız yok. Bizim kodlarımız server'da çalıştı ve sonucunda oluşan sayfa buraya geldi. Tekrar kodumuza dönsek ve şöyle yapsak,
Bunun sayfada görünümü
ve sayfa kaynağına bakarsak
Dediğimiz gibi <%= ile başlayan blok HTML kodu içinde tam bulunduğu yere sonucu yazıyor. Bu örnekte de bulunduğu yer sayfada görünen bir yer olmadığı için ancak sayfa kaynağına bakınca görebiliyoruz. Ama bu şekilde kullanarak HTML elemanların özelliklerini de Ruby kodu ile değiştirebileceğimizi gördük. Neyse görsel kodumuzu eski haline döndürelim ve devam edelim.
Şimdiye kadar öğrendiklerimizin bir üstünden geçelim. Rails'den bir sayfa talep edilince neler oluyor?
- Tarayıcı http://127.0.0.1:3000 adresine bir GET isteğinde bulunuyor.
- Rails uygulamamız isteği alıyor.
- Rails router bu adres ana sayfa adresi olduğu için onu routes.rb içinde istenildiği gibi ArticlesController kontrolörü index aksiyonuna yönlendiriyor.
- index aksiyonu Article modelini kullanarak veritabanından tüm kayıtları çekiyor.
- Rails otomatik olarak app/views/articles/index.html.erb görselini yayınlıyor.
- Görsel içindeki ERB kodu çalışarak yayınlanacak olan HTML kodunu modifiye ediyor.
- Server oluşan HTML kodunu tarayıcımıza cevap olarak gönderiyor.
MVC yapısının tüm parçalarını şimdiye kadar kullanmış olduk. Sırada Rails uygulamalarının ikinci önemli temel yapısı var.
Rails 7 Uygulamalarda CRUD İşlemleri
Bir veriye dayalı tüm web uygulamaları CRUD işlemlerini içermek zorundadır. CRUD - Create, Read, Update, Delete kelimelerinin baş harflerinden oluşturulmuş bir kelimedir. Create yeni kayıt oluşturmak, Read kayıtları okumak, filtrelemek, Update bir kaydı değiştirmek, Delete de bir kaydı veritabanından silme işlemleridir. Rails bize bu işlemler için birçok kolaylık sunar. Uygulamamıza daha fazla işlevsellikler kazandırarak bu işlemleri öğrenmeye başlayalım.
Sadece bir tek kaydı gösteren bir sayfa ile başlayalım. Daha önce tüm kayıtların listesi olan index sayfasını yapmıştık. Ama burada kayıtların sadece title özelliği yani başlıkları vardı , içerikleri yoktu. Şimdi de verilen id değerine sahip tek bir kaydın ayrıntılı halini gösterecek bir sayfa için ilk önce routes.rb içinde adres yönlendirmemizi yaparız.
get "/articles/:id" şeklinde yazılınca id başında iki nokta üst üste olduğu için bu değer değişebilir ve Rails tarafından parametre olarak alınacak demek oluyor. Yani /articles/1 ya da /articles/5 yazıldığında :id parametre değeri 1 ya da 5 olacak. Daha sonra kontrolör içinde bu değeri params[:id] şeklinde parametre array'inden okuyabiliriz.
Şimdi kontrolörümüze show aksiyonunu ekleyelim:
Bu aksiyonun görseli default olarak show.html.erb adında olacaktır. Onu da ekleyelim.
Şimdi http://127.0.0.1:3000/articles/1 adresinde elimizde olan yegane kaydı görebiliriz.
Adres yazmaya uğraşmadan kullanıcının direk listeden tıklayarak makalenin ayrıntısına gitmesi için index.html.erb görselindeki listeyi link şekline döndürmeliyiz.
HTML kodu olarak böyle. Rails 7 yardımcı metodları kullanarak bu linkin nasıl yapılacağını az sonra göreceğiz ama öncesinde bir düzenleme yapmamız gerekiyor.
Rails 7 Resources Adres Yönlendirmesi
Terminalde articles için tanımlı adres yönlendirmelerimize bir daha bakalım.
Şu ana kadar CRUD işlemlerinin sadece Read kısmına ait işlemler yaptık. Diğerleri için kullanacağımız daha bir çok yönlendirme olacak. Bunların hepsini tek tek tanımlayacağımıza Rails'in tüm CRUD işlemleri için standart olan yönlendirmelerini şöyle kullanırız.
resources :articles komutunun bizim için eklediği adres yönlendirmelerine terminalde bir bakalım.
Gördüğümüz üzere daha önce eklediğimiz 2 adres yönlendirmesi ekleyeceklerimiz yanında çok az kalıyor. resources metodu ayrıca Prefix olarak da bu yönlendirmeler için kullanacağımız kelimeler tanımlamış. Biz bu isimlerin sonuna _path ekleyerek kodlarımız arasında yönlendirmeler için kullanabiliriz.
Örneğin bizim show aksiyonumuz için Prefix değeri article. Biz article_path ismini kullanarak show aksiyonuna bağlanabiliriz. Bunu index.html.erb görseli içindeki linkler için yapalım.
Bu bize pek bir şey kazandırmıyor ama link_to yardımcı metodunu kullanmak bize çok şey kazandıracaktır.
link_to metodunun ilk parametresi link yazısnın ne olacağı , ikinci parametre ise nereye gideceğiz. Burada az evvel bahsettiğimiz prefix isimlerden aklınız karışmasın, link_to verilen nesneye bakıp nereye gideceğine karar verir. Yani
Şeklinde yazsak da çalışır. Bağlantı adresi için bir nesne verilirse link_to o nesnenin üretildiği modelin show aksiyonuna nesnenin id parametresi ile bağlanır.
Rails 7 Tabloya Yeni Kayıt Eklemek
Sıra geldi CRUD'un Create'ine. Tipik olarak yeni bir kayıt eklemek çok adımlı bir prosestir. Önce kullanıcı yeni kayıt eklemek için bir form talebinde bulunur. Sonra bu formu doldurup gönderir. Eğer bir sıkıntı yoksa kayıt yapılır ve bir çeşit onaylama işlemi yapılır. Eğer kaydedilecek verilerde bir sıkıntı olduysa forma tekrar dönülür ve işlem tekrarlanır.
Bir Rails uygulamasında bu proses new ve create aksiyonları ile yönetilir. Routes değerlerine bakarsak new için http GET ve create için http POST isteği beklendiğini göreceğiz. Bunları aklımızda tutup, öncelikle kontrolörümüze aksiyon metodlarını ekleyerek başlayalım.
new metodu @article adında yeni bir Article nesnesi üretiyor ve görsele bırakıyor işi. new.html.erb görselini birazdan oluşturacağız.
create aksiyonu ise, değerleri belli olan bir Article nesnesi oluşumu üretiyor. Aslında bu değerleri gönderilen formdan alacağız ama şimdilik göstermek amaçlı böyle yaptık. Sonrasında bu nesneyi save metodunu kullanarak kaydetme teşebbüsünde bulunuluyor. Konsolda yaptığımız denemeden hatırlarsak save metodu başarılı bir kayıt yapınca true değeri dönüyordu. Eğer kayıt başarılı olursa o kayda ait show sayfasına gidiliyor, başarısız olursa render metodu ile tekrar new görselindeki forma dönülüyor.
redirect_to yeni bir yönlendirme yapar ve eğer render yerine redirect_to ile new görseline gidersek daha önce forma girilen değerler sıfırlanır. render , formu en son üzerindeki verilerle açar.
Son olarak status: :unprocessable_entity opsiyonu ile new görseline geri dönerken tarayıcıya 422 Unprocessable Content cevabı da gönderir ve tarayıcıya "sen bişey gönderdin ama ben bu verileri işleyemiyorum" uyarı mesajı veriliyor.
Rails 7 Form Builder Kullanmak
Yeni kayıt bilgilerini girmek için formumuzu new.html.erb görselinde yayınlayacağız. Formumuzu oluşturmak için Rails form builder kullanacağız.
form_with yardımcı metodu bir form builder oluşum nesnesi üretir. form_with bloğu içinde label veya text_field gibi form elemanlarını kaydımızla ilgili olarak kullanırız. form_with çağrısı sonucunda şöyle bir html form kodu oluşur.
Rails 7 Zorlanmış Parametreler (Strong Parameters)
Formda gönderilen bilgiler params hash değişkenine konur. Böylece create aksiyonu formda girilen title değerine params[:article][:title] ile ve body değerine params[:article][:body] ile erişebilir. Bu değerleri ayrı ayrı Article.new metodunu kullanırken parametre olarak girebiliriz. Ancak formda girilecek veri sayısı arttıkça hata yapma olasılığımız çok artacaktır.
Bunun yerine parametreleri tek bir hash içinde verebiliriz. Bununla birlikte hash içinde hangi verilerin olabileceğini kısıtlamak gerekir. Kötü niyetli kişiler formu gönderirken bizim kullanıcıya sunmadığımız özel alanları da ekleyip, özel verilerimize erişebilirler. Zaten Rails de params[:article] hash değerini direk olarak Article.new metoduna verdiğimizde ForbiddenAttributesError hatası vererek bu şekil değerleri kabul etmez. Bu durumda params değerlerini filtrelemek için Rails strong parameters işlemini kullanırız.
Kontrolöre article_params adında bir private metod ekleyerek params değerlerini kısıtlayalım.
:article için gönderilen params değerinden sadece :title ve :body alanlarını alıp geri dönüyor bu metod. Dikkat edelim yukarıda create metodunda artık bu filtre edilmiş parametre hash kullanılıyor.
Rails 7 Veri Kontrolleri (validation) ve Hata Mesajı Göstermek
Anlattığımız gibi Rails'de yeni kayıt eklemek çok adımlı bir proses. Formu açtık , kullanıcı formu doldurdu ve Kaydet butonuyla gönderdi. Şimdi gelen verilerin geçerli olmasının kontrolü var. Modelimiz içinde tabloya girilecek verilerin kontrollerini yapabiliriz. app/models/article.rb içini şöyle düzenleyelim.
İlk kontrol title değeri için. presence: true ile title değerine mutlaka bir şey girilmesi şartı konuyor. O kutu boş bırakılamaz. İkinci kontrolde ise body değerinin hem boş bırakılamayacağı hem de length: yani harf sayısının minimum 10 karakter olması şartı konuyor.
Bu kontrollerden geçemezse @article.save metodu false değer dönecek ve form tekrar yayınlanacaktır. Formu tekrar verirken bir hata mesajı da vermek için görseli şöyle değiştiririz.
Şimdi boş bir formda Kaydet butonuna basarsak
Mesajların istediğimiz mesajlar olması için model ile oynayabiliriz.
Şimdi boş form yollarsak
Son olarak yeni kayıt için ana sayfaya bir link eklemeliyiz.
Prefix tanımlarına bakarsak link bizi http://127.0.0.1:3000/articles/new adresine gönderecektir. Hadi yeni bir kayıt ekleyelim.
Kaydet butonuna tıklanınca yeni kaydımızı gösteren sayfaya otomatik olarak gidecektir.
Rails 7 Bir kaydı Değiştirmek
CRUD kelimesinin CR harflerini halletik , sırada Update işlemi var. Bir kaydı değiştirmek , yeni bir kayıt yapmak ile çok benzer prosedür gerektirir. Önce kullanıcı kaydı değiştirme isteği gönderir. Form bu sefer boş değil içinde değiştirilecek kayıt bilgileri ile dolu olarak getirilir. Sonra kullanıcı değişikliklerini yapar ve formu gönderir. Eğer bilgilerde sıkıntı yoksa kayıt değiştirilir.
Bu işlemler kontrolörün edit ve update aksiyonları ile yönetilir. Şimdi bu metodların da tipik şeklini kontrolöre ekleyelim.
Dikkat edersek edit ve update aksiyonları new ve create aksiyonlarına çok benziyor. Fakat edit aksiyonu veritabanından söz konusu kaydı bulup @article oluşum değişkenine koyuyor. Böylece kayda ait bilgiler form oluşturulurken kullanılacak. edit aksiyonu tabi ki edit.html.erb görseline bağlı.
update aksiyonu ise yine veritabanından söz konusu kaydı buluyor ve formdan gönderilen verileri kullanarak ve nesnenin update metodunu kullanarak veritabanında kaydı değiştirmeye çalışıyor. Kayıt için yine filtrelenmiş article_params hash değeri kullanılıyor. Eğer değer kontrollerinde sorun olmaz ve veritabanında kayıt değişmesi sorunsuz gerçekleşirse değişen kaydın son halini göstermek için show aksiyonuna yönlendiriliyor. Eğer kayıtta sorun varsa edit görseli tekrar ama değerler başa döndürülmeden yayınlanıyor.
Rails 7 Ortak Görseller İçin Parça Görsel Yapısı
edit görselinde kullanacağımız ve daha önce new görselinde kullandığımız formlar birbirinin aynı. Böyle durumlarda aynı olan görsel kodunu parça görsel adı verilen dosyalarda toplamamız için Rails bize imkan sunuyor. Şimdi formumuzun kodlarını app/views/articles/_form.html.erb dosyasında toplayalım.
Parça görsel dosyaları isimleri mutlaka alt çizgi karakteri ile başlamalıdır. Buradaki form kodunun new görselinde yazdığımız koddan tek farkı @article oluşum değişkenini değil article yerel değişkenini kullanmasıdır. Şimdi new görseli dosyamızı şöyle yazarak bu parça görseli kullanacak hale getiririz.
Dikkat edersek render ile parça görsel çağrılırken baştaki alt çizgi karakteri yazılmıyor. Parça görsel çağrılırken orada kullanılacak olan article yerel değişkenine de @article değişkenine eşitleniyor. Mesela bu şekilde buton üzerinde yazacak yazıyı da parça görseli çağıran yerden belirtebiliriz.
Ve form parça görseli içinde buton kodunu şöyle yaparız.
Böylece new görselinden _form parça görselini çağırınca buton üzerinde Ekle yazacaktır.
Benzer şekilde edit görselini de ekleyelim uygulamamıza
İşi bitirmek için tek makalenin ayrıntılarını gösteren show görseline kaydı düzenlemek üzere bir link ekleyelim
Şimdi Düzenle linkine tıklayıp bir kaydı düzenleyelim.
Rails 7 Bir Kaydın Silinmesi
CRUD kelimesi son harfi olan Delete işlemine geldi sıra. Silme işlemi yeni kayıt ya da kayıt değiştirme işlemine göre çok daha basit. Sadece bir adres yönlendirmesi ve bir kontrolör aksiyonu gerekiyor. Adres bağlaması zaten routes.rb dosyasındaki resources satırı tarafından eklendi. DELETE isteği yapan yönlendirme kontrolörün destroy aksiyonuna yönlendirilmiş.
O zaman kontrolöre destroy aksiyonunu ekleyerek başlayalım.
destroy aksiyonu id değeri verilen kaydı veritabanından buluyor. Sonrası bu kayıt nesnesinin destroy metodunu çağırıyor ve kaydı siliyor. Sonrasında uygulama tarayıcıyı 303 See Other durum koduyla ana sayfaya gönderiyor.
Burada yönlenilen sayfa olarak root_path seçilmiş. Burada duruma özel tercih bu. Ama birden çok tablo üzerinde çalışan bir uygulama yaparken silme işlemi sonunda silinen kaydın tablosuna ait geri kalan verilerin gösterildiği index sayfasına dönmek genel olarak en mantıklı işlem olacaktır (mesela articles_path).
Şimdi show.html.erb görselinde en alta kaydı silmek için de bir link ekleyelim.
Normalde bir link GET eylemiyle istekte bulunur. Ama biz silmek için DELETE eylemi ile istek yapmalıyız. Bunu belirtmek için data opsiyonunu kullanıyoruz. data bloğu içinde verilen turbo_method ile DELETE eylemini kullanarak istekte bulunulmasını bildiriyoruz. Sadece turbo_method: :delete yeterli ama öylece bırakırsak kazara da olsa linke tıklandığı anda kayıt silinir. İstekte bulunulmadan önce kullanıcıya bir popup açıp onay almak için turbo_confirm özelliğine de bir mesaj değeri girerek kullanıcıya bu mesajın sorulması ve Tamam ya da OK butonu tıklanınca istekte bulunulmasını bildiriyoruz.
Burada İptal seçilirse kayıt silinmez. Genelde programlarımızda geri dönülemeyecek işlemler yapmadan önce hep bu şekilde kullanıcının onayını almalıyız.
Böylece CRUD işlemlerinin hepsinin nasıl yapıldığını öğrendik. Şimdi uygulamamıza ikinci bir model ekleyelim.
Rails 7 Uygulamaya İkinci Bir Model Eklemek
Makaleleri yayınladık. İkinci bir model tanımlayıp, o tabloda da yazılara yapılan yorumları saklayalım. Daha önce Article modelini oluştururken kullandığımız Rails jeneratörünü kullanalım. Terminalde:
commenter yani yorum yapanın adı ya da nik name'ini saklayan sütun verileri string tipinde olacak. Yorum yazısı yine body adlı sütunda saklanacak ve text tipinde olacak. Son sütun ise Article modeline referans bilgisi içerecek. article:references yazınca Rails tabloya article_id adında bir sütun ekler ve bu sütun söz konusu yorumun yapıldığı makalenin id değerini içermelidir. Bu takibi yapabilmek için Rails bize kolaylıklar sağlar. Bunların ilkini görmek için Comment model dosyasını açalım.
belongs_to :article satırı Comment kayıtlarının her birinin bir Article kaydına bağlı olması gerektiği belirtiliyor. Şimdi de jeneratörün ürettiği migrasyon dosyasına bakalım.
Article modeline bir referans var ve bu değer boş olamaz. Ayrıca tablonun bu sütununun foreign_key olduğu yani başka bir tabloya bağlantı bilgisi içerdiği bildiriliyor. Şimdi de bu migrasyon çalıştığında oluşacak tabloya bir bakalım. Terminalde ,
Oluşan tabloya VSCode editörde bir göz atalım
schema.rb dosyasında da yeni tablomuzun yapısını görebiliriz.
t.index ["article_id"] tabloda bir sütun değil Comment kayıtlarını article_id değerlerine göre sorgularken cevap hızı artsın diye konmuş bir indexleme. Ayrıntı isterseniz SQL sorgularda CREATE INDEX araştırabilirsiniz.
Neyse uygulamamıza dönelim. Comment modelinde kayıtların bir Article değerine bağlı olacağını belirttik ama tersi olarak Article kayıtlarının da bir ya da birden çok Comment kaydına bağlı olabileceğini belirtmeliyiz. Article modeli koduna şu ilaveyi yapalım:
has_many :comments satırı bir Article kaydının birden çok Comment kaydına sahip olabileceğini bildiriyor. comment değil comments yani çoğul yazıyoruz unutmayalım.
Bu iki model dosyası içinde yaptığımız bağlantı bildirimi sayesinde kayıtlar içinde çok kolay sorgular yapabiliriz. Mesela @article.comments bize o makaleye yapılan yorumları verir. @comment.article ise bize o yorumun yapıldığı makaleyi verir.
Adres bağlamalarını yaparken de modeller arasındaki ilişkiye uygun yapabiliriz.
Bu şekilde içi içe tanımlayınca adresler nasıl oluyor terminalde bir bakalım
Prefix isimlerine dikkat edelim. Bize daha kolay yollar sunuyor. Ancak uygulamamızda yapmayı düşündüklerimizden dolayı zaten yorumlar için makalelere benzer sayfalar hazırlamayacağız.
Rails 7 Yorumlar İçin Kontrolör Eklemek
Terminalde comments için bir kontrolör üretelim
Yorumlar için ayrı ayrı sayfalar yapmayacağız. Mantık olarak makaleyi okuyanlar yorumu hemen yazının altında yaparlar. Bu yüzden articles/show.html.erb içine yorum yapmak için bir form ekleyelim.
Burada anlamadığımız tek nokta model seçerken verdiğimiz [ @article, @article.comments.build ] değeri. Biz burada elimizde olan @article nesnesi özlliklerinden giderek bu formu oluşturmaya çalışıyoruz. Terminaldeki gördüğümüz Prefix değerleri ve adreslere bakarsak formumuzu /articles/:article_id/comments adresine POST eylemi ile göndermek gerekiyor.
Daha önce article için form doldururken /articles adresine POST eylemi ile göndermek için
Yazmıştık ve Rails bizi @article nesnesinin kontrolöründeki create aksiyonuna gönderdi. Şimdi bize bir comment nesnesi lazım ki buraya parametre olarak girelim. Bu nesneye ulaşmak için @article.comments.build yazarsak elimizde @article nesnesinin comment'leri ile aynı yapıda bir nesne elde ederiz.
yazarsak Rails comments_path adresine göndermeye kalkacak ama tanımlı adreslere bakarsak article_comments_path adresine göndermesi gerekiyor.
Şeklinde yazmak bizi birleşimi olan article_comments_path adresine yönlendirir. articles_controller.rb içinde show aksiyonuna bu @article nesnesine bağlı bir @comment nesnesi üretip göndersek daha mı kolay olurdu acaba?
Ama yine de içi içe adresleme olduğu için
şeklinde yazmak gerekiyor. Seçim size kalmış.
Şimdi kontrolör içine form gönderilince çalışacak olan create aksiyonunu yazalım.
Şimdi formu doldurup göndererek makaleye yorum yapabiliriz. Ama yapılan yorumları da show görselinde göstermemiz gerekiyor.
Artık yorum ekleyebiliriz.
Rails 7 Kolleksiyonları Parça Görselde Yayınlamak
Yorumları eklerken biraz dağıldık. Kodumuzu biraz toparlayalım. Mesela yorumları bir parça görselde toplayalım.
Sonra show.html.erb görselinde bu parça görseli kullanalım.
Bu render komutunu @article.comments kolleksiyonu ile çağırınca döngü yazmamıza gerek kalmıyor. Rails her bir yorum kaydı için _comment.html.erb görselini tekrar tekrar kullanıyor.
Yeni yorum ekleme formumuzu da app/view/comments klasöründe bir parça görsele taşıyalım. Orada olması daha doğru.
Form kodunda hiç bir şeyi değiştirmeden parça görsele aktardık. Şimdi show.html.erb görsel kodumuz baya bir kısaldı.
Refactoring işlerimiz de bitti.
Rails 7 Concern Kullanmak
Concern dosyaları karmaşık kontrolörler ve modeller kullanırken işleri basitleştirmek için kullanılır. Ayrıca bir çok modelde (veya kontrolörde) ortak kullanılabilecek işler için kullanılabilir. Concern kodları modüller kullanarak tanımlanır.
Concern kodlarını kontrolör ya da modellerimizde aynı modül kullanır gibi kullanırız. Uygulamamızı ilk üretirken Rails 2 tane klasör tanımlar.
Concern kodları nasıl kullanılır görmek için modellerimize ilave yapacağız. Sonra yazdığımız concern kodları ile bu ilave özellikleri etkili bir şekilde kullanmayı göreceğiz.
Bir blokta yazdığımız makalelerin çeşitli durumları olabilir. Örneğin yazımızı hazırlarken daha bitmeden önce sadece bizim göreceğimiz durum - private. Makaleyi yayınladığımızda herkesin görebileceği durum - public. Bir de eski makaleleri artık yayından kaldırmak ama veritabanından silmemek için arşivlenmiş durumu - archived.
Bu durumları benzer şekilde yorumlar için de kullanabiliriz. Onaylanmamış yorumlar private, yayınlananlar public ve gösterimden kaldırılanlar archived gibi. Şimdi bu bilginin saklanacağı sütunları veritabanımıza ekleyelim. Terminalde
Rails çok akıllı tasarlanmış migrasyona verdiğimiz AddStatusToArticles kelimesinden Add ile bir ilave yapılacağı, ToArticles ile articles tablosuna ilave yapılacağını, Status ve sonra opsiyon verilen ststus:string ile status adında string tipi bir sütun ekleneceğini anlıyor.
Şimdi migrasyon komutunu çalıştırıp bu eklediğimiz 2 migrasyonun gerçekleşmesini sağlayalım ve tablolarımıza bakalım nasıl olmuşlar.
Bu yeni sütunları ilk önce kontrolörlerin içindeki parametre zorlamalarına ekleyelim.
Modellerimiz içine de bu yeni sütun için değer kotrolü eklemek gerekecektir.
status sütunundaki değer GEÇERLİ_DURUMLAR içinde tanımladığımız durumlardan biri olmalıdır. Ayrıca bir kaydın arşivlenmiş olduğunu gösteren basit bir metod ilave ederek görsellerde arşivlenmiş kayıtları kolayca filtrelemek istiyoruz.
Aynı şeyleri Comment modelinde de yapmamız gerekiyor.
Şimdi index sayfamızda arşivlenmemiş makaleleri göstermek için ilave yapalım.
Yorumlar için hazırladığımız parça görsele de arşivlenmemiş yorumları göstersin diye ilave yapalım.
Daha önce girilmiş olan kayıtlarda status sütunu boş olduğu için hepsi gösterilmeye devam edecektir.
Bununla birlikte dikkatimizi çeken status sütunu yüzünden iki modelimizde de aynı kodları tekrar yazdık. İleride mesela private durumlu kayıtlar için ayrı bir işlem yapmaya kalksak yine her iki modelde de aynı kodları yazacağız. Tek yerde kod yazmak için modeller iin bir concern modülü ekleyelim. Kayıtların görünmesi ya da görünmemesine karar vereceğine göre modülümüze Visible adını verelim.
Veri doğrulamaları da concern içinde yapılabilir ama bunun için ActiveSupport:: Concern sınıfı metodlarını kullanmak gerekiyor.
Şimdi bu modülü modellerimiz içinde kullanalım.
Sınıf metodları da concern içine eklenebilir. Örneğin public durumlu makale sayısını hesaplayan bir sınıf metodumuzu concern içinde ifade edelim.
Artık diğer sınıf metodları gibi bu metodu sanki model sınıfımızın bir metoduymuş gibi kullanabiliriz. index görselimizde o anda kaç tane public durumlu makalemiz olduğunu yazalım.
Şimdi ana sayfaya bakarsak
Sıfır makale var diyor. Çünkü şu andaki kayıtlar biz status sütununu eklemeden önce eklenmiş kayıtlar ve status değerleri şu anda boş. Kayıtları düzenleyebilmek için form parça görsellerine status bilgisi girilmesi için de kullanıcıya seçenek sunmalıyız. Formlarda gönderme düğmesinin hemen üzerlerine bu seçeneği koyalım.
Yorumlar için şimdilik düzenleme sayfası yok ama yeni yorum eklerken kullandığımız forma da durum seçimi, ekleyelim.
Rails 7 Yapılan Yorumu Silmek
Bloğumuza yazdığımız yazılara yapılan yorumların uygunsuz olanlarını silmek için de bir link ekleyelim. Yorumlar için parça görselimiz _comment görseline destroy aksiyonunu çağıracak bir link ekleyeceğiz.
Şimdi kontrolörümüze destroy aksiyonunu ekleyelim.
@article nesnesini yorumu sildikten sonra tekrar tekrar makalenin görseline dönmek için kullanıyoruz. Geri kalan kısım Article için yaptığımızla aynı.
Rails 7 Kayda Bağlı Diğer Tablodaki Kayıtları da Silmek
Bir makaleyi sildiğimizde comments tablosunda ona bağlı yorumları silmezsek boş yere vertabanında yer kaplarlar. Rails bu amaçla bize model tanımında yapabileceğimiz bir kolaylık sağlıyor.
has_many :comments ile article kaydının comments tablosunda birden çok kayda bağlantısı olabileceğini ifade ederken, dependent: :destroy ile eğer bir article kaydı silinirse ona bağlı comment kayıtlarının da silinmesi için destroy eylemleri bağlanıyor.
Deneme için bir kayıt ve ona yapılmış 2 yorum ekledikten sonra makaleyi sildiğimizde server konsolunda yapılan işlemler şöyle sıralanıyor:
Önce bağlı yorumları tek tek silip en son makaleyi de siliyor.
Rails 7 Basit Yetkilendirme
Bloğumuzu bu haliyle yayınlarsak sayfaya bağlanan herkes yeni yazı veya yorum ekleyebilir. Yazılan yazıları ya da yorumları silebilir. Bir yetkilendirme sistemi kurup blog sahibinin yapabileceklerini belirtmemiz gerekiyor.
Rails bize basit HTTP yetkilendirme kullanmak için imkan sağlıyor. http_basic_authenticate_with metodu sayesinde belirlenen aksiyonların erişimini sadece verilen kullanıcı adı ve şifreyi doğru giren kişilerin erişebileceği hale getirebiliriz.
Mesela Articles kontrolöründe index ve show aksiyonlarına herkes erişebilsin ama diğer aksiyonlara sadece yetkili kişi erişebilsin şeklinde ayarlayalım.
Şimdi bir makale eklemeye , olan bir makaleyi değiştirmeye ya da silmeye kalktığımızda bize kullanıcı adı ve şifre soracaktır.
Burada kullanıcı olarak dhh ve şifre olarak secret girersek işlem devam eder yoksa erişimin engellendiğine dair bir hata mesajı çıkar. except: [:index, :show] opsiyonu ile index ve show haricinde tüm aksiyonlar için bu parola korumasının yapılması isteniyor.
Yorum içinse sadece yorum silmek için yetki isteyelim. Zaten sadece yeni yorum ekleme ve olanı silmek üzerine aksiyonlarımız var orada.
Bu sefer opsiyon olarak only: :destroy verdik, böylece sadece destroy aksiyonu için şifre istenecek.
HTTP basit yetkilendirme işleminde logout yapmak baya zor. Basit şekli tarayıcınızı kapatıp tekrar açmak. JavaScript Ajax falan bulaşmadan işi Rails ile çözmek için boş bir şifreyle girilen logout aksiyonu ekleyerek işi çözebiliriz.
Tabi ki routes.rb içinde bu aksiyona bir bağlantı eklemeliyiz.
Bir de ana sayfada logout yapmak için link ekleyelim
Kullanıcı LOGOUT linkine tıklayınca şifre sorar eğer hiçbir şey girmeden Tamam basarsa çıkış gerçekleşir ve articles ana sayfasına döner.
Orjinal yazı burada bitti, ben arada aklımın erdiğince bir şeyler ekledim. Umarım yardımı olur. Sonraki yazılarda buluşmak üzere kalın sağlıcakla..
Hiç yorum yok:
Yorum Gönder