Nginx ve Passenger Kurulumu – Ubuntu ve Debian

Nginx ve Passenger Kurulumu

Nginx ve passenger kurulumu ile ilgili internette pek çok İngilizce döküman bulunuyor ancak bunların pek çoğu resmi Passenger dökümanında anlatılan yolların dışında yöntemler kullanmışlar. Bunları uygulayıp, ne gibi zorluklara yol açtığını gördüğüm için, Passenger ve Nginx’in tüm dökümanlarını baştan okuyup bu yazıyı hazırladım. Öncelikle sisteminizde Ruby ve Rails kurulu değilse rbenv aracını kullanarak kurulumu yapmanız gerekiyor.

Passenger tarafından Ubuntu ve Debian için official APT reposu sağlanmakta. Bu repoyu kullandığınızda hem kurulumu kolayca yapabilirsiniz hemde güncelleştirmeleri kolayca takip edebilirsiniz. Aşağıda anlatacağım adımları takip ettiğiniz taktirde passenger-install-apache2-module veya passenger-install-nginx-module araçlarını kullanmanıza gerek kalmayacaktır.

İlk olarak PGP anahtarını sisteminize ekleyin:

Passenger reposu HTTPS’ten bağlantı kurduğu için sisteminize HTTPS desteğini kurun:

/etc/apt/sources.list.d/ klasörü altında passenger.list isminde bir dosya oluşturun ve kurulumu yapmak istediğiniz işletim sistemine uygun olarak aşağıdaki satırlardan sadece bir tanesini! ekleyin:

passenger.list dosyasının izinlerini düzenleyin ve paket listenizi güncelleyin:

Nginx paketlerini kurun:

Daha sonra, /etc/nginx/nginx.conf dosyasını düzenleyerek, passenger_root ve passenger_ruby değişkenlerini uncomment edin.

Önerdiğim şekilde Ruby kurulumunu rbenv aracı ile yaptıysanız, bu iki değişken şu şekilde olacaktır:

Nginx’i restart edin:

Şuan herşey yolundaysa nginx çalışıyor olmalıdır.

Passenger’ın çalışması için yapmamız gereken bir kaç şey kaldı:

Hepsi bu kadar. Şuan nginx ve passenger sorunsuz çalışıyor olmalı.

Nginx konfigürasyonu şurada bulunur:

Nginx hata logları şurada bulunur:

Deploy işlemleri ve Nginx konfigürasyonunu bir sonraki yazıda anlatacağım.

Rbenv ile Ruby ve Rails Kurulumu – Debian 7

Rbenv Kurulumu

Rbenv, RVM gibi ancak RVM’ye göre çok daha basit bir şekilde, birden çok Ruby versiyonunu birlikte kullanmak için geliştirilmiş bir araçtır. Sisteminizde tek bir Ruby sürümüne ihtiyaç duyuyorsanız dahi, rbenv ile kurulum yapmanızı öneririm.

Öncelikle rbenv’i /home/foo altına klonlayın:

Daha sonra PATH’e, rbenv değişkenlerini ekleyin:

Ruby sürümleri ve diğer şeyler için otomatik tamamlamayı etkinleştiren aşağıdaki komutu çalıştırın:

Terminalinizi yeniden başlatın. Daha sonra;

komutunu çalıştırdığınızda:

çıktısını görüyorsanız kurulum başarıyla tamamlanmış demektir.

Rbenv’in ruby-build eklentisini kurarak, Ruby kurulumu için ortamı hazır edelim:

Rbenv’in çalışma mantığı gereği, herhangi bir GEM kurduktan sonra her seferinde “rbenv rehash” komutunu çalıştırmamız gerekiyor. Ancak bu can sıkıcı bir iş olduğu için, bunun içinde bir eklenti yazmışlar. Bunu da sistemimize çekelim:

Rbenv kurulum işlemleri bu kadar. Şimdi Ruby’yi kuralım.

Ruby Kurulumu

Ruby için gerekli temel paketleri kurun:

Rbenv’de listelenen Ruby sürümlerine bakın:

Bunlardan kurmak istediğiniz sürümü kendiniz seçebilirsiniz. Ben bu yazının yazıldığı tarihteki en kararlı sürüm olan Ruby 2.1.5’i kullanacağım:

Herşey yolundaysa sisteminize Ruby kurulmuş olmalıdır. Rbenv ile, kurulan bu Ruby sürümünü ister sistem çapında, istersenizde uygulama çapında kullanabilirsiniz.

