3 Mart 2015 Salı

Rails 2015 B2

www.railstutorial.org adresinden 2. bölüm.

Bu sefer Rails özelliklerini tanımak için bir oyuncak uygulama. Kullanıcıların mikro gönderiler yazdığı bir site, minicik twitter.

rails new komutu kullanarak uygulamamızı üretelim (Cloud 9 üzerinde uygulama geliştirme hakkında önceki bölümü okuyabilirsiniz) :
$ rails _4.2.0_ new toy_app
$ cd toy_app/
Ve uygulama dosyalarımız otomatik olarak üretildikten sonra gemfile içeriğini kullanacağımız gem listesine göre değiştiriyoruz (toy_app/Gemfile):
source 'https://rubygems.org'

gem 'rails',        '4.2.0'
gem 'sass-rails',   '5.0.1'
gem 'uglifier',     '2.5.3'
gem 'coffee-rails', '4.1.0'
gem 'jquery-rails', '4.0.3'
gem 'turbolinks',   '2.3.0'
gem 'jbuilder',     '2.2.3'
gem 'sdoc',         '0.4.0', group: :doc

group :development, :test do
  gem 'sqlite3',     '1.3.9'
  gem 'byebug',      '3.4.0'
  gem 'web-console', '2.0.0.beta3'
  gem 'spring',      '1.1.3'
end

group :production do
  gem 'pg',             '0.17.1'
  gem 'rails_12factor', '0.0.2'
end

Geliştirme esnasında kullanmayacağımız production grubu gemler hariç yüklemek için komut satırında:
$ bundle install --without production
yazarak gereken gemlerin yüklenmesini sağlıyoruz.

Şimdi, ilk modelimiz (veri tablomuz) kullanıcılar için, "users" modelinin tamsayı bir id sütunu, string bir name sütunu ve yine string bir email sütunu var:
İkinci modelimiz ise mikro gönderiler için, "microposts" modelinin de tamsayı bir id sütunu var, gönderinin yer aldığı text bir content sütunu var, ve son olarak mikro gönderiyi yazan kullanıcının "users" modelindeki id değerini içeren tamsayı bir user_id sütunu var:

Rails'in en güzel yanlarından biri scaffolding ile kullanıcılar modelimizi oluşturuyoruz:
$ rails generate scaffold User name:string email:string
      invoke  active_record
      create    db/migrate/20140821011110_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml
      invoke  resource_route
       route    resources :users
      invoke  scaffold_controller
      create    app/controllers/users_controller.rb
      invoke    erb
      create      app/views/users
      create      app/views/users/index.html.erb
      create      app/views/users/edit.html.erb
      create      app/views/users/show.html.erb
      create      app/views/users/new.html.erb
      create      app/views/users/_form.html.erb
      invoke    test_unit
      create      test/controllers/users_controller_test.rb
      invoke    helper
      create      app/helpers/users_helper.rb
      invoke      test_unit
      create        test/helpers/users_helper_test.rb
      invoke    jbuilder
      create      app/views/users/index.json.jbuilder
      create      app/views/users/show.json.jbuilder
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/users.js.coffee
      invoke    scss
      create      app/assets/stylesheets/users.css.scss
      invoke  scss
      create    app/assets/stylesheets/scaffolds.css.scss
id sütunu zaten her modele otomatik eklenmekte, string olan name ve email sütunlarını da biz komut satırında tanımlıyoruz. Gördüğünüz gibi scaffolding gereken tüm dosyaları otomatik olarak oluşturdu. Modelimizin veri tabanına birleştirilmesi için migrate işlemi yapıyoruz:
$ bundle exec rake db:migrate
==  CreateUsers: migrating ====================================================
-- create_table(:users)
   -> 0.0017s
==  CreateUsers: migrated (0.0018s) ===========================================
 Şimdi server'ı çalıştırıp bir bakalım:
$ rails server -b $IP -p $PORT    # Eğer Cloud9 değil kendi PCnizdeyseniz `rails server` yeterli
MVC yapıda kullanıcılar için üretilen sayfaların değişik görevleri var. Bunlara bir göz atalım:
URLActionAmacı
/usersindextüm kullanıcıları listeleyen sayfa
/users/1showid'si 1 olan kullanıcıyı gösteren sayfa
/users/newnewyeni bir kullanıcı belirlemek için sayfa
/users/1/editeditid'si 1 olan kullanıcının bilgilerini düzenleme sayfası 
uygulamamızın root sayfasını kullanıcı listesine yönlendirmek için config/routes.rb dosyasına şu satırları ekleyelim:
Rails.application.routes.draw do
  resources :users
  root 'users#index'
  .
  .
  .
