Skip to content

Commit

Permalink
this is it
Browse files Browse the repository at this point in the history
  • Loading branch information
blake.mizerany@gmail.com committed Sep 8, 2007
0 parents commit 72be291
Show file tree
Hide file tree
Showing 17 changed files with 477 additions and 0 deletions.
20 changes: 20 additions & 0 deletions examples/hello/test.rb
@@ -0,0 +1,20 @@
$LOAD_PATH.unshift '../../lib/'
require 'sinatra'

get '/' do
body <<-HTML
<form method="POST"><input type="text" name="name"/><input type="submit"></form>
HTML
end

post '/' do
body "You entered #{params[:name]}"
end

get '/erb' do
erb :index
end

get '/test' do
erb "Hello <%= params[:name] %>"
end
1 change: 1 addition & 0 deletions examples/hello/views/index.erb
@@ -0,0 +1 @@
<%= 1 + 3 %>
1 change: 1 addition & 0 deletions files/default_index.erb
@@ -0,0 +1 @@
Default Index!!!!!!!
52 changes: 52 additions & 0 deletions files/not_found.erb
@@ -0,0 +1,52 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html>

<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Not Found :: Sinatra</title>
</head>

<body id="not_found">

<style type="text/css" media="screen">
body {
background-color: #fff;
}

.message {
padding: 10px;

font-size: 20px;
font-color: #333;
}

#content {
}

.message pre {
font-size: 15px;
text-align: left;

background-color: #ccc;

padding: 10px;
}
</style>

<div id="container">
<div id="content">
<div class='message'>
<h3>Sinatra doesn't know this diddy, but he's a quick study.</h3>
<p>Add this to your lyrics:</p>
<pre><%= request.request_method.downcase %> '<%= request.path_info %>' do
html "Replace this with your code."
end</pre>
</div>
</div>
</div>

</body>

</html>
36 changes: 36 additions & 0 deletions lib/sinatra.rb
@@ -0,0 +1,36 @@
%w(rubygems rack).each do |library|
begin
require library
rescue LoadError
raise "== Sinatra cannot run without #{library} installed"
end
end

require File.dirname(__FILE__) + '/sinatra/core_ext/class'
require File.dirname(__FILE__) + '/sinatra/core_ext/hash'

require File.dirname(__FILE__) + '/sinatra/logger'
require File.dirname(__FILE__) + '/sinatra/event'
require File.dirname(__FILE__) + '/sinatra/dispatcher'
require File.dirname(__FILE__) + '/sinatra/server'
require File.dirname(__FILE__) + '/sinatra/dsl'

SINATRA_LOGGER = Sinatra::Logger.new(STDOUT)

def set_logger(logger = SINATRA_LOGGER)
[Sinatra::Server, Sinatra::EventContext, Sinatra::Event].each do |klass|
klass.logger = logger
end
end

set_logger

SINATRA_ROOT = File.dirname(__FILE__) + '/..'

Dir.glob(SINATRA_ROOT + '/vendor/*/init.rb').each do |plugin|
require plugin
end

at_exit do
Sinatra::Server.new.start unless Sinatra::Server.running
end
48 changes: 48 additions & 0 deletions lib/sinatra/core_ext/class.rb
@@ -0,0 +1,48 @@
# Extends the class object with class and instance accessors for class attributes,
# just like the native attr* accessors for instance attributes.
class Class # :nodoc:
def cattr_reader(*syms)
syms.flatten.each do |sym|
next if sym.is_a?(Hash)
class_eval(<<-EOS, __FILE__, __LINE__)
unless defined? @@#{sym}
@@#{sym} = nil
end
def self.#{sym}
@@#{sym}
end
def #{sym}
@@#{sym}
end
EOS
end
end

def cattr_writer(*syms)
options = syms.last.is_a?(Hash) ? syms.pop : {}
syms.flatten.each do |sym|
class_eval(<<-EOS, __FILE__, __LINE__)
unless defined? @@#{sym}
@@#{sym} = nil
end
def self.#{sym}=(obj)
@@#{sym} = obj
end
#{"
def #{sym}=(obj)
@@#{sym} = obj
end
" unless options[:instance_writer] == false }
EOS
end
end

