18 Mart 2025 Salı

Rails 7 Denemeler 1

https://ujk-ujk.blogspot.com/2025/03/rails-7-denemeler-1.html
İçindekiler +

     

    Selam RubyOnRails versiyon 7 ile bazı denemeler yaparken framework özelliklerini öğrenmeyi amaçlıyorum. 



    RubyOnRails Kurulumu

    Rails kullanarak uygulama geliştirirken kullandığımız Ruby ve Rails gem versiyonlarının stabil olması , ileride sıkıntılar yaşamamak için önemli. Bu yüzden kurulumları Ruby Version Manager - rvm ile yapacağız. 

    RVM Linux sistemlerde kuruluyor Windows'ta da WSL Ubuntu terminal kullanarak kurulabilir. 

    Öncelikle PPA kaynaklarını kullanmak için yüklenmesi gereken paket için konsolda

    $ sudo apt-get install software-properties-common

    Bu baştaki $ işareti prompt'u ifade için kullanılan bir genel gösterim konsola onu yazmayacağız tabi ki.

    Şimdi rvm kaynaklarını sisteme eklemek için konsolda şu iki satırı girelim.

    $ sudo apt-add-repository -y ppa:rael-gc/rvm
    ve
    $ sudo apt-get update

    Son olarak rvm kurulumunu yapalım.

    $ sudo apt-get install rvm


    rvm kullanmaya başlayabilmek için kurulumda da belirtildiği gibi komutun yerini bildirmemiz gerekiyor.

    $ source /etc/profile.d/rvm.sh

    Kurulum gerçekleşti mi bakalım.

    $ rvm --version
    rvm 1.29.12 (manual) by Michal Papis,
    Piotr Kuczynski, Wayne E. Seguin [https://rvm.io]


    Eğer hala rvm command not found alıyorsanız terminali kapatıp açmanız gerekebilir. 

    Şimdi Ruby stabil versiyon 3.2.7 kurulumu yapalım.

    $ rvm install 3.2.7

    Bu uzun bir zaman alabilir. 

    Yüklediğimiz Ruby versiyonunu kullanmak için 

    $ rvm --default use 3.2.7

    Using /usr/share/rvm/gems/ruby-3.2.7

    Kullandığımız Ruby versiyonunu görelim.

    $ ruby -v

    ruby 3.2.7 (2025-02-04 revision 02ec315244) [x86_64-linux]


    Şu anda Ruby versiyon 3.2.7 ve rvm hazır , artık RubyOnRails kurulumuna geçebiliriz. 



    Rails 7 kurulumu

    Şimdiye kadar Rails hariç bize gereken geliştirme ortamının kurulumunu gerçekleştirdik şükür. 

    Öncelikle her eklediğimiz Ruby gem için doküman yüklenmesini engellemek için aşağıdaki komutu girelim de yüklemelerimiz hızlansın.

    $ echo "gem: --no-document" >> ~/.gemrc

    Bu komut root klasöründeki .gemrc dosyasına bir satır ilave ederek bundan sonra gem yüklemelerinde doküman yüklenmemesini sağlar.

    Şimdi Rails gem'inin istediğimiz versiyonunu yüklemek için.

    $ gem install rails -v 7.2.2

    Test edelim.

    $ rails -v
    Rails 7.2.2





    İlk Uygulamamız

    Her programlama dilinde olduğu gibi ekranda bir "Merhaba Dünya" yazısı almak ilk uygulamanın amacıdır. Biz Rails kullandığımız ve Rails de web uygulaması geliştirme platformu olduğuna göre ilk uygulamamızda bir web uygulaması gerçekleştireceğiz. 

    RubyOnRails ile yeni bir uygulama oluşturmak için rails new komutu terminalde çalıştırılır. Bu komut ismini verdiğimiz klasör altında bir Rails uygulamasının iskeletini kurar. 

    Önce denemelerimizi yapmak için bir klasör oluşturalım.

    $ cd
    # mkdir rails7
    # cd rails7


    Şimdi bu klasör içinde belirlediğimiz Rails versiyonu ile yeni bir uygulama oluşturalım.

    $ cd ~/rails7
    $ rails _7.2.2_ new merhaba_app --skip-bundle

    Burada _7.2.2_ şeklinde versiyon belirtmek zorunda değiliz ama biz kararlı bir uygulama yapalım diye Rails versiyonunu da belirttik, yoksa en son yüklenen rails gem versiyonu ile çalışır. --skip-bundle seçeneği ile bundle çalıştırmasını otomatik yapmasın biz sonra kendimiz elle yapacağız diyoruz. 

    Şu anda merhaba_app adında bir klasör içinde yeni uygulamamızın dosyaları toplanmış durumdadır. Klasör içindeki dosya yapısına bir bakalım.


    Kısaca bir liste tablomuzda dosya ve klasörleri anlatıyor.

    Dosya/Klasör      Amacı
    -----------------------------------------------------------------
    app/              Ana uygulama kodunu içerir, modeller, kontrolör
                      ler, görseller ve yardımcılar
    app/assets        Stiller, resimler gibi uygulamamızın varlıkları
    bin/              Binary çalıştırılabilir dosyalar
    config/           Uygulama yapılandırması
    db/               Veritabanı dosyaları
    doc/              Uygulama dokümanları
    lib/              Kütüphane modülleri
    log/              Uygulama log dosyaları
    public/           Dışarıdan tarayıcıdan erişilebilen dosyalar,
                      örneğin hata sayfaları
    bin/rails         Konsol oturumu açmak veya server çalıştırmak
                      gibi işlemleri yapan program
    test/             Uygulama test dosyaları
    tmp/              Geçici dosyalar
    README.rb         Uygulamanın kısa açıklaması
    Gemfile           Bu uygulamada kullanılacak gem'lerin listesi
    Gemfile.lock      Uygulamanın tüm kopyalarında aynı versiyon
                      kullanılması gereken gem listesi
    config.ru         Rack middleware için yapılandırma dosyası
    .gitignore        Git tarafından dikkate alınmayacak dosyalar




    Bundler

    Yeni bir Rails uygulaması ürettikten sonra yapılması gereken , uygulamamızın kullanacağı gem'leri bundler yardımıyla kurmak. Uygulamamız oluşturulurken otomatik olarak Gemfile adında bir dosya da üretilmişti. Burada Gemfile içinde verilen listeyi görmek istiyoruz. Bir editör ile Gemfile dosyasını açalım (ben VSCode kullanıyorum). 

    Eğer sisteminizde VSCode uygulaması yüklüyse uygulamamızın klasöründe 

    $ code .

    Yazarak VSCode editörünü uygulama klasörümüzdeki dosyaları düzenlemek için açabiliriz. Windows işletim sisteminde WSL Ubuntu ile çalışıyorsanız code . komutu ile zaten Windows'ta kurulu olan VSCode editörü otomatik olarak WSL Ubuntu sistemi için gereken dosyaları yükleyip çalışır. Dönelim Gemfile dosyamıza.

    Bu dosyada birçok satır yoruma atılmış bazı gem'lerin bundler ile nasıl kullanılacağına dair bilgiler veriyor. gem komutuna versiyon numarası belirtmezsek bundler o gem'in en son versiyonunu yükler. 

    gem "sprockets-rails"


    Gem versiyonu belirtmenin iki değişik yolu var.

    gem "sqlite3", ">= 1.4"

    Bu şekilde >= kullanınca gem'in o versiyon ya da ondan büyük versiyon olan en son versiyonu yüklenir.

    gem "rails", "~> 7.2.2"

    Bu şekilde ~> kullanınca 7.2.2 ya da daha yüksek minor versiyon gem yüklenir 7.2.9 varsa yüklenir ama 7.3 yüklenmez. 

    Gemfile dosyamızda Rails uygulamamızın kararlılığı için bir tek satır değiştireceğiz.

    gem "rails", "~> 7.2.2"

    Olan satırı kesinlikle versiyon 7.2.2 kullansın diye 

    gem "rails", "7.2.2"

    Yapalım ve dosyayı kaydedelim. Şimdi klasörümüze geçip bundle komutunu çalıştıralım.

    $ cd merhaba_app
    $ bundle install


    Bu noktadan sonra uygulamamız artık çalışmaya hazırdır. 


    rails server

    rails new ve bundle install komutlarından sonra uygulamamız çalıştırılmaya hazır. Rails uygulamamızı bir server'da denememiziçin bize rails server komutunu sunar. Uygulama klasörümüzde bu komutu çalıştıralım.

    $ rails server

    Bu noktada bir hata ile falan karşılaşırsanız ilk önce 

    $ gem update --system

    denemenizi öneririm. Sonra her şeye yeni yüklenen rails versiyonu ile devam edin. 

    Server çalışınca Listening on http://127.0.0.1:3000 mesajını yazılanlarda görebiliriz. Bu bilgisayarımızda port 3000'de tarayıcımıza cevap vermeye hazır bir server çalıştığını gösterir. Tarayıcımızın adres kısmına http://localhost:3000 yazıp enter basalım ve açılan sayfaya bakalım.


    Bu resmi görmeyi başardıysak Rails'in bizim için otomatik oluşturduğu uygulama çatısı çalışıyor demektir. Artık sırada onu değiştirmeye başlamak var, ama öncelikle Rails uygulama bel kemiğini oluşturan MVC yapısına bakalım.


    Model-View-Controller (MVC)

    Daha çok başlardayız ama Rails'in nasıl çalıştığını anlamak için MVC uygulama tekniğini biraz anlamamız gerekiyor. Şu şekle bir bakalım.


    Uygulamamızın app/ klasörü de models , views , ve controllers adında 3 klasör içeriyor. Bunlar Rails'in MVC (models-views-controllers) yapısını takip etmek için kullandığı klasörler. MVC yapısı uygulamanın iş yapan kısmını, görsel kısmını ve verileri ayarlama kısmını ayrı yerlerde gruplama temeline dayanıyor. Bu uygulama geliştirmede en yaygın kullanılan tekniklerden biridir.

    Bir Rails uygulaması ile iletişimde olan bir tarayıcı, bir istek gönderir. Server bu isteği kontrolör nesnesine iletir. Kontrolör bu isteğe karşı ne yapılacağını bilir. Bazı durumlarda kontrolör bir şablondan görsel cevabı oluşturarak (HTML gibi) tarayıcıya cevap olarak gönderir. Bazı durumlarda ise kontrolör önce model ile iletişime girerek oradan istediği verileri çeker ya da değiştirir ve bu veriler doğrultusunda bir HTML görünümü tarayıcıya döner. 

    Bunlar şimdilik biraz soyut gelse de ilerde uygulamalar yaptıkça iyice sindireceğiz nasipse. 



    Merhaba Dünya!

    İlk uygulamamızda küçük bir değişiklik yaparak "Merhaba Dünya!" mesajımızı görmeye çalışacağız. Bunu Merhaba Dünya! mesajı yazdıran bir kontrolör eylemi tanımlayarak yapacağız. 

    İsminden de anlaşılacağı üzere kontrolör eylemleri , kontrolörün içinde tanımlanır. Şimdi merhaba eylemimizi Application kontrolörü içinde tanımlayacağız. Şu anda Application kontrolörü uygulamamızın app/controllers dizinindeki yegane kontrolör. Uygulamamızda mevcut kontrolörleri 

    $ ls app/controllers/*_controller.rb

    Komutunu konsolda girerek görebiliriz. app/controllers/application_controller.rb dosyasındaki kodu editörümüzle şu şekilde değiştirelim.

    class ApplicationController < ActionController::Base
      # Only allow modern browsers supporting webp images, web push, badges,
      # import maps, CSS nesting, and CSS :has.
      allow_browser versions: :modern

      def merhaba
        render html: "Merhaba Dünya!"
      end
    end


    Dosya içindeki yazılı olanları silmedik, sadece merhaba metodu tanımını ekledik. İstediğimiz string'i dönen bir metod tanımlamak Rails'e default sayfa yerine bu eylem istenince bu cevabı vermesini anlatır. Default sayfa yerine bu eylemin sonucunun dönülmesi için Rails yönlendiriciye ana sayfa olarak bu eyleme yönlenmesi gerektiğini anlatmalıyız. Rails yönlendiriciler uygulamamızın config/routes.rb dosyasında listeleniyor. Bu dosyanın en altında iki satır bize yönlendirmenin nasıl yapılacağını yorum satırlarında göstermiş.

      # Defines the root path route ("/")
      # root "posts#index"

    Şimdi bizim merhaba eylemimize gitmesini sağlamak için alttaki satırda yorumu kaldırıp şu hale getirelim.

      # Defines the root path route ("/")
      root "application#merhaba"

    Şimdi server'ı çalıştırıp localhost:3000 sayfasını açarsak ya da zaten server çalışmakta ise sayfayı yenilersek.


    application#merhaba notasyonunu Rails sistemi için application_controller.rb dosyasındaki merhaba metodu anlamına geliyor. 

    Yaşasın sonunda Merhaba Dünya uygulamamızı çalıştırmayı başardık. Merak etmeyin ilerledikçe Rails'in işlerimizi uzatan değil aslında çok kısaltan bir yapı olduğunu kavramaya başlayacağız. 

    Ctrl+c basarak server'ı durduralım.





    Buzz Adında bir Uygulama

    Şimdi Rails'in gücünü görmek için küçük bir uygulama yapacağız. Rails'in ve web geliştirmenin temellerine gireceğiz biraz. Hızlıca uygulama geliştirmek için bir sürü işi bizim için otomatik yapan Rails scaffold üreticilerini kullanacağız. Bu küçük uygulama ile Rails'in meşhur REST yapısını da göreeceğiz. 

    Uygulamamızda kullanıcılar ve onların mikro gönderileri olacak. Kafa karıştırmamak için tasarımı oldukça basit tutacağız. Temelleri anladıktan sonra ayrıntılarla uğraşmak daha kolay olacak. 



    Uygulamanın planlanması

    Öncelikle uygulama iskeletimizi bir hazırlayalım da bir kenarda dursun. 

    $ cd ~/rails7
    $ rails new buzz --skip-bundle
    $ cd buzz

    Şimdi önceki uygulamada anlattığımız gibi Gemfile içinde 

    gem "rails", "7.2.2"

    Değişikliğini yapalım ve bundler çalıştıralım.

    $ bundle install

    Artık uygulama hazır server çalıştırabiliriz.

    $ cd ~/rails7/buzz
    $ rails server

    Tarayıcımızda localhost:3000 adresine gidelim ve default giriş sayfasını görelim , sonra devam edelim.

    Önceki uygulama gibi bu uygulamada da giriş sayfasını değiştirerek başlayalım. Önce application_controller.rb kontrolör dosyasına merhaba metodu ilave edelim.

      def merhaba
        render html: "Merhaba Buzz!"
      end

    Sonra da config/routes.rb dosyasının son satırına 

      root "application#merhaba"

    satırını ekleyelim. Şimdi rails server çalıştırıp http://localhost:3000 adresine tarayıcımızda bakarsak kendi mesajımızı görürüz. 



    Kullanıcılar veri modeli

    Artık uygulamamızı geliştirmeye başlayabiliriz. Genelde bir Rails uygulaması geliştirirken ilk yapacağımız veri modellerini ve aralarındaki ilişkileri tanımlamak olacaktır. Bizim basit uygulamamızda sadece kullanıcılar ve onların mikropostları olacak. Öncelikle veri tabanımızda bulunacak ve kullanıcıları saklayacak olan users tablosu ile başlayalım.

    İnternette birçok siteye kayıt için kullanıcı girişleri görmüşsünüzdür , bir sürü bilgi isterler. Biz basit kalmak amacıyla çok az bilgi kullanacağız. Kullanıcıların bir id değeri (integer ve yegane), herkesin göreceği isimi saklayan bir name değeri (string tipi) ve bir email adresi olacak (bu da string ve yegane). Şimdilik password yok şifreleri nasipse daha ilerideki konularda göreceğiz. 

    users modelimizin yapısı şöyle:

    users
    idinteger
    namestring
    emailsrting


    Burada users veri tabanında bir tablo adına , id, name ve email de tablonun sütunlarına karşılık geliyor.



    Mikropostlar veri modeli

    Bir mikroblog uygulaması geliştiriyoruz demiştik. Kullanıcıların paylaştıkları kısa gönderileri de microposts adında bir model ile ifade edelim. Neler olacak? Yine kayıtları karıştırmamak için her gönderinin benzersiz bir id değeri (integer) olacak, gönderi içeriğini saklayan content değeri (text) olacak ve hangi kullanıcıya ait olduğunu saklayacağımız (ve ilgili kullanıcının id değeri ile aynı olan) bir user_id değeri (integer) olacak. Modelimiz şöyle:

    microposts
    idinteger
    contenttext
    user_idinteger


    İleride bu user_id şeklinde notasyonun bir kullanıcının birçok gönderisi olmasını ifade ederken nasıl kullanıldığını göreceğiz bu yüzden veri modellerinde mümkün olduğunca Rails özelliklerinden yararlanmak için İngilizce isimler kullanmaya gayret ediyorum.



    Users Resource

    Önce kullanıcılar için düşündüğümüz users modelinin kaynaklarını oluşturacağız. İşimiz bittiğinde users tablosu, tablodaki verilerin listelenmesi, değiştirilmesi, eklenmesi ve silinmesi işlemlerinin hepsini HTTP üzerinden tarayıcımız ile yapabiliyor olacağız. Tüm bu users modeline ait dosyalara Users Resource denir. 

    Bir veri modeli hakkında tüm kaynak dosyaları Rails scaffolding kullanarak çok kolay ve otomatik olarak oluşturabiliriz. Ruby programcılarının farkı burada ortaya çıkıyor, aynı işleri yapmak için uzun süreler uğraşmak istemiyorlar ve o işleri Ruby'ye yaptırıyorlar. 

    Kaynakları oluşturmak için rails generate metoduna scaffold ifadesi ve argümanlarında modelimizin bilgilerini veriyoruz. Öncelikle eğer açıksa Rails server'ı kapatalım.  Uygulama klasöründe şunu girelim.

    $ rails generate scaffold User name:string email:string

    Bir sürü yeni dosya oluşturdu. Ama onlara geçmeden önce yazdığımız komuta bir bakalım. 

    rails generate - Rails sisteminin bize bir çok değişik işleri kısaltmak için hazırladığı komut

    scaffold - bir modelle ilgili tüm kaynakları oluşturan sihirli komut

    Model adı girilirken Büyük harfle başladığı ve tekil yazıldığına (users değil) dikkat etmeliyiz. 

    name:string ve email:string ise modelimizin sütunları, key parametre gibi verilmiş. 

    id sütunu ise scaffold argümanlarında verilmiyor, Rails her model tanımlamasında otomatik olarak benzersiz integer değeri olan bir id sütununu otomatik ekler. 

    Rails scaffold işlemi birçok dosya oluşturdu ama veri tabanında tabloyu otomatik olarak oluşturmadı, sadece migration (birleştirme) dosyası hazırladı. Komutun çıktısında 

    db/migrate/20250317181337_create_users.rb

    benzeri create_users başına tarih/saat yazılmış bir dosya oluşturdu. Bunun içine bir göz atalım.

    class CreateUsers < ActiveRecord::Migration[7.2]
      def change
        create_table :users do |t|
          t.string :name
          t.string :email

          t.timestamps
        end
      end
    end


    Aşağı yukarı bir şeyler tahmin edilebiliyor ama şimdilik anlamaya çalışmayalım. Yolumuza devam edelim, bu birleştirmenin Rails tarafından gerçekleştirilmesini sağlamalıyız. 

    $ rails db:migrate
    == 20250317181337 CreateUsers: migrating =======================
    -- create_table(:users)
       -> 0.0154s
    == 20250317181337 CreateUsers: migrated (0.0163s) ==============


    rails db:migrate komutu veri tabanı için oluşturulmuş ve işlenmemiş db/migrate dizini içindeki birleştirme dosyalarını veri tabanına işler. 

    Artık veri tabanımızda yeni tablo eklenmiş ve kullanıma hazır. Benim bir portable SQLite veri tabanı inceleme programım var, onda açınca tablo şöyle görünüyor:


    Scaffold sadece veri tabanı dosyaları hazırlamadı, ayrıca bu tabloda işlem yapmak için gerekli dosyaları da üretti. 



    Kullanıcılarda gezinelim

    Şu anda server'ımızı çalıştırsak User modelindeki kayıtlar için hazırlanmış sayfalar mevcut.

    URL             Eylem       Amacı
    -----------------------------------------------------
    /users          index       Tüm kullanıcıların listesi
    /users/1        show        id değeri 1 olan kullanıcı
    /users/new      new         yeni kullanıcı ekleme sayfası
    /users/1/edit   edit        id 1 kullanıcıyı değiştirme


    Şimdi server'ı çalıştırıp http://localhost:3000/users sayfasını tarayıcıda açalım.


    Devam etmeden önce hemen bu sayfada bir düzenleme yapalım. Server'ın konsola yazdıklarına bakarsak tarayıcının /users isteğine cevap olarak 

    Rendering users/index.html.erb

    mesajı var. Bu dosya /users sayfasının görseli ve app/views/users/index.html.erb dosyası. Editörümüzde açalım.

    <p style="color: green"><%= notice %></p>

    <% content_for :title, "Users" %>

    <h1>Users</h1>

    <div id="users">
      <% @users.each do |user| %>
        <%= render user %>
        <p>
          <%= link_to "Show this user", user %>
        </p>
      <% end %>
    </div>

    <%= link_to "New user", new_user_path %>

    Burada ne olduğuna sonra geleceğiz şimdilik sadece gördüklerimizi Türkçe'ye çevirmek için değişiklik yapalım.

    <p style="color: green"><%= notice %></p>

    <% content_for :title, "Users" %>

    <h1>Kullanıcılar</h1>   <%# burası %>

    <div id="users">
      <% @users.each do |user| %>
        <%= render user %>
        <p>
          <%= link_to "Kullanıcıyı göster", user %>   <%# burası %>
        </p>
      <% end %>
    </div>

    <%= link_to "Kullanıcı ekle", new_user_path %>   <%# burası %>

    Sayfayı yenilersek görüntü değişmiş olacaktır.


    İstediğmizi elde ettik. Yeni bir kullanıcı eklemek için Kullanıcı ekle linkine tıklayalım, bu bizi /users/new sayfasına götürür. 


    Bu görüntüde de Türkçe düzenlemesi yapalım. Bu sayfanın görselinde 2 adet görsel dosyası kullanılıyor, ilki app/views/users/new.html.erb

    <% content_for :title, "New user" %>

    <h1>New user</h1>

    <%= render "form", user: @user %>

    <br>

    <div>
      <%= link_to "Back to users", users_path %>
    </div>

    Burada render "form" satırı gördüğümüz formun başka bir dosyadan yüklendiğini gösteriyor. Bu dosyamızda sadece "Back to users" yerine "Kullanıcılara geri dön" yazalım ve h1 başlığındaki New user yerine Yeni Kullanıcı yazalım. 

    <% content_for :title, "New user" %>

    <h1>Yeni Kullanıcı</h1>

    <%= render "form", user: @user %>

    <br>

    <div>
      <%= link_to "Kullanıcılara geri dön", users_path %>
    </div>

    Görselin form kısmı aynı dizindeki _form.html.erb dosyasında bulunuyor , bu kısmi bir görsel dosyası (adı _ ile başlıyor). Çünkü aynı form kullanıcı bilgisini edit ederken de kullanılıyor. Bu dosyada şu kısma ilave yapıyoruz.

      <div>
        <%= form.label :name, style: "display: block" %>
        <%= form.text_field :name %>
      </div>

      <div>
        <%= form.label :email, style: "display: block" %>
        <%= form.text_field :email %>
      </div>

      <div>
        <%= form.submit %>
      </div>

    Türkçeleştirme için label ve buton yazılarını el ile vermemiz gerekiyor.

      <div>
        <%= form.label :name, style: "display: block", value: "İsim" %>
        <%= form.text_field :name %>
      </div>

      <div>
        <%= form.label :email, style: "display: block" %>
        <%= form.text_field :email %>
      </div>

      <div>
        <%= form.submit value: "Ekle" %>
      </div>

    Email için default Rails etiketini kullanmaya devam ediyoruz, sadece gönderme butonu ve Name etiketini değiştirdik. Dosyaları kaydedelim ve sayfayı yenileyelim.


    Bir isim ve email girerek Ekle butonuna tıkladığımızda uygulamamıza yeni bir kullanıcı eklenir ve kullanıcıyı gösteren /users/1 sayfasına otomatik yönlendirilir. 


    En üstte Rails tarafından otomatik üretilen ve kullanıcı eklemenin başarılı olduğuna dair bir bilgilendirme mesajı var. Sayfayı yenilersek bu mesaj bir daha görünmez, bir kerelik bilgilendirme. Bu sayfanın görseli de aynı dizinde show.html.erb dosyası.

    <p style="color: green"><%= notice %></p>

    <%= render @user %>

    <div>
      <%= link_to "Edit this user", edit_user_path(@user) %> |
      <%= link_to "Back to users", users_path %>

      <%= button_to "Destroy this user", @user, method: :delete %>
    </div>

    İşte o en üstteki satır , eğer bir bildirim varsa gösteriyor. Bu dosyada Türkçeleştirme işlemlerimizi yapalım.

    <p style="color: green"><%= notice %></p>

    <%= render @user %>

    <div>
      <%= link_to "Kullanıcıyı düzenle", edit_user_path(@user) %> |
      <%= link_to "Kullanıcılara geri dön", users_path %>

      <%= button_to "Kullanıcıyı sil!", @user, method: :delete %>
    </div>

    Bu koddaki 

    <%= render @user %>

    Satırı yine bir kısmi görsel olan _user.html.erb dosyasını içeriğe ekliyor. 

    <div id="<%= dom_id user %>">
      <p>
        <strong>Name:</strong>
        <%= user.name %>
      </p>

      <p>
        <strong>Email:</strong>
        <%= user.email %>
      </p>

    </div>

    Buradaki yazıları da Türkçeleştirelim.

    <div id="<%= dom_id user %>">
      <p>
        <strong>İsim:</strong>
        <%= user.name %>
      </p>

      <p>
        <strong>Email:</strong>
        <%= user.email %>
      </p>

    </div>

    Sadece Name yerine İsim yazdık. Sayfayı yenilersek.


    Kullanıcı bilgilerini değiştirmek istersek Kullanıcıyı düzenle linkine tıklarız ve sistem bizi edit sayfasına yani /users/1/edit adresine yönlendirir. 


    Hemen dikkatimizi çekti _form.html.erb kısmi görseli burada da kullanılmış, o yüzden form Türkçe etiketlerle geldi. Ama başka bir şey daha oldu, üzerinde Update user yazması gereken butonda Ekle yazıyor. Değişikliği kısmi görselde yaptık ama tüm Rails butonlarını etkiledi. Şimdi ilk önce _form.html.erb dosyasında buton için yaptığımız değişikliği geri alalım.

      <div>
        <%= form.submit %>
      </div>

    Rails'e butonların üzerinde default yazanları değiştirdiğimizi bildirmek için config/locales/en.yml dosyasına bir ekleme yapmamız gerekiyormuş. Başta dosyada şu kod var (yorum satırları hariç).

    en:
      hello: "Hello world"

    Şimdi buraya create ve update için default yazıları belirtelim.

    en:
      hello: "Hello world"
      helpers:
        submit:
          create: "Ekle"
          update: "Güncelle"


    Şimdi sayfayı yenilersek.


    Sayfa görselinin form harici kısmı edit.html.erb dosyasında.

    <% content_for :title, "Editing user" %>

    <h1>Editing user</h1>

    <%= render "form", user: @user %>

    <br>

    <div>
      <%= link_to "Show this user", @user %> |
      <%= link_to "Back to users", users_path %>
    </div>

    Burada da Türkçeleştirme işlemlerimizi yapalım.

    <% content_for :title, "Editing user" %>

    <h1>Kullanıcıyı düzenleyin</h1>

    <%= render "form", user: @user %>

    <br>

    <div>
      <%= link_to "Kullanıcıyı göster", @user %> |
      <%= link_to "Kullanıcılara dön", users_path %>
    </div>



    Güncelle butonu tıklanınca kullanıcı bilgisi güncellenerek tekrar show sayfasına geri dönülür.


    Şimdi Kullanıcılara geri dön linkine tıklayıp yen bir kullanıcı daha eklersek /users sayfamız şöyle bir liste gösterecek.


    Bu görsel çok sakil olmuş, eski versiyon Rails'lerde bari bir tablo şeklinde idi, ne sorunlar yaşadılarsa böyle değiştirmişler. İleride bu görseli daha yakışıklı yapmak için bir şeyler yapacağız inşallah. Şimdilik amacımız üzüm yemek, bağcıyı sonra döveriz. 

    Kullanıcı listesi, yeni kullanıcı ekleme, kullanıcı bilgilerini değiştirme ve gösterme işlerini bitirdik , şimdi geride bir kullanıcının silinmesi kaldı. Şu ikinci gereksiz kullanıcıyı silelim. İkinci kullanıcı altındaki Kullanıcıyı göster linkine tıklayalım ve show sayfasında kullanıcıyı görelim. En altta Kullanıcıyı sil! yazan bir buton var. Buna tıkladığımızda kullanıcı veri tabanından silinecek. Eskiden emin misin? diye sorardı ama Rails7 sormadan direk kaydı sildi ve /users sayfasına geri döndü. 


    Rails kaydı silmek için JavaScript kullanır, eğer tarayıcınızda JavaScript çalışmasını engellemişseniz bu noktada başarısız olunabilir. 




    MVC işleyişi

    Önceden MVC yapısı üzerinde durmuştuk. Şimdi /users sayfası için Rails'de MVC yapısının nasıl çalıştığına bakalım. 


    Gösterilen adımların işleyişi şöyle:

    1. Tarayıcı /users adresi için bir istekte bulunur.
    2. Rails yönlendirici isteği Users kontrolörü index aksiyonuna yönlendirir.
    3. index eylemi User modelinden tüm kayıtları (User.all) ister.
    4. User modeli veri tabanından tüm kullanıcıları çeker.
    5. User modeli topladığı kayıtları kontrolöre geri döner.
    6. Kontrolör kullanıcı listesi kayıtlarını @users değişkeninde toplar ve bunu index görseline gönderir.
    7. Görsel kodu embedded Ruby kullanarak görseli HTML kodunda yayınlar. 
    8. HTML kodu kontrolör tarafından tarayıcıya cevap olarak dönülür.


    Tarayıcıdan gelen istek nasıl doğru kontrolörün doğru eylemine gönderiliyor acaba? 

    Scaffold işlemi uygulama kodlarında bir ilave daha yapar. config/routes.rb dosyasını bir açalım.

    Rails.application.routes.draw do
      resources :users

    ...


    resources metodu ismi verilen users ana başlığındaki tüm MVC yönlendirmelerini yönlendirmelere ekliyor. Buradaki :users şeklinde sembol olarak değer girilmesi konusunda ileride yazarız nasipse. 

    Hazır routes.rb dosyasını açmışken uygulamamızın ana sayfasını da /users sayfası yapalım.

      root "application#merhaba"

    olan satırı

      root "users#index"

    yapalım.

    Kontrolör dosyamız app/controllers/users_controller.rb dosyası, içinde eylemlerimizin metod tanımları scaffold tarafından oluşturulmuş.

    class UsersController < ApplicationController
      .
    .
      def index
        ..
      end

      def show
      end

      def new
    ..
      end

      def edit
      end

      def create
    ..
      end

      def update
    ..
      end

      def destroy
    ..
      end

    end


    Dikkat edersek görsel sayfalarımızdan fazla eylem var. Daha önce index, show, new, ve edit eylemlerinin bize gösterdiği sayfalardan bahsetmiştik. Ancak burada create, update, ve destroy eylemleri de var. Bu eylemler sayfa yayınlamaz (isteseler yaparlar), sadece amaçları veri tabanında kullanıcı kayıtları üzerinde işlem yapmaktır. 

    Tüm bu eylemlerin toplamına Rails'de REST yapısı adı verilir. 

    HTTPrequest metod   URL         Eylem     Amacı
    ----------------------------------------------------------------
    GET               /users        index     kullanıcı listesi
    GET               /users/1      show      id 1 olan kullanıcı
    GET               /users/new    new       yeni kayıt ekleme formu
    POST              /users        create    yeni kayıt ekler
    GET               /users/1/edit edit      id 1 kaydı düzenle formu
    PATCH             /users/1      update    id 1 kaydı güncelle
    DELETE            /users/1      destroy   id 1 kaydı sil


    RESTful yönlendirme listesinde dikkatimizi aynı URL değerine yapılan isteklerin farklı eylem yapması çekiyor. Aralarındaki fark  HTTPRequest metodları, yakın zamanda göreceğiz nasipse. 

    Kontrolör çalışmasını anlamak için index eylemine bir bakalım. 

      # GET /users or /users.json
      def index
        @users = User.all
      end


    Konuya girmeden önce yorum satırı dikkatimi çekti ve adrese bir de /users.json yazdım, gelen cevap bir JSON veri oldu.


    Gelelim eyleme , bu eylem User modeline tüm kullanıcı kayıtlarını almak için başvuruyor. Gelen veriyi @users oluşum değişkeninde saklıyor. 

    User model sınıfı app/models/user.rb dosyasında tanımlı.

    class User < ApplicationRecord
    end


    User sınıfı ApplicationRecord sınıfından kalıtımla üretildiği için onda olan birçok yararlı özelliklere sahip. Bunlardan birisi de User.all metodu. Tüm kayıtları bu metod yardımıyla @users değişkenine aldıktan sonra kontrolör diyagramda gördüğümüz şekilde görsel dosyasını çağırır. Başında @ işareti olan oluşum değişkenleri görsel dosyalarından erişilebilir. Şu andaki görselimiz app/views/users dizinindeki index.html.erb dosyası. 

    <p style="color: green"><%= notice %></p>

    <% content_for :title, "Users" %>

    <h1>Kullanıcılar</h1>  

    <div id="users">
      <% @users.each do |user| %>
        <%= render user %>
        <p>
          <%= link_to "Kullanıcıyı göster", user %>  
        </p>
      <% end %>
    </div>

    <%= link_to "Kullanıcı ekle", new_user_path %>  


    Bu kodu şimdilik anlamamıza gerek yok ama kısaca, bir döngü içinde @users içinde gelen her kayıt için görseli oluşturur ve HTML'e dönüştürerek kontrolöre geri döner. Kontrolör de bu HTML kodu tarayıcıya geri döner.




    Users kaynaklarının zayıflıkları

    Şimdilik uygulamamız basit kalsın diye bazı dezavantajları gözardı ediyoruz ama bahsetmeden olmaz.

    • Veri doğrulaması yok - Veri tabanımız (User modelimiz) boş isimleri , geçersiz email adreslerini vs. hepsini kabul ediyor.
    • Yetkilendirme yok - Kullanıcının şifreli bir giriş yöntemi yok, yetki jısıtlaması yok, herkes her işe karışabilir.
    • Test yok - Bu aslında teknik olarak doğru değil , scaffolding temel testleri içerir. Ama üretilen testler veri doğrulamasını ve yetkiler gibi konuları içermez. 
    • Stil ve yerleşim yok - Web sitemizin bir görsel sitili ve yerleşim düzeni yok, çok yavan.


    Bunların hepsini anladığımızda zaten scaffolding'in neler yaptığını çok iyi biliyor olacağız. 



    Microposts Resource

    Users dosyalarını bitirdikten sonra ona bağlı olan Mıcroposts dosyalarına gelelim. Göreceğimiz üzere ikisi birbiri ile birçok benzerliğe sahip. Rails uygulamasının RESTful yapısını bu tekrarları yaparken daha iyi anlayacağız. 


    Micropost'larda bir Microtour

    Aynı Users gibi Microposts için de gereken dosyaları rails generate scaffold ile oluşturacağız. 

    $ rails generate scaffold Micropost content:text user_id:integer


    Hemen veri tabanı birleştirmesini yapalım

    $ rails db:migrate
    == 20250318193534 CreateMicroposts: migrating =================
    -- create_table(:microposts)
       -> 0.0123s
    == 20250318193534 CreateMicroposts: migrated (0.0128s) ========


    Tahmis edebileceğiniz gibi Rails yönlendirici microposts için yönlendirmeleri de config/routes.rb dosyasına eklemiştir.

    Rails.application.routes.draw do
      resources :microposts
      resources :users
    .....


    Bunun anlamı aynı users, users/new, users/1 gibi microposts, microposts/new, microposts/1 linkleri vs. de artık geçerli. Haydi bir inceleyelim. 


    Sırayla görsellere bir dalalım. Önce app/views/microposts/index.html.erb

    <p style="color: green"><%= notice %></p>

    <% content_for :title, "Microposts" %>

    <h1>Gönderiler</h1>

    <div id="microposts">
      <% @microposts.each do |micropost| %>
        <%= render micropost %>
        <p>
          <%= link_to "Gönderiyi göster", micropost %>
        </p>
      <% end %>
    </div>

    <%= link_to "Yeni gönderi", new_micropost_path %>


    Yeni gönderi linkine tıklayıp formu açalım. ilk değişklik  dosyamız app/views/microposts/new.html.erb

    <% content_for :title, "New micropost" %>

    <h1>Yeni gönderi</h1>

    <%= render "form", micropost: @micropost %>

    <br>

    <div>
      <%= link_to "Gönderilere dön", microposts_path %>
    </div>

    İkincisi form app/views/microposts/_form.html.erb

      <div>
        <%= form.label :content, style: "display: block", value: "İçerik" %>
        <%= form.text_area :content %>
      </div>

      <div>
        <%= form.label :user_id, style: "display: block", value: "Kullanıcı" %>
        <%= form.number_field :user_id %>
      </div>


    Şimdi yeni gönderi girebiliriz.


    Ekle deyip kaydettikten sonra show sayfasına gidecektir. Onun da görselini elden geçirelim. İlk önce app/views/microposts/show.html.erb

    <p style="color: green"><%= notice %></p>

    <%= render @micropost %>

    <div>
      <%= link_to "Gönderiyi düzenle", edit_micropost_path(@micropost) %> |
      <%= link_to "Gönderilere dön", microposts_path %>

      <%= button_to "Gönderiyi sil", @micropost, method: :delete %>
    </div>


    İkinci olarak app/views/microposts/show.html.erb

    <div id="<%= dom_id micropost %>">
      <p>
        <strong>İçerik:</strong>
        <%= micropost.content %>
      </p>

      <p>
        <strong>Kullanıcı:</strong>
        <%= micropost.user_id %>
      </p>

    </div>


    Kullanıcı id değeri olarak şu anda yegane kullanıcımızın id değeri olan 1 giriyoruz. Bir tane daha gönderi ekleyip gönderiler sayfasına geri dönelim.




    Mikro gönderileri mikro yapalım

    Bir mikro gönderinin mikro olması için boyutunun kısıtlanmış olması gerekir. Rails veri doğrulaması ile bunu yapmak çok kolay. Maksimum 140 karakter olan bir uzunluk doğrulaması yapalım. Modelimizin dosyası app/models/micropost.rb dosyasını açalım ve şu satırı ekleyelim.

    class Micropost < ApplicationRecord
      validates :content, length: { maximum: 140 }
    end


    Bu kod garip gelebilir, kısaca açıklayalım, ileride ayrıntılarına gireriz. Yeni bir gönderi eklemeye kalktığımızda formda içeriğe 140 karakterden fazla bir yazı yazmaya kalkarsak Rails bir hata mesajı ile bize yanlışımızı anlatır. 




    Bir kullanıcının birçok gönderisi olur

    Rails'in en güçlü özelliklerinden biri veri modelleri arasında bağlantıları takip edebilmesidir (associations). Bizim User modelimizi düşünürsek, her kullanıcının birçok gönderisi olabilir. Bu ilişkiyi User ve Micropost model dosyalarında şöyle değişiklik yaparak ifade ederiz. 

    class User < ApplicationRecord
      has_many :microposts
    end

    ve

    class Micropost < ApplicationRecord
      belongs_to :user
      validates :content, length: { maximum: 140 }
    end


    Bakar mısınız, Rails'çiler tekil ve çoğul kelime kullanımı konusunda zirve yapmışlar. Sanki konuşur gibi kod yazıyorsunuz. 

    Şimdi Rails modeller arasında ilişkiyi öğrendi. Hadi bir gönderinin kullanıcısını olmayan bir kullanıcı id değeri girelim bakalım ne oluyor. 


    Gördüğümüz gibi Rails öğrenmiş, olmayan kullanıcıya ait gönderi kabul edemem diyor. İlişkiyi görsel olarak ifade etmek gerekirse



    Bu verilerle biraz oynamak için Rails konsolu da kullanabiliriz. Rails konsolu Rails uygulaması ile bir konsol üzerinden iletişim kurmak ve denemeler yapmak için Ruby IRB gibi bir özellik. Konsolu çalıştırmak için 

    $ rails console

    Komutunu girmemiz yeterli. Şimdi konsolda bir şeyler deneyelim.

    Loading development environment (Rails 7.2.2)
    3.2.7 :001 > ilk_kullanıcı = User.first
      User Load (0.4ms)  SELECT "users".* FROM "users"
      ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
     =>
    #<User:0x00007f675a425a90
    ...
    -------------------------------------------------------------------

    3.2.7 :002 > ilk_kullanıcı
     =>
    #<User:0x00007f675a425a90
     id: 1,
     name: "Ümit Kayacık",
     email: "[FILTERED]",
     created_at: "2025-03-18 09:49:45.993673000 +0000",
     updated_at: "2025-03-18 09:49:45.993673000 +0000">
    -------------------------------------------------------------------

     3.2.7 :003 > ilk_kullanıcı.microposts
      Micropost Load (0.3ms)  SELECT "microposts".* FROM "microposts"
      WHERE "microposts"."user_id" = ? /* loading for pp */ LIMIT ?  
      [["user_id", 1], ["LIMIT", 11]]
     =>
    [#<Micropost:0x00007f6759423b88
      id: 1,
      content: "İlk gönderim.",
      user_id: 1,
      created_at: "2025-03-18 20:03:37.952906000 +0000",
      updated_at: "2025-03-18 20:03:37.952906000 +0000">,
     #<Micropost:0x00007f675a50cb20
      id: 2,
      content: "İkinci gönderim",
      user_id: 1,
      created_at: "2025-03-18 20:12:24.749035000 +0000",
      updated_at: "2025-03-18 20:12:24.749035000 +0000">]
      ----------------------------------------------------------------

      3.2.7 :004 > micropost = ilk_kullanıcı.microposts.first
      Micropost Load (0.3ms)  SELECT "microposts".* FROM "microposts"
      WHERE "microposts"."user_id" = ? ORDER BY "microposts"."id"
      ASC LIMIT ?  [["user_id", 1], ["LIMIT", 1]]
     =>
    #<Micropost:0x00007f6759ca2098
    ...

    3.2.7 :005 > micropost
     =>
    #<Micropost:0x00007f6759ca2098
     id: 1,
     content: "İlk gönderim.",
     user_id: 1,
     created_at: "2025-03-18 20:03:37.952906000 +0000",
     updated_at: "2025-03-18 20:03:37.952906000 +0000">
     ----------------------------------------------------------------

     3.2.7 :006 > micropost.user
     =>
    #<User:0x00007f675a425a90
     id: 1,
     name: "Ümit Kayacık",
     email: "[FILTERED]",
     created_at: "2025-03-18 09:49:45.993673000 +0000",
     updated_at: "2025-03-18 09:49:45.993673000 +0000">

    3.2.7 :007 > exit


    user.microposts kullanıcının gönderileri, micropost.user gönderinin kullanıcısı oluyor. Bunları ileride uygulama geliştirirken çok kullanacağız. 

    Yalnız Rails modellerinin SQL sorgularına bakarsak bize çok bilgiler veriyor. 




    Biraz daha veri doğrulama yapalım

    Nasıl gönderi boyutunun 140 karakterden uzun olmamasını sağladıysak , bir-iki doğrulama daha ekleyelim. Mesela gönderi boş olamasın, kullanıcı adı ya da email değeri de boş olmasın. User ve Micropost modellerine bu ilaveleri yapalım.

    class User < ApplicationRecord
      has_many :microposts

      validates :name, presence: true
      validates :email, presence: true
    end

    ve Micropost modeli

    class Micropost < ApplicationRecord
      belongs_to :user
      validates :content, length: { maximum: 140 },
        presence: true
    end

    Yes, işte bu, artık boş kutu olmayacak. 




    Kalıtım hiyerarşisi

    Rails'deki kontrolör ve model hiyerarşilerine bir kısa bakışla bu bölümü bitirelim. 

    User modeli ve Micropost modeli kendiside ActiveRecord::Base sınıfından türetilmiş olan ApplicationRecord sınıfından türetilmiştir. 

    class Micropost < ApplicationRecord

    Bu sayede model nesnelerimiz veri tabanındaki tablolara erişmek ve sütunları Ruby öznitelikleri gibi kullanma vs. kabiliyetlerine sahip olur. 


    Kontrolör kalıtım hiyerarşisi de modellere benzer. User ve Micropost kontrolörleri de ApplicationController sınıfından türetilmiştir.

    class MicropostsController < ApplicationController

    ApplicationController de  ActionController::Base sınıfından türetilmiştir. 

    class ApplicationController < ActionController::Base


    Modellerde olduğu gibi kontrolörlerde de esas sınıftan (burada ActionController::Base) birçok yetenek vardır. Örneğin model nesnelerini kullanmak, HTTP isteklerini analiz edip görselleri HTTP olarak isteklere geri dönmek. 




    Sonuç olarak

    Bu basit uygulamamızın sonuna geldik. Uygulamamızın güçlü ve zaayıf yönleri var.


    Güçlü yönleri:

    • Rails temellerine yukarıdan bir bakış
    • MVC yapısını biraz anlamak
    • REST mimarisi hakkında ön bilgi
    • Veri modellemesine ön bakış
    • Gerçek bir veri tabanına dayalı uygulama geliştirmek


    Zayıf yönleri:

    • Kendi yerleşim ve stillerimizi uygulamadık
    • Veriler harici , statik bir sayfamız yok ("Ana Sayfa" veya "Hakkımızda" gibi)
    • Kullanıcı şifreleri yok
    • Kullanıcı resmi yok
    • Kullanıcı giriş ekranı yok
    • Güvenlik yok
    • Kullanıcı-gönderiler arasında otomatik ilişkilendirme yok
    • Takip ediliyor ya da takip edildi gibi kavramlar yok
    • Anlamlı testleri yok
    • Tam olarak anlaşılma yok


    Ne çok zayıf yönler varmış. Ama merak etmeyin ilerledikçe uygulamalarımızda zayıflıklar azalıp güçlü yönler artacak.



    Bu bölümde öğrendiklerimiz

    • Scaffolding sayesinde veri modelleri ve web üzerinden verilere erişim için gereken tüm temel dosyalar üretiliyor.
    • Scaffolding hızlı başlangıç için iyi , ancak anlayarak devam etmek için kötü bir işlem.
    • Rails web uygulamaları yaparken e Model-View-Controller (MVC) mimarisini kullanıyor.
    • Rails tarafından yorumlanan REST mimarisi , bir standart set url değerine ve veri modelleri ile çalışan kontrolör eylemlerine sahip.
    • Rails, veri modellerinde değerler için doğrulamalar yapabilme özelliklerine sahip.
    • Rails veri modelleri arasında ilişkileri tanımlayabileceğimiz hazır metodlar içeriyor.
    • Rails console sayesinde Rails uygulamamızın veri tabanı ile konsol üzerinde kod denemeleri yapabiliyoruz. 



    Bu sayfayı burada kapatalım. Sonraki sayfada biraz statik sayfalar, biraz yerleşim ve görseller üzerinde çalışacağız. Şimdilik kalın sağlıcakla..










    Hiç yorum yok:

    Yorum Gönder