end
Artık uygulamamız Rails karşılama sayfasını değil , kullanıcı listesi sayfasını ana sayfa olarak göstermeye başlayacaktır.

MVC (Model View Controller) yapının Controller tarafında ise app/controllers/users_controller.rb dosyası var:
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
Gördüğünüz gibi modelimiz üzerinde yapılacak her işlem için bir sayfa olduğu gibi hepsine karşılık gelen metodlar tanımlanmış. Sayfaların dışında create, update ve destroy metodları var bunlar bir sayfa yayınlamıyor, sadece model üzerinde işlem yapıyorlar.

Bu metodların her birinin bir HTTP request karşılığı var:
HTTP requestURLActionAmaç
GET/usersindextüm kullanıcıları listeler
GET/users/1showid'si 1 olan kullanıcıyı gösterir
GET/users/newnewyeni kullanıcı tanımlama sayfasını açar
POST/userscreateyeni kullanıcıyı kaydeder
GET/users/1/editeditid'si 1 olan kullanıcı bilgileri düzenleme sayfasını açar
PATCH/users/1updateid'si 1 olan kullanıcının bilgilerini değiştirir
DELETE/users/1destroyid'si 1 olan kullanıcı kaydını siler

Users controller ve User model arasındaki ilişkiyi anlamak için
class UsersController < ApplicationController
  .
  .
  .
  def index
    @users = User.all
  end
  .
  .
  .
end
index metodu tüm kullanıcıları veri tabanından sorgular ve @users değişkenine yerleştirir. MVC'nin V'si yani view ile de bu bilgi index sayfasında yayınlanır. app/views/users/index.html.erb dosyasına bakalım:
<h1>Listing users</h1>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Email</th>
      <th colspan="3"></th>
    </tr>
  </thead>

<% @users.each do |user| %>
  <tr>
    <td><%= user.name %></td>
    <td><%= user.email %></td>
    <td><%= link_to 'Show', user %></td>
    <td><%= link_to 'Edit', edit_user_path(user) %></td>
    <td><%= link_to 'Destroy', user, method: :delete,
                                     data: { confirm: 'Are you sure?' } %></td>
  </tr>
<% end %>
</table>

<br>

<%= link_to 'New User', new_user_path %>
İşte bu dosya da @users değişkenindeki verileri bir tablo halinde HTML'e dönüştürür.

İyi güzel de bu User kaynaklarında zayıf noktalar var:

  1. Veri doğrulaması yok = Boş bir isim girilebilir ya da uyduruk bir email girilmiş olabilir.
  2. Şifre koruması yok
  3. Testleri yok = Scaffolding basit testleri üretir ama veri doğrulaması gibi ayrıntılara test hazırlamaz.
  4. Stil ya da yerleşim dosyaları yok
  5. Anlaşılabilirlik yok = Eğer scaffolding'in ürettiği kodları anlayabiliyorsanız zaten bu kitabı okumanıza gerek kalmamıştır.

Sıra geldi mikro gönderilere, önce Micropost kaynaklarını üretelim:
$ rails generate scaffold Micropost content:text user_id:integer
      invoke  active_record
      create    db/migrate/20140821012832_create_microposts.rb
      create    app/models/micropost.rb
      invoke    test_unit
      create      test/models/micropost_test.rb
      create      test/fixtures/microposts.yml
      invoke  resource_route
       route    resources :microposts
      invoke  scaffold_controller
      create    app/controllers/microposts_controller.rb
      invoke    erb
      create      app/views/microposts
      create      app/views/microposts/index.html.erb
      create      app/views/microposts/edit.html.erb
      create      app/views/microposts/show.html.erb
      create      app/views/microposts/new.html.erb
      create      app/views/microposts/_form.html.erb
      invoke    test_unit
      create      test/controllers/microposts_controller_test.rb
      invoke    helper
      create      app/helpers/microposts_helper.rb
      invoke      test_unit
      create        test/helpers/microposts_helper_test.rb
      invoke    jbuilder
      create      app/views/microposts/index.json.jbuilder
      create      app/views/microposts/show.json.jbuilder
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/microposts.js.coffee
      invoke    scss
      create      app/assets/stylesheets/microposts.css.scss
      invoke  scss
   identical    app/assets/stylesheets/scaffolds.css.scss
