Önceki bölümü okumadan buraya geldiyseniz hiç kasmayın geri dönün
- ORTA SEVİYE BİR RAİLS TUTORIAL - 1 (Kurulum, ilk stiller)
Gönderiler
Artık blog özelliğini eklemeye başlayabiliriz. Uygulamamızın amacı aynı fikirde olan insanları bir araya getirmek olduğundan, bu mesajların yazarlarının tanımlanması gerekiyor. Bunun için kullanıcı yetkilendirme sistemi gerekiyor (authentication).
Kullanıcı Yetkilendirmesi
Kullanıcı yetkilendirme sistemi kurmak için Devise gem kullanacağız. Kendi kendimize de yetkilendirme sistemi kurabiliriz ama bu çok vakit ve kod alacaktır. Bu kolay bir yol ve Rails topluluğu tarafından çok kullanılıyor.
İlk adım Gemfile içine eklemek.
gem "devise"
sonra aktif hale getirmek için şu komutları girelim.
bundle
rails g devise:install
Şimdi devise jeneratörü kullanarak bir User modeli oluşturalım.
rails g devise User
Yeni modelimizi veritabanına ekleyelim.
rails db:migrate
Bu kadarıyla yetkilendirme sistemi hazır. Devise metodları ile yeni kullanıcı ekleyebilir, kullanıcıları düzenleyebiliriz. Şu anda uygulamada tanımlı linklerin listesine bakarsak bir hayli link eklendiğini göreceğiz.
rails routes
Şimdi server’ı çalıştırıp bu linklerden birkaçını deneyelim. http://localhost:3000/users/sign_in adresine gidelim ve kullanıcı girişi sayfasını görelim.
Eğer http://localhost:3000/users/sign_up sayfasına gidersek de bir yeni kullanıcı kaydı sayfası görürüz. Fakat
views
klasörüne gittiğimizde Devise kontrolorüne ait görsellerin bulunduğu düzenleyebileceğimiz bir klasör yok. Devise dökümanlarını incelediğimizde görselleri modifiye edebilmek için ilk önce jeneratör ile devise görsellerini oluşturmamız gerekiyor.
rails g devise:views
Şimdi views
klasörüne baktığımızda Devise görsellerinin toplandığı klasörü görürüz. Şimdi giriş ve kayıt sayfalarını görmek istediğimiz gibi düzenleyebiliriz. Kullanıcı girişi sayfası ile başlayacağız, çünkü kayıt sayfasında User modeline ilave bilgi ekleyeceğiz.
Login sayfası
app/views/devise/sessions/new.html.erb
dosyasını açalım. Sadece bir form genel olarak dikkatimizi çeker. Rails’in form_for
metodu ile bu form üretilmiştir. Form stilini Bootstrap stiline göre değiştireceğiz. Dosyanın içeriğini şu hale getirelim:
app/views/devise/sessions/new.html.erb
<%= bootstrap_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> <%= f.email_field :email, autofocus: true, class: "form-control", placeholder: "email" %> <%= f.password_field :password, label: "Şifre", autocomplete: "off", class: "form-control", placeholder: "password" %> <% if devise_mapping.rememberable? %> <%= f.check_box :remember_me, label: "Beni hatırla" %> <% end %> <%= f.submit "Giriş yap", class: "form-control login-button" %> <% end %>
Eğer http://localhost:3000/users/sign_in adresine gidersek bir metod bulunamadı hatası alırız.
undefined method 'bootstrap_form_for
Bootstrap formlarını kullanmak için Rails’e bootstrap_form gem eklemeliyiz.
Gemfile
açın ve şunu ekleyin:
gem "bootstrap_form"
Sonra da tabiki konsoldabundle
Şu anda login sayfası şuna benziyor:Formun da Bootstrap içinde olması için etrafını stillerle çevirmeliyiz.
app/views/devise/sessions/new.html.erb
<div class="container"> <div class="row"> <div class="col-sm-6 col-sm-offset-3"> <h2 class="text-center">Log in</h2> <!-- önceki içeriği buraya kopyalayın --> </div> </div> </div>
Formun genişliği 12 lik grid alanının 6 kolonluk kısmı, başına da 3 kolon ofset verilmiş. Cep telefonu gibi küçük ekranlarda form tüm genişliği kaplayacaktır.
Biraz route düzenlemesi yapalım. Kullanıcı giriş sayfasına
users/sign_in
adresi yerine /login
adresiyle girsek daha derli toplu olacak. İlk önce kullanıcı girişi yapmak için kullanılan aksiyonun nerede olduğunu bilmeliyiz. Devise kontrolörleri gem’in kendisi içinde saklanmıştır. Devise dökümanlarına göre devise_scope
metodu ile route değiştirmesi yapabiliriz.
config/routes.rb
Rails.application.routes.draw do devise_for :users root to: "pages#index" devise_scope :user do get "login", to: "devise/sessions#new" end end
Artık http://localhost:3000/login adresine giderek kullanıcı giriş sayfasını açabiliriz. Şimdilik login sayfasını böyle bırakalım ve yeni kullanıcı kaydı sayfasına geçelim.
Signup sayfası
Eğer http://localhost:3000/users/sign_up sayfasına gidersek default yeni kullanıcı sayfasını görürüz. Daha önce dediğimiz gibi yeni kayıt sayfasında ilave yapacaktık. Standart devise bilgilerin yanında kullanıcı ismini de kaydetmek istiyoruz.
users
tablosuna :name
sütunu ekleyeceğiz.
db/migrate
klasörüne gidelim ve içinde şu anda yegane dosya olan *ÜretimTarihi*_devise_create_users.rb
gibi ismi olan dosyayı açalım. change
metodu içindeki create_table
bloğunun içine en başa t.string :name, null: false, default: ""
satırını ekleyelim. Şimdi tabloyu tekrar üretmek için konsolda:
rails db:drop:_unsafe
rails db:migrate
Tabloya yeni sütunu ekledik. Şimdi bunu kontrolöre eklemeli. Devise kontrolörlerinde değişiklik yapmak için devise jeneratörü kullanarak kontrolörleri üretebiliriz ya da sadece değiştirmek istediğimiz kontrolör ve metodlara ait dosyalar yapabiliriz. Biz 2. yoldan gideceğiz. app/controllers
klasörüne gidelim ve registrations_controller.rb
adında yeni bir dosya ekleyip içine şu kodu yazalım:
app/controllers/registrations_cotroller.rb
class RegistrationsController < Devise::RegistrationsController private def sign_up_params params.require(:user).permit( :name, :email, :password, :password_confirmation) end def account_update_params params.require(:user).permit( :name, :email, :password, :password_confirmation, :current_password) end end
Bu kod :name parametresini de içereren yeni metodları orjinalde üretilmiş olan
sign_up_params
ve account_update_params
metodlarının üzerine yazar.
routes.rb
dosyasında tanımlamamız gerekiyor.
devise_for :users
satırını şöyle değiştirelim:devise_for :users, :controllers => {:registrations => "registrations"}
Artık new.html.erb
dosyasında :name alanını ekleyebiliriz.
app/views/devise/registrations/new.html.erb
<%= bootstrap_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> <%= f.text_field :name, placeholder: "username (herkesin göreceği isim)", class: "form-control", label: "İsim" %> <%= f.text_field :email, placeholder: "email", class: "form-control" %> <%= f.password_field :password, placeholder: "password", class: "form-control", label: "Şifre" %> <%= f.password_field :password_confirmation, placeholder: "password doğrulama", class: "form-control", label: "Şifre (tekrar)" %> <%= f.submit "Kayıt ol", class: "btn sign-up-btn" %> <% end %> <%= render "devise/shared/links" %>
Şimdi bu formu da login formunda olduğu gibi Bootstrap grid sistem içine alalım.
app/views/devise/registrations/new.html.erb
<div class="container" id="sign-up-form"> <div class="row"> <h1>Aynı amaçlı insanlarla görüşün</h1> <h3>Birlikte amaçlar belirleyin, çalışın, başarıya ulaşın</h3> <div class="col-sm-4 col-sm-offset-4"> <h3>Kayıt olun <small> bedava!</small></h3> <!-- önceki içeriği buraya kopyalayın --> </div> </div> </div>
Aynı login sayfasında olduğu gibi
user/sign_up
yerine bu syfaya /signup
adresi yazarak girebilmek için config/routes.rb
dosyasına ilave yapalım.
config/routes.rb
Rails.application.routes.draw do devise_for :users, :controllers => {:registrations => "registrations"} root to: "pages#index" devise_scope :user do get "login", to: "devise/sessions#new" get "signup", to: "devise/registrations#new" end end
Devam etmeden biraz stil düzenlemesi yapalım.
app/assets/stylesheets/partials
klasörüne signup.scss
isimli bir dosya ekleyelim ve içine şu kodu yazalım:
app/assets/stylesheets/partials/signup.scss
#sign-up-form { margin-top: 100px; h1 { font-size: 36px !important; font-size: 3.6rem !important; } text-align: center; padding-bottom: 20px; }
application.scss
dosyası içine @import "partials/layout/*"
satırının hemen üzerine tüm partials
klasörü içini de dahil edelim.
app/assets/stylesheets/application.scss
... // Parça dosyalar @import "partials/*"; @import "partials/layout/*";
Tüm sitenin görüntüsünü etkileyecek birkaç stil daha ekleyelim.
app/assets/stylesheets/base
klasörü içine default.scss
adında bir dosya ekleyelim ve içine şu kodu yazalım:
app/assets/stylesheets/base/default.scss
* { box-sizing: border-box; } html { font-size: 62.5%; } body { background: $backgroundColor; font-size: 14px; font-size: 1.4rem; } h1 { font-size: 24px; font-size: 2.4rem; } i { width: 26px; } ul { list-style-type: none; } a:hover, a:active, a:link, a:visited { text-decoration: none; } .control-label { display: none; }
Burada
$backgroundColor
adında bir değişken kullandık ama daha önce tanımlamadık. Değişkenleri koymak için yazdığımız variables.scss
dosyasına şu satırı ekleyelim.
$backgroundColor: #f0f0f0;
Şimdi default.scss
dosyasını da application.scss
içinde import edelim.
app/assets/stylesheets/application.scss
... // Değişkenler @import "base/variables"; // Default stiller @import "base/default"; ...
Gezinti bar düzenleme
Artık 3 sayfamız var, ana sayfa, login ve signup sayfaları. Bunlar arasında geçiş yapabilmek için
_navigation.html.erb
parça görseline linkler ekleyelim.
.container
bloğu içindeki yapı şuna benzeyecek:
<div class="row"> <!-- Her zaman görünen elemanlar --> <div class="col-sm-7"> ... </div> <!-- Küçük ekranlarda otomatik gizlenecek elemanlar --> <div class="col-sm-5"> ... </div> </div>
Böyle devam edersek çarşı karışacak. Şu yukarıdaki iki bölümü ayrı dosyalara alalım ki hakimiyeti kaybetmeyelim.
app/views/layouts
klasörü altında navigation
adında yeni bir klasör oluşturalım ve içinde _header.html.erb
dosyasını oluşturarak _navigation.html.erb
içindeki tüm .navbar-header
bölümünü bu dosya içine taşılayalım. Yine aynı yere _collapsible_elements.html.erb
dosyası üretip içine tüm .navbar-collapse
bölümünü taşıyalım.
_navigation.html.erb
dosyasını şu hale geitrelim:
app/views/layouts/_navigation.html.erb
<nav class="navbar navbar-default navbar-fixed-top"> <div class="container"> <div class="row"> <!-- Her zaman görünen elemanlar --> <div class="col-sm-7"> <%= render "layouts/navigation/header" %> </div> <!-- Küçük ekranlarda otomatik gizlenecek elemanlar --> <div class="col-sm-5"> <%= render "layouts/navigation/collapsible_elements" %> </div> </div> </div><!-- /.container --> </nav>
Şimdi http://localhost:3000/ adresine gidersek bir değişiklik olmadı ama sadece kodumuzu biraz temizledik ve ileride yapacağımız ilavelere hazırladık.
_collapsible_elements.html.erb
dosyasını şu hale getirelim:
app/views/layouts/navigation/_collapsible_elements.html.erb
<div class="collapse navbar-collapse navbar-right" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <% if user_signed_in? %> <li class="dropdown pc-menu"> <a id="user-settings" class="dropdown-toggle" data-toggle="dropdown" href="#"> <span id="user-name"><%= current_user.name %></span> <span class="caret"></span> </a> <ul class="dropdown-menu" role="menu"> <li><%= link_to "Profili düzenle", edit_user_registration_path %></li> <li><%= link_to "Çıkış yap", destroy_user_session_path, method: :delete %></li> </ul> </li> <li class="mobile-menu"> <%= link_to "Profili düzenle", edit_user_registration_path %> </li> <li class="mobile-menu"> <%= link_to "Çıkış yap", destroy_user_session_path, method: :delete %> </li> <% else # kullanıcı giriş yapmamış %> <li><%= link_to "Login", login_path %></li> <li><%= link_to "Signup", signup_path %></li> <% end %> </ul> </div><!-- /.navbar-collapse -->
Burada aynı şeylerden bazen iki kopya konmuş birine
pc-menu
diğerine mobile-menu
CSS sınıfı verilmiş. Bunun amacı farklı ekran boyutlarındaki görünümü değiştirmek. Şimdi bu sınıflara ait stiller ekleyelim. app/assets/stylesheets
klasörü altında responsive
adında bir klasör ekleyelim ve içine desktop.scss
ve mobile.scss
adında iki stil dosyası ekleyelim.
app/assets/stylesheets/respnsive/desktop.scss
@media screen and (min-width: 767px) { .mobile-menu { display: none !important; } }
app/assets/stylesheets/respnsive/mobile.scss
@media screen and (max-width: 767px) { .pc-menu { display: none !important; } }
Şimdi bu stilleri
application.scss
içinde import edelim.
...
// Ekrana göre görünüm seçimleri
@import "responsive/*";
app/assets/stylesheets/partials/layout/navigation.scss
dosyasında nav
elemanı bloğunun içine şunu ekleyelim:
.col-sm-5, .col-sm-7 { padding: 0; }
Dosyanın en altına da şunları ekleyelim:
.pc-menu { margin-right: 10px; } .mobile-menu { i { color: white; } ul { padding: 0px; } a { display: block; padding: 10px 0px 10px 25px !important; } a:hover { background: white !important; color: black !important; i { color: black; } } } .icon-bar { background-color: white !important; } .active a { background: $navbarColor !important; border-bottom: solid 5px white; } .dropdown-toggle, .dropdown-menu { background: $navbarColor !important; border: none; } .dropdown-menu a:hover { color: black !important; background: white !important; }
Şu anda uygulamamızın giriş yapılmamış görüntüsü şöyle olacak:
Giriş yapılmış hali de şuna benzeyecek:
Küçük ekranlarda da şöyle olacak:
Yardımcılar
_collapsible_elements.html.erb
dosyasında bulunan bir kısım yönetim programını görsel dosyası içinden çıkaracağız. app
klasörüne bakarsak içinde bir de helpers
adında klasör var. Görsel dosyasında bulunan lojik kısmı bu klasör içine koyacağız.
helpers
klasörüne gidip navigation_helper.rb
adında bir dosya ekleyelim.
app/helpers/navigation_helper.rb
Helper dosyaları içinde yardımcılar modüller olarak tanımlanır. Şu modülü tanımlayarak başlayalım:
app/helpers/navigation_helper.rb
module NavigationHelper end
Default olarak Rails tüm görsellere ait yardımcı dosyalarını yükler ve her yerde kullanılabilir. Fakat bu farklı yardımcı dosyaları içinde bulunabilecek benzer isimli metodlarda çakışmaya sebep olabilir. İlk önce bu default davranışı engelleyelim. Bunun için
config/application.rb
içinde Application
sınıf tanımı içine şu satırı ekleyelim.
config.action_controller.include_all_helpers = false
Artık yardımcılar sadece ilgili kontrolörün görsellerinde kullanılabilir. Yani PagesController
varsa pages_helper.rb
tüm görseller içinden pages
klasörü içindeki görsellerde kullanılabilir.
NavigationHelper
ama bir NavigationController
yok. O zaman bu yardımcıya hiç bir yerden erişilemeyecek. Erişilebilir yapmak için NavigationHelper
modülünü ApplicationHelper
modülü içine include
metodu ile enjekte ederiz.
app/helpers/application_helper.rb
module ApplicationHelper include NavigationHelper end
Artık
NavigationHelper
modülü içindeki metodlara tüm uygulama genelinde erişilebilir.
_collapsible_elements.html.erb
dosyasına. Dosyayı editörde açalım. if else bloğu içindeki iki bölümü parça dosyalara alacağız. Dosyanın bulunduğu navigation
klasörü altında collapsible_elements
adında bir alt klasör tanımlayalım.
app/views/layouts/navigation/collapsible_elements
Klasör içine iki yeni dosya ekleyelim, _signed_in_links.html.erb
(giriş yapmış kullanıcıların linkleri için) ve _non_signed_in_links.html.erb
(giriş yapılmadan önceki linkler için). Şimdi _collapsible_elements.html.erb
dosyası içinden ilgili kısımları kesip bu dosyalara taşıyalım. Dosyalar şu hale gelecek:
app/views/layouts/navigation/collapsible_elements/_signed_in_links.html.erb
<li class="dropdown pc-menu"> <a id="user-settings" class="dropdown-toggle" data-toggle="dropdown" href="#"> <span id="user-name"><%= current_user.name %></span> <span class="caret"></span> </a> <ul class="dropdown-menu" role="menu"> <li><%= link_to "Profili düzenle", edit_user_registration_path %></li> <li><%= link_to "Çıkış yap", destroy_user_session_path, method: :delete %></li> </ul> </li> <li class="mobile-menu"> <%= link_to "Profili düzenle", edit_user_registration_path %> </li> <li class="mobile-menu"> <%= link_to "Çıkış yap", destroy_user_session_path, method: :delete %> </li>
app/views/layouts/navigation/collapsible_elements/_non_signed_in_links.html.erb
<li><%= link_to "Login", login_path %></li> <li><%= link_to "Signup", signup_path %></li>
Şimdi
_collapsible_elements.html.erb
dosyası içinde bulunan if else bloğu yerine collapsible_links_partial_path
yardımcı metodunu render
metoduyla çağıralım.
app/views/layouts/navigation/_collapsible_elements.html.erb
<div class="collapse navbar-collapse navbar-right" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <%= render collapsible_links_partial_path %> </ul> </div><!-- /.navbar-collapse -->
Sıra geldi
NavigationHelper
içine metodumuzu eklemeye:
app/helpers/navigation_helper.rb
module NavigationHelper def collapsible_links_partial_path if user_signed_in? "layouts/navigation/collapsible_elements/signed_in_links" else "layouts/navigation/collapsible_elements/non_signed_in_links" end end end
Böylece ilk yardımcımızı tanımlamış olduk. Bundan sonra mümkün olduğu kadar bu yolla görsellerin içinden lojiği ayıracağız.
Geldik bir bölümün daha sonuna. Bu uygulama için yapacağımız daha çok şey var. Bir süre sonra makyajlara hız vereceğiz. Sonraki bölümde görüşmek üzere kalın sağlıcakla..
Sırada şunlar var:
- ORTA SEVİYE BİR RAİLS TUTORIAL - 3 (Blog altyapısı)
- ORTA SEVİYE BİR RAİLS TUTORIAL - 4 (JavaScript stiller)
- ORTA SEVİYE BİR RAİLS TUTORIAL - 5 (Kolleksiyon sayfaları)
- ORTA SEVİYE BİR RAİLS TUTORIAL - 6 (Ana sayfa güncellemesi)
- ORTA SEVİYE BİR RAİLS TUTORIAL - 7 (Anlık mesajlaşma ilavesi)
Hiç yorum yok:
Yorum Gönder