Sistem çapında bu sürümü kullanmak için:

Uygulama çapında kullanmak için, uygulamanızın olduğu dizine düştükten sonra, o dizin içerisinde:

komutlarını kullanabilirsiniz.

Kurulumu kontrol edin:

Rails Kurulumu

Rails kurulumunda özel bir durum bulunmamaktadır. GEM olarak kurmanız yeterlidir:

Kurulumunuz başarıyla tamamlandıysa “rails -v” komutu ile kurulmuş olan Rails sürümünü görebiliyor olmanız gerekir.

Debian için OpenJDK Kurulumu

Kaynak listenize openjdk’yı ekleyin:

Daha sonra:

Debian’da herşey yolundaysa “java -version” çıktısı şöyle birşey olacaktır:

Debian ve Ubuntu – ElasticSearch Kurulumu

ElasticSearch kurulumu yapabilmek için öncelikle sisteminizde OpenJDK kurulu olmalıdır. Kurulum için: http://www.serhatdundar.com/debian-icin-openjdk-kurulumu

OpenJDK’yı kurduktan sonra ElasticSearch kurulumuna geçebilirsiniz.

Öncelikle GPG anahtarını ekleyin:

Aşağıda ki satırı /etc/apt/sources.list dosyanıza ekleyin:

Kurulumu gerçekleştirin:

Sistem başladığında elasticsearch hizmetinin de otomatik olarak başlamasını istiyorsanız:

veya manuel olarak elasticsearch’ü başlatmak için;

Şuan herşey yolundaysa ElasticSearch çalışıyor olmalıdır. Rails uygulamalarınızda ElasticSearch ile arama yapabilmek için modelinizde ElasticSearch’ü include etmeniz gerekir. Örneğin “User” modelimize bunu include edelim:

Ardından, arama yapacağınız controller action’unda (çoğunlukla index) ElasticSearch’ü çağırmanız gerekmektedir:

Rails console’dan elasticsearch’ün çalışıp çalışmadığına aşağıdaki şekilde bakabilirsiniz;

Herşey yolundaysa status olarak green dönecektir. Elasticsearch çalışıyor ancak performans sorunları varsa yellow dönecektir.

Bonus: View Tarafı:

TurEng Konsol Uygulaması

Konsolda çalışırken bir kelimenin İngilizce’sine bakmak için web tarayıcıya geçmekten sıkıldığım için ve tureng sözlük uygulamasının konsoldan çalışabilen ufak bir betik halini yazdım:

https://github.com/msdundar/tureng

Bu uygulama kısaca, tureng sözlük’ten ilgili kelimeyi aratıyor ve dönen sayfaları Nokogiri ile parse ediyor. Daha sonra parse ettiği sonuçları ise “text-table” ile tablolayarak tekrar konsola basıyor. TurEng bizlere bir API sunmadığı için böyle bir yola başvurdum.

Görüntüsü şöyle =>

687474703a2f2f692e696d6775722e636f6d2f6b674f48656f462e706e67

Daha sonra betiği Ruby Türkiye grubunda paylaştığımda Yusuf Yalım ve Ahmet Kapıkıran‘da projeyi forklayarak bir takım katkılar (cümle çevirileri gibi) sağladı.

Son olarak Uğur Özyılmazel ise betiği GEM’leştirerek daha stabil bir sürümünü paylaştı.

ile kurabilir ve aşağıdaki örneklerdeki gibi kullanabilirsiniz:

Yapmak istediğiniz değişiklikler için vigo/tureng’i forklayıp daha sonra pull request yapabilirsiniz.

Güle güle kullanın.

Rails – N+1 Sorguları ve Çözümü

Veritabanınızda 5 tane “exam_center” kaydı olduğunu varsayalım.

ve aşağıda ki gibi bir model yapınız olduğu;

Bu exam_center’ların tamamını bir index sayfasında göstermek istediğinizde, her bir exam_center için 1 tane country, 1 tanede city sorgusu yapılacaktır. Yani her bir kayıt için view’dan çağırdığınız ilişki sayısı kadar sorgu yapılacak. 5 tane veritabanı kaydımız olduğu için, toplamda 10 sorgu çekilecek ve ek olarak ilk sorgu olan exam_center’ın kendisinin sorgulanmasıyla birlikte toplamda 11 sorgu edecektir. Buna kısaca N+1 durumu ismi verilir.