def cattr_accessor(*syms)
cattr_reader(*syms)
cattr_writer(*syms)
end
end
7 changes: 7 additions & 0 deletions lib/sinatra/core_ext/hash.rb
@@ -0,0 +1,7 @@
class Hash

def symbolize_keys
self.inject({}) { |h,(k,v)| h[k.to_sym] = v; h }
end

end
42 changes: 42 additions & 0 deletions lib/sinatra/dispatcher.rb
@@ -0,0 +1,42 @@
module Sinatra

DEFAULT_HEADERS = { 'Content-Type' => 'text/html' }

class Dispatcher

def headers
DEFAULT_HEADERS
end

def call(env)
@request = Rack::Request.new(env)

event = EventManager.events.detect(lambda { not_found }) do |e|
e.path == @request.path_info && e.verb == @request.request_method.downcase.intern
end

result = event.attend(@request)

[result.status, headers.merge(result.headers), result.body]
rescue => e
puts "#{e.message}:\n\t#{e.backtrace.join("\n\t")}"
end

private

def not_found
Event.new(:get, nil) do
status 404
views_dir SINATRA_ROOT + '/files'

if request.path_info == '/'
erb :default_index
else
erb :not_found
end
end
end

end

end
11 changes: 11 additions & 0 deletions lib/sinatra/dsl.rb
@@ -0,0 +1,11 @@
module Kernel

%w( get post put delete ).each do |verb|
eval <<-end_eval
def #{verb}(path, &block)
Sinatra::Event.new(:#{verb}, path, &block)
end
end_eval
end

end
94 changes: 94 additions & 0 deletions lib/sinatra/event.rb
@@ -0,0 +1,94 @@
module Sinatra

module EventManager

extend self

def events
@events || []
end

def register_event(event)
(@events ||= []) << event
end

end

class EventContext

cattr_accessor :logger

attr_reader :request

def initialize(request)
@request = request
@headers = {}
end

def status(value = nil)
@status = value if value
@status || 200
end

def body(value = nil)
@body = value if value
@body || ''
end

# This allows for:
# header 'Content-Type' => 'text/html'
# header 'Foo' => 'Bar'
# or
# headers 'Content-Type' => 'text/html',
# 'Foo' => 'Bar'
#
# Whatever blows your hair back
def headers(value = nil)
@headers.merge!(value) if value
@headers
end
alias :header :headers

def params
@params ||= @request.params.symbolize_keys
end

end

class Event

cattr_accessor :logger

attr_reader :path, :verb

def initialize(verb, path, &block)
@verb = verb
@path = path
@block = block
EventManager.register_event(self)
end

def attend(request)
begin
context = EventContext.new(request)
context.instance_eval(&@block) if @block
log_event(request, context, nil)
context
rescue => e
context.status 500
log_event(request, context, e)
context
end
end
alias :call :attend

private

def log_event(request, context, e)
logger.info "#{request.request_method} #{request.path_info} | Status: #{context.status} | Params: #{context.params.inspect}"
logger.exception(e) if e
end

end

end
21 changes: 21 additions & 0 deletions lib/sinatra/logger.rb
@@ -0,0 +1,21 @@
module Sinatra

class Logger

def initialize(steam)
@stream = steam
end

%w(info debug error warn).each do |n|
define_method n do |message|
@stream.puts message
end
end

def exception(e)
error "#{e.message}:\n\t#{e.backtrace.join("\n\t")}"
end

end

end
26 changes: 26 additions & 0 deletions lib/sinatra/server.rb
@@ -0,0 +1,26 @@
module Sinatra

class Server

cattr_accessor :logger
cattr_accessor :running

def start
begin
Rack::Handler::Mongrel.run(Sinatra::Dispatcher.new, :Port => 4567) do |server|
logger.info "== Sinatra has taken the stage on port #{server.port}!"
trap("INT") do
server.stop
self.class.running = false
logger.info "\n== Sinatra has ended his set (crowd applauds)"
end
end
self.class.running = true
rescue => e
logger.exception e
end
end

end

end

0 comments on commit 72be291

Please sign in to comment.