Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Merhaba "Sinatra"

Merhaba "Sinatra"

Ruby web framework'ü Sinatra'yı tanıyalım!

Uğur Özyılmazel

March 31, 2013
Tweet

More Decks by Uğur Özyılmazel

Other Decks in Programming

Transcript

  1. MERHABA “SİNATRA”
    Uğur Özyılmazel
    http://ugur.ozyilmazel.com | @ugurozyilmazel

    View full-size slide

  2. FRANK SINATRA

    View full-size slide

  3. Sinatra ?
    Ruby ile hızlı ve kolay bir
    şekilde web uygulaması
    geliştirmek için hazırlanmış bir
    DSL’dir.
    http://www.sinatrarb.com/

    View full-size slide

  4. DSL ?
    Belirli bir problemi çözmek ya da işlemi
    yapmak için geliştirilmiş / hazırlanmış
    dil.

    View full-size slide

  5. Genel Özellikler
    • RACK Application *
    • Küçük ölçekli web uygulamaları
    • Saniyede 2000 request kapasite
    • Hız ve düşük hafıza kullanımı
    • Kolay kurulum ve deployment
    • “1 file app”
    * RACK : Ruby ve Ruby Framework’leri için Web Sunucusu
    Blake Mizerany

    View full-size slide

  6. Kullanım Alanları
    • Hızlıca Prototip hazırlamak
    • API sunmak / yapmak
    • Herhangi bir ilave framework
    kullanmadan Web Uygulaması yapmak
    • Apache+PHP’nin Ruby yansıması

    View full-size slide

  7. Dan Benjamin
    “RACK’den fazla
    RAILS’den az!”
    Peepcode - Meet Sinatra
    “More than RACK, Less than RAILS”

    View full-size slide

  8. Kurulum
    $ gem install sinatra
    * Mart 2013 itibariyle son sürüm : 1.4.2

    View full-size slide

  9. Yardımcı Araçlar
    $ gem install shotgun thin
    $ shotgun server.rb
    == Shotgun/Thin on http://127.0.0.1:9393/
    >> Thin web server (v1.5.0 codename Knife)
    >> Maximum connections set to 1024
    >> Listening on 127.0.0.1:9393, CTRL+C to stop
    • shotgun
    • thin

    View full-size slide

  10. “Merhaba Dünya”
    require 'rubygems'
    require 'sinatra'
    get '/' do
    "Merhaba Dünya! saat: #{Time.now}"
    end
    # application.rb
    $ ruby application.rb # default http://localhost:4567
    $ shotgun application.rb # http://127.0.0.1:9393

    View full-size slide

  11. HTTP Metodları
    GET
    POST
    PUT
    DELETE
    PATCH
    OPTIONS
    LINK
    UNLINK

    View full-size slide

  12. Yakalayıcılar (Handlers)
    get '/merhaba/:user_name' do
    "Merhaba #{params[:user_name]}!"
    end
    get '/merhaba/*/numaran/*' do
    "#{params[:splat][0]}, #{params[:splat][1]}"
    end
    http://127.0.0.1:9393/merhaba/vigo/numaran/11
    http://127.0.0.1:9393/merhaba/jspyconf

    View full-size slide

  13. Params, Splat ve RegExp Kullanımı
    get '/indir/*.*' do |file, ext|
    "Dosya: #{file}, Tipi: #{ext}"
    end
    http://127.0.0.1:9393/indir/resim.jpg
    get %r{/kullanici/([\w]+)/?(\d+)?} do
    "Yakalananlar: #{params[:captures]}"
    end
    http://127.0.0.1:9393/kullanici/vigo
    http://127.0.0.1:9393/kullanici/vigo/1
    get '/kazanan/:user/?:id?' do
    "Kazanan #{params[:user]}, id var mı? #{!params[:id].nil?}"
    end
    http://127.0.0.1:9393/kazanan/vigo
    http://127.0.0.1:9393/kazanan/vigo/1

    View full-size slide

  14. Duruma Bağlı Yakalama (Conditions)
    :agent
    # AppleWebKit/536.28.10
    # Sadece AppleWebKit tarayıcıları için
    get '/ajan', :agent => /AppleWebKit\/(\d+)/ do
    mversion = @params[:agent].first
    "AppleWebKit major sürümü: #{mversion}"
    end
    get '/ajan' do
    "Tüm tarayıcılar için..."
    end
    :host_name
    # http://localhost:9393/admin yakalar
    # http://127.0.0.1:9393/admin çalışmaz
    get '/admin', :host_name => /^local/ do
    "Sadece adminler girebilir!"
    end
    :provides
    get '/test_provide', :provides => :json do
    pass unless request.accept? 'application/json'
    { :username => 'vigo', :email => '[email protected]' }.to_json
    end

    View full-size slide

  15. Kendi Durumumuz Oluşturalım
    set(:ihtimal) { |value| condition { rand <= value } }
    get '/piyango', :ihtimal => 0.1 do
    "Tebrikler kazandınız!"
    end
    get '/piyango' do
    "Kaybettiniz ):"
    end
    set(:test_auth) do |*roles|
    condition do
    unless roles.any? {|role| current_test_user.in_role? role }
    redirect "/sistem/giris", 303
    end
    end
    end
    get "/sistem/giris/?" do
    "Bu sayfaları görüntülemek için sisteme giriş yapmanız gerekiyor!"
    end
    get "/sistem/profil/?", :test_auth => [:user, :guest] do
    "Profil bilgileri"
    end
    get "/sistem/admin/?", :test_auth => :admin do
    "Sadece admin olanlar görebiliyor"
    end

    View full-size slide

  16. Sayfalar (Views)
    # views/sayfa.erb
    Merhaba

    Saat <%= @saat %>

    # server.rb
    get '/sayfa/?' do
    @saat = Time.now.strftime("%I:%M:%S")
    erb :sayfa
    end

    View full-size slide

  17. Post İşlemi
    # application.rb
    get '/post/test/?' do
    erb :post_form, :layout => :genel
    end
    post '/post/test/?' do
    @username = params[:username]
    erb :post_form, :layout => :genel
    end

    Kullanıcı adı girin



    <% if @username %>
    Göndermiş olduğunuz kullanıcı adı:
    <%= h @username %>
    <% end %>

    # views/post_form.erb
    Helper

    View full-size slide

  18. Statik Dosyalar
    # application.rb
    get '/sayfa/3/?' do
    @saat = Time.now.strftime("%I:%M:%S")
    @page_title = "Bu sayfa :layout ve css kullanıyor"
    erb :sayfa, :layout => :genel2
    end
    # public/css/base.css
    body {
    background: #555;
    color: #ff0;
    font-family: Helvetica, Arial;
    margin: 20px;
    padding: 0;
    }
    h1 {
    color: #fff;
    }




    <%= @page_title %>



    genel.erb
    <%= yield %>


    # views/genel2.erb

    View full-size slide

  19. Şablonlar (Templates)
    • Haml
    • Erb
    • Builder
    • Nokogiri
    • Liquid
    • Markdown
    • Textile
    • Rdoc
    • Sass / SCSS
    • Less
    • Coffe
    • Stylus

    View full-size slide

  20. Mizanpaj (Layout)
    # application.rb
    get '/sayfa/2/?' do
    @saat = Time.now.strftime("%I:%M:%S")
    @page_title = "Bu sayfa :layout kullanıyor"
    erb :sayfa, :layout => :genel
    end
    # views/genel.erb




    <%= @page_title %>


    genel.erb
    <%= yield %>


    View full-size slide

  21. Şablonlar (Templates)
    Sass ve Markdown
    get '/sass/*.sass' do
    content_type 'text/css', :charset => 'utf-8'
    sass params[:splat].first.to_sym,
    :style => :expanded,
    :views => "#{settings.root}/sass"
    end
    # sass/*.sass yakalamak için
    get '/sayfa/ornek/markdown/?' do
    markdown :sayfa, :layout_engine => :erb, :layout => :genel3
    end
    # render için erb motorunu kullanıyoruz

    View full-size slide

  22. Şablonlar (Templates)
    Sass ve Markdown
    # views/genel3.erb




    <%= @page_title %>



    genel.erb
    <%= yield %>


    View full-size slide

  23. Şablonlar (Templates)
    Sass ve Markdown
    # views/sayfa.markdown
    # Bu H1
    ## Bu H2
    Bu pre ...
    Bu paragraf...
    def foo(user)
    "#{user}"
    end
    # sass/stil.sass
    $color: #00f
    $h1_color: adjust-hue($color, 270deg)
    $fonts: Helvetica, Arial
    body
    background-color: adjust-hue($color, 20deg)
    color: darken($h1_color, 20%)
    font-family: $fonts
    margin: 40px
    h1
    color: $h1_color
    pre
    border: 1px solid darken($color, 20)
    padding: 20px
    background-color: darken($color, 24)
    code
    line-height: 1.5em
    color: darken($h1_color, 10%)

    View full-size slide

  24. Filtreler
    before
    Request’den önce çalışır.
    after
    Request’den sonra çalışır.
    before do
    headers "Content-Type" => "text/html; charset=utf-8"
    end

    View full-size slide

  25. Filtreler
    after ve before’da set edilen değişkenler
    tüm “route”larda kullanılabiliyor.

    View full-size slide

  26. Filtreler
    before '/sayfa/3/?' do
    @before_param = "Bu değişken -before- da set edildi"
    end
    get '/sayfa/3/?' do
    @saat = Time.now.strftime("%I:%M:%S")
    @page_title = "Bu sayfa :layout ve css kullanıyor"
    erb :sayfa, :layout => :genel2
    end

    View full-size slide

  27. Yardımcı Fonksiyonlar (Helpers)
    View ve Handler’larda kullanılır.
    helpers do
    def h(text)
    Rack::Utils.escape_html(text)
    end
    end
    # application.rb
    <%= h @username %>
    # view/erb

    View full-size slide

  28. pass ve halt
    halt
    Tamamen dur!
    pass
    Uygun olan bir sonraki route’a geç

    View full-size slide

  29. pass ve halt
    get '/tahmin/:kim/?' do
    pass unless params[:kim] == 'vigo'
    "Doğru cevap!"
    end
    get '/tahmin/*/?' do
    "Hayır bilemedin!"
    end
    http://127.0.0.1:9393/tahmin/vigo/
    get '/konferans1/:hangisi/?' do
    halt unless params[:hangisi] == 'jspyconf'
    "Evet doğru konferans!"
    end
    http://127.0.0.1:9393/konferans1/jspyconf

    View full-size slide

  30. Diğer halt durumları
    get '/konferans2/:hangisi/?' do
    halt 404 unless params[:hangisi] == 'jspyconf'
    "Evet doğru konferans!"
    end
    get '/konferans3/:hangisi/?' do
    halt [403, "Yetkiniz yok"] unless params[:hangisi] == 'jspyconf'
    "Evet doğru konferans!"
    end
    Hata kodu ve ilave mesaj belirtmek

    View full-size slide

  31. Özelleştirilmiş 404
    not_found do
    "Aradığınız sayfa bulunamadı!"
    end
    Tamamen özelleştirmek...
    not_found do
    erb :ozel_404
    end

    View full-size slide

  32. Yönlerdirmek: redirect
    redirect URL, StatusCode
    get '/google' do
    redirect "http://google.com"
    # redirect "/foo", 301
    end

    View full-size slide

  33. Hata Yakalamak
    error 403 do
    "Giriş Yasak"
    end
    get '/gizli' do
    403
    end
    error 400..510 do
    "Pek çok hatayı yakaladık"
    end

    View full-size slide

  34. Özelleştirilmiş Hatalar
    disable :show_exceptions
    error do
    mesaj = env['sinatra.error'].message
    "Hata mesajı: #{mesaj}"
    end
    class CustomError < StandardError; end
    error CustomError do
    mesaj = env['sinatra.error'].message
    "Bu CustomError,
    mesajı da #{mesaj}"
    end

    View full-size slide

  35. Özelleştirilmiş Hatalar
    get '/ozel-hata/1/' do
    raise StandardError, "StandardError raise ettik"
    end
    get '/ozel-hata/2/' do
    raise CustomError, "CustomError raise ettik"
    end

    View full-size slide

  36. Konfigürasyon
    :test
    :development
    :production
    # http://www.sinatrarb.com/intro.html#Configuration
    configure do
    # set :option, 'value'
    # enable :option
    # disable :option
    enable :logging
    disable :show_exceptions
    end
    configure :development, :test
    do
    enable :logging
    end

    View full-size slide

  37. Session
    enable :sessions
    Konfigürasyon seviyesinde
    session['key'] = "value"
    get('/') {
    "Merhaba #{session['user_name']}."
    }

    View full-size slide

  38. Session
    Pooling
    Cookie
    use Rack::Session::Cookie, :key => 'rack.session',
    :domain => 'foo.com',
    :path => '/',
    :expire_after => 2592000, # Saniye
    :secret => 'burayı_düzenle'
    use Rack::Session::Pool, :expire_after => 2592000

    View full-size slide

  39. Test
    group :test do
    gem 'rack-test'
    end
    # Gemfile
    OUTER_APP = Rack::Builder.parse_file('config.ru').first
    class TestApp < Test::Unit::TestCase
    include Rack::Test::Methods
    def app
    OUTER_APP
    end
    def test_sample_page
    get '/test/amacli/1/'
    assert last_response.ok?
    assert_equal "JsPyConf çok güzel!", last_response.body
    end
    end
    # tests.rb

    View full-size slide

  40. Test
    Rack::Test::Methods
    :request
    :get
    :post
    :put
    :delete
    :options
    :head
    :follow_redirect!
    :header
    :set_cookie
    :clear_cookies
    :authorize
    :basic_authorize
    :digest_authorize
    :last_response
    :last_request

    View full-size slide

  41. Deployment
    • Apache
    • Nginx
    • Standalone
    Phusion Passenger
    Heroku
    $ sudo gem install passenger
    https://toolbelt.heroku.com/
    git push heroku
    https://devcenter.heroku.com/articles/rack#frameworks

    View full-size slide

  42. Deployment
    # config.ru
    # application.rb
    # encoding: utf-8
    require "./application.rb"
    run MyApp
    # encoding: utf-8
    require 'rubygems'
    require 'bundler'
    Bundler.require
    # gerekli diğer require'lar...
    class MyApp < Sinatra::Base
    get '/' do
    "Merhaba"
    end
    run! if app_file == $0
    end
    # encoding: utf-8
    source "https://rubygems.org"
    ruby "1.9.3"
    group :development do
    gem 'thin'
    gem 'shotgun'
    end
    group :test do
    gem 'rack-test'
    end
    gem 'sinatra'
    gem 'sass'
    gem 'rdiscount'
    # Gemfile

    View full-size slide

  43. Deployment
    Apache
    $ (sudo) passenger-install-apache2-module

    ServerName example.com
    DocumentRoot /path/to/example.com/public

    AllowOverride all
    Options -MultiViews


    View full-size slide

  44. Daha Fazla...
    • sinatra-contrib
    • DataMapper (Veritabanı Entegrasyonu)
    • Modüler Uygulamalar
    • Streaming / Long Polling
    • Middleware Geliştirmek
    • Extension Geliştirmek

    View full-size slide

  45. DataMapper
    $ gem install data_mapper
    $ gem install dm-sqlite-adapter
    $ gem install dm-mysql-adapter
    $ gem install dm-postgres-adapter

    View full-size slide

  46. DataMapper
    require 'sqlite3'
    require 'dm-core'
    require 'dm-timestamps'
    configure :development do
    DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/my_database.db")
    end
    class Blog
    include DataMapper::Resource
    property :id, Serial
    property :title, String
    property :content, Text
    property :url, String
    property :is_active, Boolean
    property :created_at, DateTime
    property :updated_at, DateTime
    end
    get '/blog/:post_id' do
    @post = Blog.get(params[:post_id])
    erb :post_detail
    end
    sqlite3

    View full-size slide

  47. DataMapper
    class Post
    has n, :comments
    end
    class Comment
    belongs_to :post
    end
    DataMapper.auto_migrate!

    View full-size slide

  48. Kimler Kullanıyor?
    • Heroku
    • Github
    • Apple
    • BBC
    • Linkedin
    • Engine Yard
    • Stanford
    • Red Hat
    • Travis CI
    • Songbird

    View full-size slide

  49. Kaynaklar
    • http://www.sinatrarb.com/
    • http://recipes.sinatrarb.com/
    • http://sinatra-book.gittr.com/
    • http://modrails.com
    • http://datamapper.org/getting-started.html
    • https://peepcode.com/products/sinatra *
    • https://tutsplus.com/course/simple-sinatra/ *
    * Ücretli servisler

    View full-size slide

  50. Kaynak Kod
    https://github.com/vigo/jspy2013-sinatra
    http://jspy2013-sinatra.herokuapp.com

    View full-size slide

  51. Teşekkürler
    @ugurozyilmazel
    @vigobronx
    http://ugur.ozyilmazel.com

    View full-size slide