Uygulamanız içerisinde controller ve view dosyalarınızın bu şekilde olduğunu varsayalım:

Bu yapıda kurgulanmış bir sistemde index metodunu çağırdığımda loglarıma şu sorgular düşüyor:

5 veritabanı kaydı için çekilen 11 sorguyu görebilirsiniz.

includes Metodu

N+1 sorgu durumundan kurtulmak için “includes” metodu kullanılır.

Controller’ı bu şekilde düzenleyerek tekrar logları kontrol edelim:

Yapılan sorgu sayısı 7’ye düştü ancak hala Country için yapılan sorgularda bir değişiklik bulunmuyor. Burada “nested” bir lişki yapısı olduğu için dökümantasyonu takip ederek controller’ı tekrar düzenlememiz gerekecek:

Tekrar loglarımızı kontrol ettiğimizde yapılan sorgu sayısının 3’e düştüğünü ve sorgular için harcanan toplam sürenin azaldığını görebilirsiniz:

Hepsi bu kadar. Detaylar için Rails dökümantasyonuna göz atabilirsiniz:

http://guides.rubyonrails.org/active_record_querying.html

GEM – Pundit ile Authorization (Cancan Alternatifi)

Neden Cancan değilde Pundit?

  • Cancan 1 yılı aşkın süredir güncellenmiyor. Pundit sık sık güncelleniyor.
  • GEM’in geliştiricisi olan Ryan Bates’in uzun zamandır kayıplara karışmış durumda. Ryan Bates ayrıca Railscasts için 2 Eylül’de dönüş yapacağını söylemişti ancak 11 Temmuz itibariyle hala dönüş yapmadı ve kendisinden haber yok. Pundit’in arkasında İsveç kökenli elabs firması var.
  • Cancan’i başka sürdüren, sahip çıkan kimsenin olmaması sebebiyle açık olan onlarca issue bulunuyor. An itibariyle cancan’de 257, pundit’te ise 20 tane açık issue var. Cancan’e yapılan pull request’ler uzun bir süredir merge edilmemiş.
  • Rails 4.1 yayında olmasına rağmen cancan hala Rails 3 üzerini ve strong parametreleri desteklemiyor. Pundit ise Rails 4 destekliyor ve pure ruby yapısından dolayı uzunca bir süre versiyon sorunu çıkarmayacak gibi duruyor.
  • Cancan’in çok magic bir yapısı var. Pundit’te işler daha sizin kontrolünüzde.
  • Pundit cancan’e göre çok daha hafif ve hızlı çalışan bir GEM.
  • Pundit’in bağımlılıkları Cancan’in bağımlılıklarından daha az.
  • Pundit sayesinde authorization yapınızı hiç modele ve controller’a bulaşmadan – dolayısıyla fat controller’lar – modeller yaratmadan kurabiliyorsunuz.

Meraklısına ilave okumalar:

  1. Cancan vs. Pundit: http://www.distilnetworks.com/cancan-vs-pundit-choose-pundit-authorization/
  2. Alternative for Cancan: http://stackoverflow.com/questions/7213927/alternative-for-cancan/10235613#10235613
  3. Cookie HQ’ın Pundit Deneyimleri: http://cookieshq.co.uk/posts/pundit/
  4. Cancan’den Pundit’e Migration: http://blog.carbonfive.com/2013/10/21/migrating-to-pundit-from-cancan/

Kurulum

application_controller‘ı aşağıdaki şekilde düzenleyin:

generator’ı çalıştırarak örnek dosyaları oluşturun:

Kısa Bir Ara (Planlama)

User” isminde bir kullanıcı modeliniz olduğunu ve şöyle bir yetkilendirme sistemi hazırlamak istediğinizi varsayalım:

auth

Böyle bir yapıyı 2 şekilde kurgulayabilirsiniz:

  1. User modelinize her bir yetki ismi için boolean bir alan oluşturursunuz ve bu sayede

    gibi sorgu yaparsınız.
  2. Roller için ayrı bir model oluşturursunuz ve her bir yetkiyi orada rol olarak tanımlarsınız ve

    gibi sorgu yaparsınız. Roller ve User modelleri HABTM ilişkisine sahip olur.

Uygulamanızın ihtiyaçlarına göre herhangi bir yolu seçebilirsiniz. İlk yöntem daha basit authorization işlemleri için yeterliyken, kapsamlı ve onlarca rolün olacağı bir sistemde ikinci yöntemi tercih etmenizi öneririm.

