1
0
Fork 0
mirror of https://github.com/sinatra/sinatra synced 2023-03-27 23:18:01 -04:00

this is it

This commit is contained in:
blake.mizerany@gmail.com 2007-09-08 23:51:24 +00:00
commit 72be291da2
17 changed files with 477 additions and 0 deletions

20
examples/hello/test.rb Normal file
View file

@ -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

View file

@ -0,0 +1 @@
<%= 1 + 3 %>

1
files/default_index.erb Normal file
View file

@ -0,0 +1 @@
Default Index!!!!!!!

52
files/not_found.erb Normal file
View file

@ -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
lib/sinatra.rb Normal file
View file

@ -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

View file

@ -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

View file

@ -0,0 +1,7 @@
class Hash
def symbolize_keys
self.inject({}) { |h,(k,v)| h[k.to_sym] = v; h }
end
end

42
lib/sinatra/dispatcher.rb Normal file
View file

@ -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
lib/sinatra/dsl.rb Normal file
View file

@ -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
lib/sinatra/event.rb Normal file
View file

@ -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
lib/sinatra/logger.rb Normal file
View file

@ -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
lib/sinatra/server.rb Normal file
View file

@ -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

41
test/helper.rb Normal file
View file

@ -0,0 +1,41 @@
require File.dirname(__FILE__) + '/../lib/sinatra'
%w(mocha test/spec).each do |library|
begin
require library
rescue
STDERR.puts "== Sinatra's tests need #{library} to run."
end
end
Sinatra::Server.running = true
class Test::Unit::TestCase
def get_it(path)
request = Rack::MockRequest.new(Sinatra::Dispatcher.new)
@response = request.get path
end
def post_it(path)
request = Rack::MockRequest.new(Sinatra::Dispatcher.new)
@response = request.post path
end
def response
@response
end
def status
@response.status
end
def text
@response.body
end
def headers
@response.headers
end
end

View file

@ -0,0 +1,30 @@
require File.dirname(__FILE__) + '/../helper'
describe "When a dispatcher receives a request" do
it "should attend to the event" do
Sinatra::Event.new(:get, '/') do
body 'this is the index as a get'
end
get_it "/"
status.should.equal 200
text.should.equal 'this is the index as a get'
headers['Content-Type'].should.equal 'text/html'
post_it "/test"
status.should.equal 404
text.scan("Not Found :: Sinatra").size.should.equal 1
headers['Content-Type'].should.equal 'text/html'
get_it '/foo'
status.should.equal 404
text.scan("Not Found :: Sinatra").size.should.equal 1
end
end

View file

@ -0,0 +1,17 @@
require File.dirname(__FILE__) + '/../helper'
describe "Event" do
it "should return 500 if exception thrown" do
set_logger stub_everything
event = Sinatra::Event.new(:get, nil) do
raise 'whaaaa!'
end
result = event.attend(stub_everything)
result.status.should.equal 500
end
end

3
vendor/erb/init.rb vendored Normal file
View file

@ -0,0 +1,3 @@
require File.dirname(__FILE__) + '/lib/erb'
Sinatra::EventContext.send(:include, Sinatra::Erb::InstanceMethods)

27
vendor/erb/lib/erb.rb vendored Normal file
View file

@ -0,0 +1,27 @@
require 'erb'
module Sinatra
module Erb
module InstanceMethods
def erb(content)
s = if content.is_a?(Symbol)
open("%s/%s.erb" % [views_dir, content]).read
else
content
end
body ERB.new(s).result(binding)
end
def views_dir(value = nil)
@views_dir = value if value
@views_dir || File.dirname($0) + '/views'
end
end
end
end