The document discusses Ruby on Rails and alternatives for building web applications in Ruby. It covers concepts like coupling and cohesion in software design. It then introduces Rack, an interface between web servers and Ruby frameworks, and how it helped connect different Ruby frameworks like Sinatra, Merb, and Ramaze. It provides examples of using Rack with the Sequel ORM and Thin web server to build simple web applications in Ruby.
2. 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
4. 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
10. 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
11. 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
12. 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
13. 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(quot;postgres://postgres:postgres@localhost/my_dbquot;,
:max_connections => 10, :logger => Logger.new('log/db.log'))
08/05/19 13
14. ORM – Sequel (Core, 2)
DB << quot;CREATE TABLE users (name VARCHAR(255) NOT NULL)quot;
DB.fetch(quot;SELECT name FROM usersquot;) 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
15. 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
16. 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
19. 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
24. What IS Rack?
http://rack.rubyforge.org/
By Christian Neukirchen
05/19/08 24
25. 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
26. This is Rack!
class RackApp
def call(env)
[ 200, {quot;Content-Typequot; => quot;text/plainquot;}, quot;Hi!quot;]
end
end
app = RackApp.new
05/19/08 26
32. 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
33. 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
37. 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
38. 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
39. 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
40. 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
41. 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
44. Easy to use?
%w(rubygems ramaze).each {|dep| require dep}
class MainController < Ramaze::Controller
def index; quot;Hiquot; end
end
class HugsController < Ramaze::Controller
map '/hug'
def index; quot;Hug!quot; end
end
Ramaze.start :adapter => :thin, :port => 3000
05/19/08 44
45. Ramaze Usage
class SmileyController <
Ramaze::Controller
map '/smile'
helper :smiley
def index
smiley(':)')
end
end
05/19/08 45
46. 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
47. Alternative Stack
● ORM – Sequel
● Web server – Thin + NginX
● Rack Middleware
● Ramaze framework
● Templates – HAML, Tenjin, Amrita2
05/19/08 47
48. 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