Ö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)
- ORTA SEVİYE BİR RAİLS TUTORIAL - 2 (Kullanıcı girişi - Bootstrap CSS)
- 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ı)
Ana sayfa güncellemesi
Hali hazırda ana sayfada birkaç rastgele gönderi görebiliyoruz. Tüm kolleksiyonlardan birkaç gönderi gösterebilmek için ana sayfayı değiştirelim.
_main_content.html.erb dosyasının içeriğini şöyle değiştirelim:
app/views/pages/index/_main_content.html.erb
<div id="main-content" class="col-sm-9"> <h3 class="page-name"><%= link_to "Hobi Arkadaşı", hobby_posts_path %></h3> <div class="row"> <%= render @hobby_posts %> <%= render no_posts_partial_path(@hobby_posts) %> </div><!-- row --> <h3 class="page-name"><%= link_to "Çalışma Arkadaşı", study_posts_path %></h3> <div class="row"> <%= render @study_posts %> <%= render no_posts_partial_path(@study_posts) %> </div><!-- row --> <h3 class="page-name"><%= link_to "Takım Arkadaşı", team_posts_path %></h3> <div class="row"> <%= render @team_posts %> <%= render no_posts_partial_path(@team_posts) %> </div><!-- row --> </div><!-- ana içerik -->
Her kolleksiyondan gönderilerin olduğu bölümler oluşturduk.
Oluşum değişkenlerini
PagesController in index aksiyonunda tanımlayalım. Aksiyonu şöyle yapalım:
app/controllers/pages_controller.rb
def index @hobby_posts = Post.by_branch("hobby").limit( 8 ) @study_posts = Post.by_branch("study").limit( 8 ) @team_posts = Post.by_branch("team").limit( 8 ) end
Daha önce
no_posts_partial_path yardımcı metodunu tanımlamıştık. Fakat üzerinde biraz değişiklik yapmamız gerekiyor. Şu anda sadece kolleksiyon sayfalarına göre çalışıyor. Metoda bir posts parametresi ekleyelim:
app/helpers/posts_helper.rb
def no_posts_partial_path(posts) posts.empty? ? "posts/shared/no_posts" : "shared/empty_partial" end
Burada
posts parametresini tanımladık, oluşum değişkenini basit değişken ile değiştirdik. Parça dosyayı daha mantıklı bir yere taşıyoruz çünkü şu anda sadece kolleksiyonlarda kullanılmıyor.
posts/branch/_no_posts.html.erb
dosyasını
posts/shared/_no_posts.html.erb
adresine taşıyalım.
Daha önce
no_posts_partial_path metodunu kullandığımız _branch.html.erb dosyasında metoda parametre olarak @posts oluşum değişkenini verelim.
Bazı stil değişiklikleri için
default.scss dosyasına şunları ekleyelim:
app/assets/stylesheets/base/default.scss
.container {
padding: 0;
}
.row {
margin: 0;
}
Ayrıca
home_page.scss içine şunları ekleyelim:
app/assets/stylesheets/partials/home_page.scss
.page-name { margin: 15px 0 15px 0; text-align: center; background-color: white !important; font-weight: bold; a { color: black; } a:hover { text-decoration: underline; } }
Servis nesneleri
Daha önce belirttiğimiz gibi eğer kontrolör içine lojik koyarsanız kolayca ortalık karışabilir ve testler çok sıkıntılı olabilir. Bu yüzden lojiği kontrolör dışında bir yerlere almak faydalı olacaktır. Bu amaçla servis nesneleri (servisler) kullanabiliriz.
PostsController içinde şöyle bir get_posts metodumuz vardı:def get_posts branch = params[:action] search = params[:search] category = params[:category] if category.blank? && search.blank? posts = Post.by_branch(branch).all elsif category.blank? && search.present? posts = Post.by_branch(branch).search(search) elsif category.present? && search.blank? posts = Post.by_category(branch, category) elsif category.present? && search.present? posts = Post.by_category(branch, category).search(search) else end end
Bu metodda çok fazla servislere aktarılacak lojik var. Servisler Ruby sınıfları gibidir. Tanımlanmış bir metodu çağırırız ve dönen değeri kullanırız. Ruby’de sınıfın üreteci olan
initialize metodu parametreler ile çağırarak sınıf üretiriz. Daha sonra tüm lojiği işleyecek bir metod tanımlarız. Uygulamalı yaparak kod içinde nasıl göründüğüne bakalım.
app klasörü altında services adında bir alt klasör oluşturalım.
app/services
Klasör içinde yeni bir posts_for_branch_service.rb dosyası tanımlayarak içine şu kodu yazalım:
app/services/posts_for_branch_service.rb
class PostsForBranchService def initialize(params) @search = params[:search] @category = params[:category] @branch = params[:branch] end # isteğe uygun gönderileri getir def call if @category.blank? && @search.blank? posts = Post.by_branch(@branch).all elsif @category.blank? && @search.present? posts = Post.by_branch(@branch).search(@search) elsif @category.present? && @search.blank? posts = Post.by_category(@branch, @category) elsif @category.present? && @search.present? posts = Post.by_category(@branch, @category).search(@search) else end end end
Görüldüğü üzere
initialize metodunda parametreleri alıyor ve başka metodda kullanılacağı için oluşum değişkeni olarak kaydediyoruz. Sonra call metodu içinde daha öncesinde kontrolörde yazdığımız get_posts metodunun lojiğini aynen işliyoruz. Şimdi get_posts metoduna geri dönelim ve içeriğini şöyle değiştirelim:
app/controllers/posts_controller.rb
...
def get_posts
PostsForBranchService.new({
search: params[:search],
category: params[:category],
branch: params[:action]
}).call
end
...
Peki Rails nereden bilecek bu sınıfı? Default olarak Rails
app klasörü altındaki tüm sınıf tanımlarını başlangıçta yükler. Server’ı tekrar başlatmamız yeterli olacaktır.
Yeni gönderi oluşturmak
Şimdiye kadarki gönderiler seed ile üretilmiş yapay gönderilerdi. Kullanıcının yeni gönderiler girmesi için gereken arabirimi hazırlayalım artık.
posts_controller.rb dosyasında new ve create aksiyonlarına ihtiyacımız var. Bunları tanımlayalım (tabi ki private bölümü dışında):
app/controllers/posts_controller.rb
...
def new
@branch = params[:branch]
@categories = Category.where(branch: @branch)
@post = Post.new
end
def create
@post = Post.new(post_params)
if @post.save
redirect_to post_path(@post)
else
redirect_to root_path
end
end
...
new aksiyonu içinde formda kullanılmak üzere yeni gönderi oluşturmak amaçlı oluşum değişkenlerini belirliyoruz. @categories oluşum değişkeninde o kolleksiyona ait kategorilerin listesi bulunuyor. @post oluşum değişkeni ise formda yeni bir gönderi oluşturmak için bir yeni Post nesnesi bulunuyor.
create aksiyonu ise form doldurulup gönderilince yeni gönderiyi post_params metodu ile oluşturarak kaydını yapıyor. Şimdi post_params metodunu private bölümüne ekleyelim:
app/controllers/posts_controller.rb
... private ... def post_params params.require(:post). permit(:content, :title, :category_id). merge(user_id: current_user.id) end ...
permit metodu sayesinde sadece belirtilen parametreler form gönderiminden alınır, gerisine izin verilmez.
PostsController en üst satıra şunu ekleyelim:
app/controllers/posts_controller.rb
class PostsController < ApplicationController before_action :redirect_if_not_signed_in, only: [:new] ...
before_action Rails filtrelerinden biridir. Burada kullanıcı girişi yapmamış ziyaretçilerin yeni gönderi oluşturmasına engel oluyoruz. Buradaki satırın anlamı new aksiyonuna gitmeden önce redirect_if_not_signed_in metodu çağırılacak. Tahmin edersiniz ki bu metod uygulamada başka yerlerde de gerekecektir mutlaka. O yüzden metodu application_controller.rb içine ekleyelim:
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base protect_from_forgery with: :exception def redirect_if_not_signed_in redirect_to root_path if !user_signed_in? end def redirect_if_signed_in redirect_to root_path if user_signed_in? end end
Giriş yapmamış kullanıcılar ana sayfaya yönlendirilecek. Ayrıca nasıl olsa lazım olur diyerek giriş yapmış kullanıcıları ana sayfaya yönlendiren bir metod daha ekledik.
Sıra geldi görsel kalıp dosyamıza.
app/views/posts klasöründe new.html.erb kalıp dosyasını tanımlayıp içine şunları yazalım:
app/views/posts/new.html.erb
<div class="container new-post"> <div class="row"> <div class="col-sm-6 col-sm-offset-3"> <h1>Yeni gönderi oluşturun</h1> <%= render "posts/new/post_form" %> </div> </div> </div>
Parça görsel için
new klasörünü ve içine _post_form.html.erb dosyasını tanımlayarak içine şunları yazalım:
app/views/posts/new/_post_form.html.erb
<%= bootstrap_form_for(@post) do |f| %> <%= f.text_field :title, label: "Başlık", maxlength: 100, placeholder: "Başlık", class: "form-control", required: true, minlength: 5 %> <%= f.hidden_field :branch, :value => @branch %> <%= f.text_area :content, label: "İçerik", rows: 6, required: true, minlength: 20, maxlength: 1000, placeholder: "Neler aradığınızı yazın. Örn. özel ilgiler, uzmanlık seviyesi vs.", class: "form-control" %> <%= f.collection_select :category_id, @categories, :id, :name, class: "form-control", label: "Kategori" %> <%= f.submit "Gönderi oluşturun", class: "form-control" %> <% end %>
Bu kodda yeni olan tek şey
collection_select bize bir dropdown list tanımlıyor. Kısaca şöyle, category_id parametresine @categories oluşum değişkenine koyduğumuz kolleksiyona ait kategorilerden birini id sini kullanıcı seçimime göre koyuyor.
Şimdi
new görsel kalıbı için biraz stil tanımlayalım. app/assets/stylesheets/partials/posts klasöründe new.scss dosyası tanımlayalım ve içine şunları yazalım:
app/assets/stylesheets/partials/posts/new.scss
.new-post { height: calc(100vh - 50px); background-color: white; h1 { text-align: center; margin: 25px 0; } input, text-area, select { width: 100%; } }
Yeni gönderi oluşturma formu şuna benzedi:
Son olarak tüm alanların doğru doldurulduğundan emin olmak için bazı doğrulamalar yapalım.
Post modeli içine şunları ekleyelim:
app/models/post.rb
...
validates :title,
presence: true,
length: { minimum: 5, maximum: 255 }
validates :content,
presence: true,
length: { minimum: 20, maximum: 1000 }
validates :category, presence: true
...
Bu bölümde anlatılacaklar da bu kadar. Gelecek bölümde yeni bir özellik ile uygulamamızı genişleteceğiz. Kullanıcılara anında mesajlaşma özelliği sağlayacağız. Şimdilik kalın sağlıcakla..
Sırada şunlar var:
- ORTA SEVİYE BİR RAİLS TUTORIAL - 7 (Anlık mesajlaşma ilavesi)



Hiç yorum yok:
Yorum Gönder