ardından veritabanında değişikliklerimizi migrate ile uygulayalım:
$ bundle exec rake db:migrate
==  CreateMicroposts: migrating ===============================================
-- create_table(:microposts)
   -> 0.0023s
==  CreateMicroposts: migrated (0.0026s) ======================================
Aynı User kaynaklarında olduğu gibi gereken dosyalarımız otomatik olarak üretildi. Birkaç yeni kullanıcı tanımlayalım, sonra da ilk mikrogönderimizi tanımlayalım:

Mikrogönderinin mikro olmasını sağlamak için, 140 karakterle sınırlayalım (Twitter stayl) app/models/micropost.rb:
class Micropost < ActiveRecord::Base
  validates :content, length: { maximum: 140 }
end

Biraz İngilizce bilenler kod satırından ne iş yaptığını anlayabilir. Şimdi 140 karakterden uzun bir gönderi yazarsanız kayıt girilmeyip hata mesajı dönecektir.

Bu Rails'i icat edenlerin biraz değişik insanlar olduğuna bir kanıt da modeller arası ilişki tanımlamaları. Mesela bir kullanıcının birçok gönderisi olabilir app/models/user.rb:
class User < ActiveRecord::Base
  has_many :microposts
end
ve bir gönderi tek bir kullanıcıya aittir app/models/micropost.rb:
class Micropost < ActiveRecord::Base
  belongs_to :user
  validates :content, length: { maximum: 140 }
end
Nasıl? nerdeyse saf İngilizce cümleler. Şimdi biraz da Rails Konsol ile modellerimize bakalım:
$ rails console
>> first_user = User.first
=> #<User id: 1, name: "Ümit Kayacık", email: "ujk7107@gmail.com",
created_at: "2015-02-27 21:05:37", updated_at: "2015-02-27 21:05:37">
>> first_user.microposts
=> [#<Micropost id: 1, content: "İlk mikro gönderi", user_id: 1, created_at:
"2015-02-27 21:25:48", updated_at: "2015-02-27 21:25:48">, #<Micropost id: 2, 
content: "İkinci gönderi", user_id: 1, created_at: "2015-02-27 21:26:28", 
updated_at: "2015-02-27 21:26:28">]
>> micropost = first_user.microposts.first    # Micropost.first yazsanız da olurdu.
=> #<Micropost id: 1, content: "İlk mikro gönderi", user_id: 1, created_at:
"2015-02-27 21:25:48", updated_at: "2015-02-27 21:25:48">
>> micropost.user
=> #<User id: 1, name: "Ümit Kayacık", email: "ujk7107@gmail.com",
created_at: "2015-02-27 21:05:37", updated_at: "2015-02-27 21:05:37">
>> exit


Bu uygulamada tanımladığımız iki modelimiz de ActiveRecord::Base nesnesinden türetilmiş olduğu için bu nesnenin tüm özelliklerini artı bizim model tanımına eklediğimiz özellikleri içerir:
class Micropost < ActiveRecord::Base
  belongs_to :user
  validates :content, length: { maximum: 140 }
end
hiyerarşi şu şekildedir:

Kontrolör hiyerarşisi biraz daha karmaşıktır. Önce ActionController::Base   sınıfından  ApplicationController  sınıfı üretilir ve bu sınıftan uygulamamızın modellerine ait kontrolörler üretilir. Bu sayede ApplicationController üzerinde yapacağımız tüm modifikasyonlar diğer modellerin kontrolörlerinde ortak olarak kullanılacaktır:


Eh bişeyler daha öğrenirken sizede anlatmaya çalıştım , ama uygulamalar hala çok zayıf, daha bir sürü eksik var:

  • Yerleşim ve stiller yok
  • Statik tanımlı sayfalar yok ("Ana Sayfa" veya "Hakkında" gibi)
  • Kullanıcı şifresi yok
  • Kullanıcı profil resmi yok
  • Şifreli giriş yok
  • Güvenlik sıfır
  • Kullanıcı ile gönderisini otomatik bağlama yok
  • "follow"lama yok
  • Mikrogönderi "feed" yok
  • Bişey ifade edecek testleri yok
  • Şu anda programcıya bişey ifade etse de kullanıcı açısından hiçbir şey değil



Hiç yorum yok:

Yorum Gönder