100% found this document useful (6 votes)
1K views48 pages

Ruby Off Rails (English)

This document discusses the evolution of Ruby web frameworks from Rails to more modular Rack-based approaches. It introduces Rack as a specification that provides a minimal interface between web servers and frameworks. Rack allows various frameworks like Sinatra, Merb and Rails to be run on different servers through its unified interface. It also enables frameworks to be composed from modular middleware components through the Rack builder.

Uploaded by

zh
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (6 votes)
1K views48 pages

Ruby Off Rails (English)

This document discusses the evolution of Ruby web frameworks from Rails to more modular Rack-based approaches. It introduces Rack as a specification that provides a minimal interface between web servers and frameworks. Rack allows various frameworks like Sinatra, Merb and Rails to be run on different servers through its unified interface. It also enables frameworks to be composed from modular middleware components through the Rack builder.

Uploaded by

zh
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 48

Ruby off Rails

by Stoyan Zhekov
Kyoto, 17-May-2008
Table of content
● Coupling and Cohesion
● Common needs for various web apps
● ORM - Sequel (short overview)
● Ruby Web Evolution
● Enter Rack - The Middle Man
● Thin, Ramaze, Tamanegi
● Summary, Extras, Questions

08/05/19 2
Coupling and Cohesion (1)
● Cohesion
http://en.wikipedia.org/wiki/Cohesion_(computer_science)
● Coupling
http://en.wikipedia.org/wiki/Coupling_(computer_science)

08/05/19 3
Coupling and Cohesion (2)

Applications should be composed of components


that show:
● High cohesion
– doing small number of things and do them well
● Low (loosely) coupling
– easy replace any component with another one

08/05/19 4
Coupling and Cohesion (3)

Google vs Amazon

08/05/19 5
Coupling and Cohesion (4)

VS

08/05/19 6
What about Rails?

08/05/19 7
Ruby on Rails
● Full Stack – was good. Now?
● Convention over configuration – good?
● DRY – possible?
– Generators
– Plugins
– Libraries

08/05/19 8
Life without Rails

Is it possible?

08/05/19 9
Common needs for various web apps

● Database handling: ORM


● Request processing: CGI env, uploads
● Routing/dispatching: map URLs to classes
● Rendering/views: rendering libraries
● Sessions: persist objects or data

08/05/19 10
Database ORM
● Active Record ?= ActiveRecord
● ActiveRecord – a lot of problems
– http://datamapper.org/why.html
● Data Mapper – fast, but not ready
– No composite keys (when I started using it)
– Have it's own database drivers
● Sequel – good, I like it

08/05/19 11
ORM – Sequel (Why?)
● Pure Ruby
● Thread safe
● Connection pooling
● DSL for constructing DB queries
● Lightweight ORM layer for mapping records to
Ruby objects
● Transactions with rollback

08/05/19 12
ORM – Sequel (Core)
● Database Connect
require 'sequel'
DB = Sequel.open 'sqlite:///blog.db'

DB = Sequel.open 'postgres://cico:12345@localhost:5432/mydb'

DB = Sequel.open("postgres://postgres:postgres@localhost/my_db",
:max_connections => 10, :logger => Logger.new('log/db.log'))

08/05/19 13
ORM – Sequel (Core, 2)
DB << "CREATE TABLE users (name VARCHAR(255) NOT NULL)"

DB.fetch("SELECT name FROM users") do |row|


p r[:name]
end

dataset = DB[:managers].where(:salary => 50..100).order(:name, :department)

paginated = dataset.paginate(1, 10) # first page, 10 rows per page


paginated.page_count #=> number of pages in dataset
paginated.current_page #=> 1

08/05/19 14
ORM – Sequel (Model)

class Post < Sequel::Model(:my_posts)


set_primary_key [:category, :title]

belongs_to :author
has_many :comments
has_and_belongs_to_many :tags

after_create do
set(:created_at => Time.now)
end

end

08/05/19 15
ORM – Sequel (Model, 2)

class Person < Sequel::Model


one_to_many :posts, :eager=>[:tags]

set_schema do
primary_key :id
text :name
text :email
foreign_key :team_id, :table => :teams
end
end

08/05/19 16
Evolution

08/05/19 17
Ruby Web Evolution

Webrick Mongrel Event Thin Ebb


Machine

05/19/08 18
Thin web server
● Fast – Ragel and Event Machine
● Clustering
● Unix sockets (the only one I found) - nginx
● Rack-based – Rails, Ramaze etc.
● Rackup files support (follows)

05/19/08 19
Thin + Nginx
thin start --servers 3 --socket /tmp/thin
thin start --servers 3 –post 3000
# nginx.conf
upstream backend {
fair;
server unix:/tmp/thin.0.sock;
server unix:/tmp/thin.1.sock;
server unix:/tmp/thin.2.sock;
}

05/19/08 20
The problem

Merb Ramaze Sinatra ...

How to connect them?

CGI Webrick Mongrel Thin

05/19/08 21
The solution - Rack

Merb Ramaze Sinatra ...

Rack – The Middle Man

CGI Webrick Mongrel Thin

05/19/08 22
What is Rack?

05/19/08 23
What IS Rack?

http://rack.rubyforge.org/

By Christian Neukirchen
05/19/08 24
WHAT is Rack?
● Specification (and implementation) of a minimal
abstract Ruby API that models HTTP
– Request -> Response
● An object that responds to call and accepts one
argument: env, and returns:
– a status, i.e. 200
– the headers, i.e. {‘Content-Type’ => ‘text/html’}
– an object that responds to each: ‘some string’

