Ö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