Kullanım

Generator’ın oluşturduğu dosya/lar GEM’in özelliklerini demo etmek ve size hazır bir iskelet yapıyı sunmak için düzenlendiğinden bunları incelemek kafanızı karıştırabilir, şimdilik boşverin.

Generator tarafından app/policies dizinine oluşturulan application_policy.rb dosyası authorization sisteminiz için default ayarlarınızı tanımlayacağınız dosyadır. Burada her bir CRUD işlemi için uygulamanın nasıl davranacağını kurgulayabilirsiniz.

Koddan anlayabileceğiniz üzere her bir controller metodu için burada bir metod tanımlıyoruz ve hangi durumlarda true, hangi durumlarda ise false döndüreceğini belirtiyoruz.

Bu genellenmiş modelin işinizi görmediği durumlar için, bu modeli miras alan ayrı ayrı policy’ler oluşturabilirsiniz.

Örneğin City isminde bir modeliniz olduğunu ve burada application_policy‘nin özelliklerini yine devralmak istediğinizi ancak ek ihtiyaçlarınız olduğunu varsayalım. Bu durumda app/policies altında “city_policy.rb” isminde bir dosya oluşturmanız yeterlidir. Veya;

komutu ile bu modele özel bir policy dosyası hızlıca oluşturabilirsiniz.

edit? metodu city_policy içerisinde tekrar tanımlandığı için application_policy‘de ki kullanımı göz ardı edilecektir. Buna benzer modele özel tanımlamaları kendi policy dosyası içerisinde yapabilirsiniz.

Şimdi tanımlamalarımız tamam olduğuna göre “cities_controller.rb” dosyasına gidelim:

Ve hepsi bu kadar. Artık basit düzeyde fakat sorunsuz çalışan bir yetkilendirme sisteminiz var.

Permission Denied Hatasını Ayıklama

Tanımladığınız durumlar dışında CRUD üzerinde yetkisiz bir işlem yapıldığında uygulamanız Pundit::NotAuthorizedError hatası vererek işlemi sonlandıracaktır. Bu hatayı yakalayarak, 403 sayfamıza yönlendirmesini sağlayalım:

application_controller.rb içerisinde aşağıdaki tanımlamayı yapınız;

Scopelar ve diğer konular için GEM dökümantasyonunu takip edebilirsiniz:

https://github.com/elabs/pundit

Kolay gelsin.

Ngrok ile Localhost Tünelleme

Ngrok, yerel makinanızı tünelleyerek ve size bir subdomain vererek – yerelinizi internet üzerinde yayınlamanıza yardımcı olan bir araçtır. Bu sayede yerel makinanızda çalışan bir uygulamayı uzakta bulunan müşterinize veya ekip arkadaşınıza çalışır halde göstermek için bir yerlere deploy etmenize gerek kalmaz.

Ngrok sayesinde yazmış olduğunuz kodu kolayca demo edebilir, HTTP trafiğini takip ve replay edebilir, request’leri, form verilerini, JSON/XML datasını uygulama web arayüzü üzerinden görüntüleyebilirsiniz.

Kurulum

https://ngrok.com/ adresinden işletim sisteminize uygun dosyayı indirin. Zip arşivini uygun bir konuma (Masaüstü vb.) çıkartın.

Yardım Kılavuzu

Zip içerisinden çıkan dosyanın bulunduğu dizine terminalden düşün. Ardından;

komutu ile uygulamanın yardım sayfalarına ulaşabilirsiniz.

Doğrulama

Ngrok’un tüm özelliklerinden faydalanabilmek için websayfası üzerinden ücretsiz olarak kayıt olabilirsiniz. Daha sonra ise dashboard sayfasından edindiğiniz anahtar ile doğrulama yapın;

Kullanım

Yerel makinanızın 80.portunu internete açmak ve erişim için bir domain almak istiyorsanız kısaca aşağıdaki komutu kullanabilirsiniz;

Komutu çalıştırdığınızda internet üzerinde çalışan bir domain adresiniz anında hazır olacaktır.

ngrok-80

Forwarding” alanında yazan adresi istediğiniz kişilere göndererek, yerel makinanız üzerinde bağladığınız porta client gibi bağlanmalarını sağlayabilirsiniz.

Port Ayarları

Ngrok’a başka bir port numarası vererek (örneğin Rails geliştiricileri 3000 portunu) aynı yöntemle yerelinizi paylaşabilirsiniz.