05/19/08 25
This is Rack!
class RackApp
def call(env)
[ 200, {"Content-Type" => "text/plain"}, "Hi!"]
end
end

app = RackApp.new

05/19/08 26
Free Hugs

http://www.freehugscampaign.org/
05/19/08 27
Hugs Application

p 'Hug!'

05/19/08 28
ruby hugs.rb

%w(rubygems rack).each { |dep| require dep }

class HugsApp
def call(env)
[ 200, {"Content-Type" => "text/plain"}, "Hug!"]
end
end

Rack::Handler::Mongrel.run(HugsApp.new, :Port => 3000)

05/19/08 29
Rack::Builder
require 'hugs'
app = Rack::Builder.new {
use Rack::Static, :urls => ["/css", "/images"], :root => "public"
use Rack::CommonLogger
use Rack::ShowExceptions

map "/" do
run lambda { [200, {"Content-Type" => "text/plain"}, ["Hi!"]] }
end

map "/hug" do
run HugsApp.new
end
}

Rack::Handler::Thin.run app, :Port => 3000


05/19/08 30
Rack Building Blocks
● request = Rack::Request.new(env)
– request.get?
● response = Rack::Response.new('Hi!')
– response.set_cookie('sess-id', 'abcde')
● Rack::URLMap
● Rack::Session
● Rack::Auth::Basic
● Rack::File
05/19/08 31
Rack Middleware

Can I create my own use Rack::... blocks?


class RackMiddlewareExample
def initialize app
@app = app
end

def call env


@app.call(env)
end
end

05/19/08 32
Common needs for various web apps

● Database handling: ORM Sequel


● Request processing: Rack::Request(env)
● Routing/dispatching: Rack 'map' and 'run'
● Rendering/views: Tenjin, Amrita2
● Sessions: Rack::Session

05/19/08 33
Does it scale?

05/19/08 34
rackup hugs.ru

require 'hugs'
app = Rack::Builder.new {
use Rack::Static, :urls => ["/css", "/images"], :root => "public"

map "/" do
run lambda { [200, {"Content-Type" => "text/plain"}, ["Hi!"]] }
end

map "/hug" do
run HugsApp.new
end
}
Rack::Handler::Thin.run app, :Port => 3000

05/19/08 35
Hugs Service
● rackup -s webrick -p 3000 hugs.ru
● thin start --servers 3 -p 3000 -R hugs.ru
● SCGI
● FastCGI
● Litespeed
● ....

05/19/08 36
Rack-based frameworks
● Invisible – thin-based framework in 35 LOC
– http://github.com/macournoyer/invisible/
● Coset – REST on Rack
● Halcyon – JSON Server Framework
● Merb
● Sinatra
● Ramaze
● Rails !?
05/19/08 37
Rack coming to Rails
● Rails already have Rack, but:
– raw req -> rack env -> Rack::Request ->CGIWrapper ->
CgiRequest
● Ezra Zygmuntowicz (merb)'s repo on github
– http://github.com/ezmobius/rails
– raw req -> rack env -> ActionController::RackRequest
– ./script/rackup -s thin -c 5 -e production

05/19/08 38
Ramaze
● What: A modular web application framework
● Where: http://ramaze.net/
● How: gem install ramaze
● git clone http://github.com/manveru/ramaze.git
● Who: Michael Fellinger and Co.

05/19/08 39
Why Ramaze?
● Modular (low [loosely] coupling)
● Rack-based
● Easy to use
● A lot of examples (~25) – facebook, rapaste
● Free style of development
● Friendly community - #ramaze
● “All bugs are fixed within 48 hours of reporting.”

05/19/08 40
Deployment options
● CGI ● Ebb
● FastCGI ● Evented Mongrel
● LiteSpeed ● Swiftiplied Mongrel
● Mongrel ● Thin
● SCGI ● Whatever comes along
● Webrick and fits into the Rack

05/19/08 41
Templating engines
● Amrita2 ● RedCloth
● Builder ● Remarkably
● Erubis ● Sass
● Ezmar ● Tagz
● Haml ● Tenjin
● Liquid ● XSLT
● Markaby

05/19/08 42
Ezamar

05/19/08 43
Easy to use?
%w(rubygems ramaze).each {|dep| require dep}

class MainController < Ramaze::Controller


def index; "Hi" end
end

class HugsController < Ramaze::Controller


map '/hug'
def index; "Hug!" end
end

Ramaze.start :adapter => :thin, :port => 3000

05/19/08 44
Ramaze Usage
class SmileyController <
Ramaze::Controller
map '/smile'

helper :smiley

def index
smiley(':)')
end
end

05/19/08 45
Ramaze Usage (2)
module Ramaze
module Helper
module SmileyHelper
FACES = {
':)' => '/images/smile.png',
';)' => '/images/twink.png'}
REGEXP = Regexp.union(*FACES.keys)

def smiley(string)
string.gsub(REGEXP) { FACES[$1] }
end
end
end
end

05/19/08 46
Alternative Stack
● ORM – Sequel
● Web server – Thin + NginX
● Rack Middleware
● Ramaze framework
● Templates – HAML, Tenjin, Amrita2

05/19/08 47
Summary
● Not trying to tell you to not use Rails
● Just keep your mind open
● Sequel is good ORM
● Use Rack – DIY framework, DIY server
● Ramaze is cool and easy to use

05/19/08 48

You might also like