184: Formtastic Bölüm 1 (view original Railscast)
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.
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.
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.
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.
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.
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, 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.
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.
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.