ngrok-3000

Subdomain Ayarları

Ngrok’un size vermiş olduğu rastgele subdomain işinizi görmüyor ve kendi alan adınızı belirlemek istiyorsanız “subdomain” parametresini kullanabilirsiniz;

Bu durumda ngrok adresiniz http://ais.ngrok.com ve https://ais.ngrok.com olacaktır.

HTTP Authentication Ayarları

Ngrok’un bir diğer şahane özelliği ise HTTP authentication desteklemesi. Bu özelliği kullanabilmek için “httpauth” parametresi girmeniz yeterli:

HTTP Trafik Analizi

Gelen HTTP trafiğini analiz edebilmek için ngrok adresinize 1 kez request (URL’yi tarayıcınızda açarak sayfayı görüntüleyin!) yapın.

Daha sonra ise http://localhost:4040/http/in adresinden gelen trafiği analiz edebilir, replay edebilir ve uygulamanızın nasıl davrandığını izleyerek hatalı durumları yakalayabilirsiniz.

ngrok-requests

Rails'te CSV İşlemleri – Roo ve SmarterCSV GEM'leri

Roo GEM

CSV, XLS ve ODS’yi başarıyla okuyor, ancak tüm yaptığı bundan ibaret – başka bir özelliği yok.

Roo GEM (CSV Load)

Roo GEM (CSV Read Örneği)

SmarterCSV GEM

Smarter_CSV sadece CSV ile çalışıyor ancak özellik bakımından çok daha üstün.

SmarterCSV (CSV Read)

process redis’ten tanıdık. Bu betik tamda istenilen şekilde hash döndürür:

Burada göründüğü üzere smarter_csv bir takım normalizasyon işlemleride yapıyor. Örneğin “TC Kimlik No” başlığını downcase ve snakecase yaparak tc_kimlik_no şekline sokmuş ancak “Öğrenci No” için aynısını başarılı yapamamış “Öğrenci_no” gibi birşey ortaya çıkmış. Bu durum key_mapping yaparken önemli.

SmarterCSV (Key Mapping)

:Öğrenci_no yüzünden çalışmayacağını düşündüğüm betik sorunsuz çalışıyor ve şunu döndürüyor:

SmarterCSV (Chunk Size)

Bu parametre her bir dizide bulunacak value:key ikilisinin sayısını belirtiyor ve sonuçları buna göre döndürüyor.

SmarterCSV (Chunk Processing ve Virtual Attributes)

CSV dosyamızı bizim belirlediğimiz miktarda yığınlara (chunk) bölerek işletebiliriz.

CSV Dosyamız=>

Betik =>

Yanıt =>

SmarterCSV (Single Chunk Processing)

Aynı CSV’yi parçalara bölmeden direk tek parça olarak işletmek için;

Yanıt olarak bu döner =>

SmarterCSV (Modellere Yazmak – Toplu)

Import dosyası =>

Deneme amacıyla ilgili işlemleri Participation modelinin index controller’ına ekledim.

Bu action’dan beklenen, Participations sayfası her ziyaret edildiğinde beklenen şey CSV’nin işlenmesiydi. Sayfayı ziyaret ettiğimde kayıtlar eklenmedi, çünkü modelde bir takım validasyonlar buna engel oluyordu.

Bu kısıtlamamdan dolayı CSV işlenmesine rağmen kayıtlar işlenmedi — ancak ve ancak request arka planda asılı kalmış bekliyordu. Bir süre sonra sistemde zaten olan kayıtları temizledim ve CSV’den gelen kayıtlar tıkır tıkır veritabanına yazıldı.

Yani özetle herhangi bir sebeple process tamamlanamazsa iptal olmuyor ve askıda kalıyor, şartlar uygunlaşıncada işlem kaldığı yerden devam ediyordu. Bu hem iyi, hemde tehlikeli bir durum!

SmarterCSV (Modellere Yazmak – Parça Parça)

Aynı işlemi chunk’lar halinde parça parça veritabanına yazmak için şöyle yapılabilir =>

SmarterCSV (Modellere Yazmak – Resque ile)

Henüz bunu denemedim fakat dökümantasyona göre bu şekilde olması gerekiyor =>

BOM’lu CSV’lerde Unicode

Windows’ta aksi belirtilmediği sürece tüm dosyala BOM’lu yazılıyor. BOM’lu CSV dosyalarında unicode problem çıkarttığı için şöyle bir şey kullanılmalıymış: