sinatra pattern 20130415
TRANSCRIPT
ちっちゃくはじめておっきく育てる
sinataraアプリの作り方
SEO Naotoshi (@sonots)
自己紹介describe Sonots do its(:company) { should == :DeNA }
it_should_behave_like “DeNA employee”end
shared_examples_for “DeNA employee” do it { should write(:perl) } #=> failend
最近やってること
Haikanko
※ このロゴはフィクションであり(ry
誰かが言ってた
sinatraってアプリが小さい時はいいけど、大きくなるとお辛いんでしょう?
そんなことないよ
ちっちゃくはじめておっきく育てる俺の最強 Sinatra パターンをお伝えします
ところでruby 2.0 で何の問題もなく動いているので、ruby 2.0関連の話は何もなし...
さっそくコード中心で><
基礎 ~ クラシックスタイル
require 'sinatra' get '/hello' do 'Hello World!'end get '/hello/:name' do "Hello #{params[:name]}!"end
$ ruby my_app.rb GemfileGemfile.lockmy_app.rb
起動 ディレクトリ構造
my_app.rb
モジュラースタイルrequire 'sinatra/base' class MyApp < Siantra::Base get '/hello' do 'Hello World!' end get '/hello/:name' do "Hello #{params[:name]}!" endend
$ rackup
GemfileGemfile.lockconfig.rumy_app.rb
起動 ディレクトリ構造# config.ru require './my_app'run MyApp
Controller足したい
1. Sinatra.register を使う# my_app.rb require 'sinatra/base'require_relative 'posts_controller'
class MyApp < Sinatra::Base register PostsController
get '/hello' do 'Hello World!' end get '/hello/:name' do "Hello #{params[:name]}!" endend Gemfile
Gemfile.lockconfig.rumy_app.rbposts_controller.rb
ディレクトリ
# posts_controller.rb module PostsController def self.registered(app) app.get '/posts' do end
app.get '/posts/:id' do "Post #{params[:id]}" end endend
app.get とかキモい
2. use (Rack Middleware)# my_app.rbclass MyApp < Sinatra::Base get '/hello' do 'Hello World!' end get '/hello/:name' do "Hello #{params[:name]}!" endend
GemfileGemfile.lockconfig.rumy_app.rbposts_controller.rb
ディレクトリ
# posts_controller.rb class PostsController < Sinatra::Base get '/posts' do end
get '/posts/:id' do "Post #{params[:id]}" endend
# config.rurequire 'sinatra/base'require './my_app'require './posts_controller'use PostsControllerrun MyApp
まぁまぁ
本命: URLMap を使うclass HelloController < Sinatra::Base get '/hello' do 'Hello World!' end get '/hello/:name' do "Hello #{params[:name]}!" endend
GemfileGemfile.lockconfig.ruhello_controller.rbposts_controller.rb
ディレクトリ
class PostsController < Sinatra::Base get '/' do end
get '/:id' do "Post #{params[:id]}" endend
require 'sinatra/base'require './hello_controller'require './posts_controller'ROUTES = { '/' => HelloController, '/posts' => PostsController,}run Rack::URLMap.new(ROUTES)
config.ru
View足したい
View ~ Sinatraにあるよclass HelloController < Sinatra::Base set :views, File.expand_path('../views', File.dirname(__FILE__)) get '/hello' do 'Hello World!' end
get '/hello/:name' do @name = params[:name] erb :hello endend
GemfileGemfile.lockconfig.rucontrollers/views/
ディレクトリ<html> <b>Hello <%= @name %>!</b></html>
views/hello.erb
Model足したい
Model ~ ActiveRecordとかsource 'https://rubygems.org'
gem 'sinatra', require: 'sinatra/base'gem 'activesupport'gem 'activerecord'gem 'sinatra-activerecord',:require => 'sinatra/activerecord'gem 'sqlite3'gem 'rake'
require 'active_record'ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :host => 'localhost', :username => 'USERNAME', #or root :password => 'PASSWORD', :database => 'db/YOURDATABASE')class Post < ActiveRecord::Baseend
models/post.rb
Gemfile
GemfileGemfile.lockconfig.rucontrollers/views/models/
ディレクトリ
MVC揃った ^^
けど
Worker欲しくなった
Worker+ gem 'foreman’
ディレクトリ
web: bundle exec rackup web/config.ruworker: bundle exec ruby worker/notification.rb
worker/notification.rb
Gemfile
GemfileGemfile.lockconfig.ruweb/ controllers/ views/models/worker/
require_relative '../models/post.rb'class Notification def run while true sleep 1 puts "hey! #{Post.all.first}" end endendNotification.new.run
Procfile
$ foreman start
起動
まとめ
• 最初はちっちゃくリーンスタートアップ
• おっきくなっても破綻しない!(Rails っぽくしていけば)
• いつ Sinatra やるの?今でしょ!
• コード https://github.com/sonots/sinatra-practice