homeASCIIcasts

184: Formtastic Bölüm 1  (view original Railscast)

Other translations: En

Written by Onur Ferhat

Formların view kodunu yazmayı uzun ve sıkıcı buluyorsanız, bunu yapmak için daha kısa bir yol sağlayan Formtastic adlı bir gem’in olduğunu öğrenmek sizi sevindirecektir. Bununla, bu bölümde göstereceğimiz gibi nispeten ufak bir kodla oldukça karmaşık formlar oluşturulabiliyor.

Veteriner Uygulamasını Oluşturma

Formtastic’e başlamadan önce, kullanabileceğiniz bir TextMate paketinden bahsetmek yerinde olacaktır. Bu paket, form oluşturmayı daha da kolaylaştırabilecek birçok yararlı kod parçacığı sağlamaktadır.

Formtastic’i tanıtmak için yeni bir Rails uygulaması oluşturacağız. Bu uygulama bir veterinerin ameliyathanesindeki hasta hayvanların takibini yapacak, bu yüzden ona vet adını veriyoruz ve normal yolla uygulamayı oluşturuyoruz.

rails vet

Formtastic bir gem olarak sağlanmaktadır. Uygulamamızın /config/environment.rb dosyasına aşağıdaki satırı ekleyerek onu uygulamamıza dahil edebiliriz. (TextMate kullanıyorsanız ve Formtastic paketini yüklediyseniz ftgem ve <TAB> tuşlarını kısayol olarak kullanabilirsiniz).

config.gem 'justinfrench-formtastic', :lib => 'formtastic', :source => 'http://gems.github.com'

Gem’in yüklendiğinden emin olmak için şu komutu çalıştırmamız yeterlidir:

  sudo rake gems:install
  

Böylece uygulamamızı yazmaya başlamak için hazırız.

Uygulamamızın parçalarını yazmayı kolaylaştırmak için, Ryan Bates’in nifty oluşturucularının bazılarından yararlanacağız. İlk önce nifty_layout oluşturucusunu kullanarak bir yerleşim (layout) dosyası ve bir stil sayfası oluşturacağız.

  script/generate nifty_layout
  

Daha sonra, nifty_scaffold oluşturucusundan yararlanarak ilk model’imizi ve ona eşlik edecek bir controller’ı ve view’ları oluşturacağız. Hayvanlarımızı kategorilere göre ayıracağız, bu nedenle model’imize Category adını vereceğiz ve name ile description öğeleri ekleyeceğiz.

  script/generate nifty_scaffold category name:string description:text
  

Şimdi veritabanımızın geçişini yapabiliriz.

rake db:migrate

Yeni uygulamamızı başlatır ve yeni kategori sayfasına gidersek scaffold (iskelet oluşturma sistemi) tarafından oluşturulan view kodunu göreceğiz.

Varsayılan Yeni Kategori sayfası.

Scaffold tarafından yukarıdaki form için oluşturulan kod aşağıdaki gibidir:

  <% form_for @category do |f| %>
    <%= f.error_messages %>
    <p>

      <%= f.label :name %><br />
      <%= f.text_field :name %>
    </p>
    <p>
      <%= f.label :description %><br />

      <%= f.text_area :description, :rows => 5 %>
    </p>
    <p><%= f.submit "Submit" %></p>
  <% end %>
  

Bu normal Rails form kodudur; bir form_for ile başlar ve formdaki her alan kendi etiketiyle birlikte ayrı ayrı tanımlanır. En sonda, yeni bir kategori eklememizi sağlayan bir gönder düğmesi bulunmaktadır.

Formtastic bu standart form metodlarının hiçbirini geçersiz kılmaz, böylece bunları bir Formtastic formunda da kullanabiliriz. Yukarıdaki formda bulunan form_for öğesini Formtastic’in semantic_form_for öğesiyle değiştirseydik form hala aynı şekilde çalışırdı. Ama bunu yapmak anlamsız olurdu, çünkü asıl kolaylık Formtastic’in form metodlarını kullandığımızda ortaya çıkar. Onları kullanarak, formumuzu aşağıdaki gibi yapabiliriz:

  <% semantic_form_for @category do |f| %>
   <%= f.inputs %>
   <%= f.buttons %>
  <% end %>
  

inputs metodu bir model’in tüm giriş alanlarını oluşturmak için kullanışlı bir yoldur ve aynı şekilde buttons metodu bir gönder düğmesi oluşturur. Formu şimdi yeniden yüklersek biraz farklı görünecektir.

Formtastic kodu kullanan Yeni Kategori sayfası.

Bu form artık Formtastic’in metodları kullanılarak gösterilmektedir. İlk görülen farklılık; scaffold’un oluşturduğu formda alanların arasında paragraf etiketleri kullanılırken, Formtastic’in giriş alanlarını düğmeden ayırmak için sıralı listeleri ve fieldset etiketlerini kullanmasıdır.

Form şu andaki haliyle pek güzel görünmüyor, ancak biraz CSS uygulayarak bunu halledebiliriz. Formtastic, bu işi kendi kendimize yapmak zorunda kalmamak için kullanabileceğimiz bazı stil sayfalarıyla birlikte gelir. Şunu çalıştırırsak:

  script/generate formtastic_stylesheets
  

uygulamamızın /public/stylesheets dizininde iki yeni stil sayfası oluşturulur ve ardından bu stil sayfalarını yerleşim dosyamıza ekleyebiliriz. Yerleşimimizin "head" bölümünde zaten bir stil sayfasını eklemiş durumdayız.

  <head>
    <title><%= h(yield(:title) || "Untitled") %></title>
    <%= stylesheet_link_tag 'application' %>
    <%= yield(:head) %>
  </head>
  

Formtastic stil sayfalarını buraya ekleyerek onları uygulamamızdaki her sayfaya dahil edebiliriz.

  <%= stylesheet_link_tag 'application', 'formtastic', 'formtastic_changes' %>
  

İkinci dosya, formtastic_changes, diğer stil sayfasındaki varsayılan stillerde yapmak istediğimiz değişiklikleri yapmamız gereken yerdir. Artık birden çok stil sayfamız olduğu için, Rails’in önbelleğe alma seçeneğinden yararlanmalıyız. Böylece uygulama production (üretim) modunda çalıştırıldığında dosyalar tek bir dosyada birleştirilir. (Bu birden çok JavaScript dosyası için de geçerlidir.)

  <%= stylesheet_link_tag 'application', 'formtastic', 'formtastic_changes', :cache => 'base' %>
  

Önbelleğe almayı bu şekilde kullanmak; üç stil sayfası dosyası base.css adlı bir dosyada birleştirileceğinden, sayfa yüklenirken daha az sayıda dosyanın sunucudan isteneceği anlamına gelir.

Şimdi formu yeniden yüklersek biraz daha iyi görünecektir, ancak hala görünmesi gerektiği gibi değil.

Formun yerleşimi pek düzgün değil.

Bu, Formtastic’in stil sayfasındaki birkaç satır nedeniyledir.

  html[xmlns] form.formtastic fieldset { display: block; }

  html[xmlns] form.formtastic fieldset ol li { display: block; }
  

Yukarıdaki iki CSS seçicisi (selector) sayfaların açılış <html> etiketinin bir xmlns özniteliğine sahip olmasını beklemektedir. nifty_layout oluşturucusu tarafından oluşturulan yerleşim dosyasındaki etikette bu yoktur, bu nedenle formun olması gerektiği gibi görünmesi için bunu eklememiz gerekecektir.

  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  

Şimdi formu yeniden yüklediğimizde metin kutularının beklediğimiz gibi hizalandığını görebiliriz. Formun olması gerektiği gibi görünmesini sağladığımıza göre, köpekler için bir tane ve kediler için bir tane olmak üzere bir çift kategori ekleyebiliriz. Bunları birazdan hayvanların kendileri için formu oluştururken kullanacağız.

İlk kategorimizi ekliyoruz.

Daha Karmaşık Bir Örnek

Şimdi hayvanlar için olan formla devam edeceğiz. Kategorilerde yaptığımız gibi bir scaffold oluşturarak başlayacağız.

  script/generate nifty_scaffold animal name:string category_id:integer born_on:date female:boolean
  

Animal model’inde name, born_on ve female öğelerinin yanısıra bir category_id olacak, böylece her hayvanı bir Category içine yerleştirebileceğiz. Scaffold’u oluşturduktan sonra, yeni tablonun veritabanında oluşturulması için veritabanımızın geçişini yapacağız.

  rake db:migrate
  

Sonraki adım model’ler arasındaki ilişkiyi kurarak bir hayvanın bir kategoriye ait olmasını…

  class Animal < ActiveRecord::Base
    attr_accessible :name, :category_id, :born_on, :female
    belongs_to :category
  end
  

…ve bir kategoride birden fazla hayvan olmasını sağlamak.

  class Category < ActiveRecord::Base
    attr_accessible :name, :description
    has_many :animals
  end
  

Scaffold tarafından oluşturulan form aşağıda gösteriliyor. Bunu biraz Formtastic koduyla değiştirmek istiyoruz.

Varsayılan Yeni Hayvan sayfası.

Kategori formunda yaptığımız gibi varsayılan form_for kodunu bir Formtastic semantic_form_for formuyla değiştireceğiz.

  <% semantic_form_for @animal do |f| %>
    <% f.inputs do %>
      <%= f.input :name %>
      <%= f.input :born_on %>
      <%= f.input :category %>
      <%= f.input :female %>
    <% end %>
    <%= f.buttons %>
  <% end %>
  

Az sonra form alanlarımızı özelleştireceğimiz için bu defa onların üzerinde biraz daha fazla kontrolümüzün olmasını istiyoruz. Bu nedenle f.inputs metoduna, alanları birer birer tanımlamak için input metodunu kullandığımız bir blok parametresi verdik. Bloğu kapattıktan sonra önceden yaptığımız gibi f.buttons metodunu kullanarak gönder düğmesini ekleyebiliriz.

Formu şimdi yeniden yüklersek Formtastic tarafından oluşturulan alanları görürüz.

Formtastic kontrolleri içeren Yeni Hayvan sayfası.

Formtastic, Animal model’inin özelliklerinin veri türlerine bağlı olarak uygun form alanlarını oluşturdu. Burada göremiyor olsanız da, category_id alanının bir ilişki olduğunu anlayıp kategori açılır kutusunu önceden eklediğimiz iki kategoriyle doldurdu bile.

Bu formda yapmak istediğimiz birkaç değişiklik var. Varsayılan olarak, tarih alanının yıl kısmı şu anki yılın 5 yıl öncesiyle 5 yıl sonrasının arasındakileri içeriyor. Bizimse bundan daha önceki yılları göstermemiz gerekiyor. Ayrıca, category açılır kutusundan boş seçeneği kaldırmak ve female alanını bir onay kutusu yerine bir çift radyo düğmesi olarak göstermek istiyoruz.

Rails’in form yardımcı metodlarına verdiğimiz seçeneklerin aynılarını kullanarak alanları özelleştirebiliriz. Yani, born_on alanına :start_year parametresi verebilir ve kategorimizdeki boş seçeneği kaldırmak için:include_blank => false parametresini kullanabiliriz.

  <% semantic_form_for @animal do |f| %>
    <% f.inputs do %>
      <%= f.input :name %>
      <%= f.input :born_on, :start_year => 1900 %>
      <%= f.input :category, :include_blank => false %>
      <%= f.input :female, :as => :radio %>
    <% end %>
    <%= f.buttons %>
  <% end %>
  

female form öğesinin türünü değiştireceğimiz için, bu alana biraz farklı davranmamız gerekiyor. Varsayılandan farklı bir alan türü belirtmek için, Formtastic’in bir :as parametresi bulunuyor. Türü radyo düğmesine çevirmek için :as => :radio parametresini kullanabiliriz.

Forma şimdi yeniden göz atarsak, yaptığımız değişikliklerin yansıtıldığını; tarihlerin 1900’den başladığını, kategoriden boş seçeneğin kaldırıldığını ve cinsiyet onay kutusunun iki radyo düğmesiyle değiştirildiğini göreceğiz.

Cinsiyet alanı artık radyo düğmeleriyle gösteriliyor.

Radyo düğmeleri onay kutusuna göre daha iyi oldu, ancak “yes” (evet) ve “no” (hayır) yazması yerine, alanın etiketinin “Gender” (Cinsiyet) olmasını ve radyo düğmelerinin “Male” (Erkek) ve “Female” (Dişi) olarak etiketlendirilmesini istiyoruz. Formtastic bu derecede bir özelleştirmeye izin veriyor mu? Evet, izin veriyor. Etiketin ve radyo düğmelerinin değerlerini belirlemek için :label (etiket) ve :collection (koleksiyon) seçeneklerini kullanabiliriz.

  <%= f.input :female, :as => :radio, :label => "Gender", :collection => [["Male", false], ["Female", true]] %>
  

Adından anlaşılacağı gibi, :label seçeneği etiketin adını belirlerken, :collection seçeneği her bir radyo düğmesinin adını ve değerini belirten, dizilerden oluşan bir diziyi parametre olarak alır.

Form artık tam istediğimiz gibi görünüyor.

Radyo düğmesinin üzerindeki etiketlerde bizim istediğimiz metin görünüyor.

Formumuz artık tamamlandı ve istediğimiz kadar yeni hayvan oluşturmak için onu kullanabiliriz.

Sonraki Adımlar

Formtastic’le birlikte nispeten daha az view koduyla oldukça karmaşık bir formu başarıyla oluşturduk, özelleştirme seçeneklerini kullanarak bazı alanları ihtiyacımıza göre değiştirdik. Yine de hala işlemediğimiz Formtastic özellikleri olduğundan, bir sonraki bölümde daha ayrıntıya gireceğiz.