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

starting again

This commit is contained in:
Blake Mizerany 2007-11-21 01:47:29 -08:00
parent 03626a1ec4
commit e53fb2bcad
53 changed files with 60 additions and 2225 deletions

View file

@ -1,8 +0,0 @@
v0.1.7 FIXES:
* test/development/production helpers changed to config_for. There was a problem with "test" fubar'ing libraries such as the new release of Sequel
* StaticEvent now makes sure the file it's looking for is really a file.
v0.1.6 Additions: require users vendor directory on load
v0.1.5 Mutex and before-filters
v0.1.0 Released!

22
LICENSE
View file

@ -1,22 +0,0 @@
Copyright (c) 2007 Blake Mizerany
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,52 +0,0 @@
CHANGELOG
examples/hello/hello.rb
examples/hello/views/hello.erb
examples/todo/todo.rb
files/default_index.erb
files/error.erb
files/logo.png
files/not_found.erb
lib/sinatra/context/renderer.rb
lib/sinatra/context.rb
lib/sinatra/core_ext/array.rb
lib/sinatra/core_ext/class.rb
lib/sinatra/core_ext/hash.rb
lib/sinatra/core_ext/kernel.rb
lib/sinatra/core_ext/metaid.rb
lib/sinatra/core_ext/module.rb
lib/sinatra/core_ext/symbol.rb
lib/sinatra/dispatcher.rb
lib/sinatra/dsl.rb
lib/sinatra/environment.rb
lib/sinatra/event.rb
lib/sinatra/irb.rb
lib/sinatra/loader.rb
lib/sinatra/logger.rb
lib/sinatra/options.rb
lib/sinatra/rack_ext/request.rb
lib/sinatra/route.rb
lib/sinatra/server.rb
lib/sinatra/sessions.rb
lib/sinatra/test_methods.rb
lib/sinatra.rb
LICENSE
Manifest
RakeFile
README
site/index.htm
site/index.html
site/logo.png
test/helper.rb
test/sinatra/dispatcher_test.rb
test/sinatra/event_test.rb
test/sinatra/renderer_test.rb
test/sinatra/request_test.rb
test/sinatra/route_test.rb
test/sinatra/static_files/foo.txt
test/sinatra/static_files_test.rb
test/sinatra/url_test.rb
vendor/erb/init.rb
vendor/erb/lib/erb.rb
vendor/haml/init.rb
vendor/haml/lib/haml.rb
Rakefile

119
README
View file

@ -1,119 +0,0 @@
Sinatra (C) 2007 By Blake Mizerany
= Classy web-development dressed in a DSL
== Install!
sudo gem install sinatra -y
== Use!
I'm going to move quick. I'll let you drool at your own pace.
* Create a file called lyrics.rb (or any name you like)
* Add
require 'rubygems'
require 'sinatra'
* Run (yes, with just ruby)
% ruby lyrics.rb
== Sinata has taken the stage on port 4567!
* Take a moment and view the default page http://localhost:4567. Go ahead and bask in it's glory.
* Notice:
* It didn't create any page to show you that default page (just a cool thing to see, that's all)
* There was nothing generated other than a log file
* Sinatra is a really cool name for a web-framework that's a DSL
* Modify lyrics.rb by adding:
get '/' do
'Hello World'
end
* Refresh (no need to restart Sinatra):
http://localhost:4567
* Modify again (then refresh) -- And yes, this presentation logic can be quickly extracted to a template.. see below.
get '/' do
<<-HTML
<form action='/' method="POST">
<input type="text" name="name" />
<input type="submit" value="Say my name!" />
</form>
HTML
end
post '/' do
"Hello #{params[:name] || 'World'}!"
end
* Test (lyrics_test.rb) -- We should be doing this first... for the purposes of this tutorial, we're doing it here
require 'sinatra/test/spec'
require 'lyrics'
context "My app" do
specify "should have a form" do
get_it '/'
response.should.be.ok
body.scan('form').size.should.equal 1
post_it '/', :name => 'Sinatra'
response.should.be.ok
body.should.equal 'Hello Sinatra!'
end
end
For more test helpers see: Sinatra::Test::Methods and http://rack.rubyforge.org/doc/classes/Rack/Response/Helpers.html
* Now you try:
Use the Sinatra::Erb::EventContext or Sinatra::Haml::EventContext to do the same. Do them inline and as template files.
* Learn more cool stuff:
see Sinatra::Dsl
* Create your own plugins!
1. Create a 'vendor' directory in your app directory
2. Lay it out like:
myapp.rb : root
|- vendor
| - plugin_name
| - init.rb # load and hook here
| - lib
|- modules/classes here
3. Use it in your app!
see $SINATRA_GEM_ROOT/vendor/erb or $SINATRA_GEM_ROOT/vendor/erb for examples.
* Tell!
We would love to here what you're doing with Sinatra and any cool patches/features you would like. (blake { dot } mizerany [ at ] gmail)
* Talk!
IRC (irc.freenode.com #sinatra)
Mailing List (sinatrarb@googlegroups.com)
* Contribute
We're using git as our scm.. cuz.. it rocks. You can get the latest source from http://repo.or.cz/w/sinatra.git
NOTE: You can also get tar'd snapshots of each commit there too. So technically you don't need git to get the latest code.
It's probably going to happen.. you'll find a bug. Please help by:
* Sending a message to sintrarb@googlegroups.com with BUG: at the start of the subject (I'm working on a better tracking system)
* Please send patches or pull requests to (blake { dot } mizerany [ at ] gmail) don't forget the dot com. ;)
== Thanks!
- Ezra Zygmuntowicz (http://brainspl.at) for answering all those random questions over IM and all the poached code
- Ditto to Chris Wanstrath (errtheblog.com) and helping me keep things simple, and some cool tricks
- Ari Lerner over at CitrusByte for ideas, code, and enthusiasm
- Christian Neukirchen for Rack (http://rack.rubyforge.org/)
- Koshi (http://www.songbirdnest.com/jkoshi/blog) here at POTI, Inc. for the Sinatra mark
- Pete Golibersuch for the hat logo
- John Philip Green (http://www.linkedin.com/in/johngreen) for motivation and evangelism
- The team here at songbirdnest.com for cool ideas

View file

@ -1,35 +0,0 @@
require 'rake/testtask'
require 'ftools'
Version = '0.1.0'
begin
require 'rubygems'
gem 'echoe'
ENV['RUBY_FLAGS'] = ""
require 'echoe'
Echoe.new('sinatra') do |p|
p.rubyforge_name = 'sinatra'
p.dependencies = ['mongrel >=1.0.1', 'rack >=0.2.0']
p.summary = "Sinatra is a classy web-framework dressed in a DSL"
p.description = "Sinatra is a classy web-framework dressed in a DSL"
p.url = "http://sinatra.rubyforge.org/"
p.author = 'Blake Mizerany'
p.email = "blake.mizerany@gmail.com"
p.test_pattern = 'test/**/*_test.rb'
p.include_rakefile = true
p.rdoc_pattern = ['README', 'LICENSE'] + Dir.glob('lib/**/*.rb') + Dir.glob('vendor/**/*.rb') + Dir.glob('lib/sinatra/test/*.rb')
p.docs_host = "bmizerany@rubyforge.org:/var/www/gforge-projects/"
end
rescue LoadError
end
desc 'Clear all the log files from here down'
task :remove_logs do
Dir.glob(Dir.pwd + '/**/*.log') do |logfile|
FileUtils.rm(logfile)
puts 'Removed: %s' % logfile
end
end

View file

@ -1,26 +0,0 @@
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../../lib'
require 'sinatra'
config_for(:production) do
get 404 do
"Not sure what you're looking for .. try something else."
end
end
get '/' do
"Hello World!"
end
get '/erb.xml' do
header 'Content-Type' => 'application/xml'
'<this_is_xml/>'
end
get '/erb' do
erb :hello
end
get '/erb2' do
erb 'Hello <%= params[:name].capitalize || "World" %> 2!'
end

View file

@ -1 +0,0 @@
Hello <%= params[:name].capitalize || 'World' %>!

View file

@ -1,42 +0,0 @@
<!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>Sinatra has taken the stage!</title>
</head>
<body>
<style type="text/css" media="screen">
body {
color: #333;
font-size: 1.5em;
}
#content {
margin: 0 auto;
text-align: center;
width: 500px;
}
#content pre {
text-align: left;
background-color: #D8D8D8;
padding: 10px;
}
</style>
<div id="content">
<div id="banner">
<img src="http://sinatra.rubyforge.org/logo.png">
</div>
<div id="content">
<h3>Sing this diddy to move on:</h3>
<pre>
get "/" do
... your code here ..
end</pre>
</div>
</div>
</body>
</html>

View file

@ -1,9 +0,0 @@
<h2>Error!</h2>
<h3>
<%= @error.message %>
</h3>
<div id="backtrace">
<%= @error.backtrace.join('<br/>') %>
</div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View file

@ -1,52 +0,0 @@
<!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>Sing this one:</p>
<pre><%= request.request_method.downcase %> '<%= request.path_info %>' do
html "Replace this with your code."
end</pre>
</div>
</div>
</div>
</body>
</html>

View file

@ -1,50 +1,65 @@
# Copyright (c) 2007 Blake Mizerany require "rubygems"
# require "rack"
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
%w(rubygems rack).each do |library| class String
begin def to_param
require library URI.escape(self)
rescue LoadError end
raise "== Sinatra cannot run without #{library} installed"
def from_param
URI.unescape(self)
end end
end end
SINATRA_ROOT = File.dirname(__FILE__) + '/..' class Symbol
def to_proc
require File.dirname(__FILE__) + '/sinatra/loader' Proc.new { |*args| args.shift.__send__(self, *args) }
end
Sinatra::Loader.load_files Dir.glob(SINATRA_ROOT + '/lib/sinatra/core_ext/*.rb')
Sinatra::Loader.load_files Dir.glob(SINATRA_ROOT + '/lib/sinatra/rack_ext/*.rb')
Sinatra::Loader.load_files Dir.glob(SINATRA_ROOT + '/lib/sinatra/*.rb')
Sinatra::Environment.prepare
Sinatra::Loader.load_files Dir.glob(SINATRA_ROOT + '/vendor/*/init.rb')
Sinatra::Loader.load_files Dir.glob(File.dirname($0) + '/vendor/*/init.rb')
at_exit do
raise $! if $!
Sinatra::Environment.prepare_loggers unless Sinatra::Environment.test?
Sinatra::Irb.start! if Sinatra::Options.console
Sinatra::Server.new.start unless Sinatra::Server.running
end end
class Array
def to_hash
self.inject({}) { |h, (k, v)| h[k] = v; h }
end
end
module Sinatra
extend self
def request_types
@request_types ||= %w(GET PUT POST DELETE)
end
def events
@events ||= Hash.new do |hash, key|
hash[key] = [] if request_types.include?(key)
end
end
class Route
URI_CHAR = '[^/?:,&#]'.freeze unless defined?(URI_CHAR)
PARAM = /:(#{URI_CHAR}+)/.freeze unless defined?(PARAM)
def initialize(path, &b)
@path, @block = path, b
@param_keys = []
regex = path.to_s.gsub(PARAM) do
@param_keys << $1.intern
"(#{URI_CHAR}+)"
end
@pattern = /^#{regex}$/
@struct = Struct.new(:block, :params)
end
def match(path)
return nil unless path =~ @pattern
params = @param_keys.zip($~.captures.map(&:from_param)).to_hash
@struct.new(@block, params)
end
end
end

View file

@ -1,94 +0,0 @@
require File.dirname(__FILE__) + '/context/renderer'
module Sinatra
class EventContext
cattr_accessor :logger
cattr_accessor :reraise_errors
attr_reader :request, :response
include Sinatra::Renderer
def initialize(request) #:nodoc:
@request = request
@response = Rack::Response.new
@response.body = nil
end
# Sets or returns the status
def status(value = nil)
@response.status = value if value
@response.status || 200
end
# Sets or returns the body
# *Usage*
# body 'test'
# or
# body do
# 'test'
# end
# both are the same
#
def body(value = nil, &block)
@response.body = value if value
@response.body = block.call if block
@response.body
end
# Renders an exception to +body+ and sets status to 500
def error(value = nil)
raise value if value.kind_of?(Exception) && reraise_errors
if value
status 500
@error = value
erb :error, :views_directory => SINATRA_ROOT + '/files/'
end
@error
end
def set_cookie(key, value)
@response.set_cookie(key, value)
end
def delete_cookie(key, value)
@response.delete_cookie(key, value)
end
# Sets or returns response headers
#
# *Usage*
# 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)
@response.headers.merge!(value) if value
@response.headers
end
alias :header :headers
# Returns a Hash of params. Keys are symbolized
def params
@params ||= @request.params.symbolize_keys
end
# Redirect to a url
def redirect(path)
logger.info "Redirecting to: #{path}"
status 302
header 'Location' => path
end
def log_event #:nodoc:
logger.info "#{request.request_method} #{request.path_info} | Status: #{status} | Params: #{params.inspect}"
logger.exception(error) if error
end
end
end

View file

@ -1,75 +0,0 @@
module Sinatra
# The magic or rendering happens here. This is included in Sinatra::EventContext on load.
#
# These methods are the foundation for Sinatra::Erb and Sinatra::Haml and allow you to quickly
# create custom wrappers for your favorite rendering engines outside of erb and haml.
module Renderer
Layouts = Hash.new # :nodoc:
DEFAULT_OPTIONS = {
:views_directory => 'views',
:layout => :layout
}
# Renders templates from a string or file and handles their layouts:
#
# Example:
# module MyRenderer
# def my(template, options, &layout)
# render(template, :my, options, &layout)
# end
#
# def render_my(template)
# template.capitalize # It capitalizes templates!!!!! WOW!
# end
# end
# Sinatra::EventContext.send :include, MyRenderer
#
# get '/' do
# my "something"
# end
#
# get_it '/' # => 'Something'
#
# The second method is named render_extname. render will call this dynamicly
#
# paramaters:
# * +template+ If String, renders the string. If Symbol, reads from file with the basename of the Symbol; uses +renderer+ for extension.
# * +renderer+ A symbol defining the render_ method to call and the extension append to +template+ when looking in the +views_directory+
# * +options+ An optional Hash of options (see next section)
#
# options:
# * +:views_directory+ Allows you to override the default 'views' directory an look for the template in another
# * +:layout+ Which layout to use (see Sinatra::Dsl). false to force a render with no layout. Defaults to :default layout
#
def render(template, renderer, options = {})
options = DEFAULT_OPTIONS.merge(options)
layout = block_given? ? yield : Layouts[options[:layout]]
result_method = 'render_%s' % renderer
if layout
send(result_method, layout) { send(result_method, determine_template(template, renderer, options)) }
else
send(result_method, determine_template(template, renderer, options))
end
end
protected
def determine_template(template, ext, options)
if template.is_a?(Symbol)
File.read("%s/%s.%s" % [options[:views_directory], template, ext])
else
template
end
end
end
end

View file

@ -1,5 +0,0 @@
class Array
def to_hash
self.inject({}) { |h, (k, v)| h[k] = v; h }
end
end

View file

@ -1,49 +0,0 @@
# 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

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

View file

@ -1,16 +0,0 @@
module Kernel
# (Taken from ActiveSupport)
# Sets $VERBOSE to nil for the duration of the block and back to its original value afterwards.
#
# silence_warnings do
# value = noisy_call # no warning voiced
# end
#
# noisy_call # warning voiced
def silence_warnings
old_verbose, $VERBOSE = $VERBOSE, nil
yield
ensure
$VERBOSE = old_verbose
end
end

View file

@ -1,18 +0,0 @@
# Compliments to why for this:
# http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html
class Object
# The hidden singleton lurks behind everyone
def metaclass; class << self; self; end; end
def meta_eval &blk; metaclass.instance_eval &blk; end
# Adds methods to a metaclass
def meta_def name, &blk
meta_eval { define_method name, &blk }
end
# Defines an instance method within a class
def class_def name, &blk
class_eval { define_method name, &blk }
end
end

View file

@ -1,11 +0,0 @@
class Module
def attr_with_default(sym, default)
define_method "#{sym}=" do |obj|
instance_variable_set("@#{sym}", obj)
end
define_method sym do
instance_variable_get("@#{sym}") || default
end
end
end

View file

@ -1,5 +0,0 @@
class Symbol
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end
end

View file

@ -1,23 +0,0 @@
module Sinatra
class Dispatcher
cattr_accessor :logger
def call(env)
Loader.reload! if Options.environment == :development
@request = Rack::Request.new(env)
event = EventManager.determine_event(
@request.request_method.downcase.intern,
@request.path_info
)
result = event.attend(@request)
result.response.to_a
end
end
end

View file

@ -1,169 +0,0 @@
module Sinatra
module Dsl
# Define an Event that responds to a +path+ on GET method
#
# The +path+ can be a template (i.e. '/:foo/bar/:baz'). When recognized, it will add <tt>:foo</tt> and <tt>:baz</tt> to +params+ with their values.
#
# Example:
# # Going RESTful
#
# get '/' do
# .. show stuff ..
# end
#
# post '/' do
# .. add stuff ..
# redirect '/'
# end
#
# put '/:id' do
# .. update params[:id] ..
# redirect '/'
# end
#
# delete '/:id' do
# .. delete params[:id] ..
# redirect '/'
# end
#
# BIG NOTE: PUT and DELETE are trigged when POSTing to their paths with a <tt>_method</tt> param whose value is PUT or DELETE
#
def get(path, &block)
Sinatra::Event.new(:get, path, &block)
end
# Same as get but responds to POST
def post(path, &block)
Sinatra::Event.new(:post, path, &block)
end
# Same as get but responds to PUT
#
# BIG NOTE: PUT and DELETE are trigged when POSTing to their paths with a <tt>_method</tt> param whose value is PUT or DELETE
def put(path, &block)
Sinatra::Event.new(:put, path, &block)
end
# Same as get but responds to DELETE
#
# BIG NOTE: PUT and DELETE are trigged when POSTing to their paths with a <tt>_method</tt> param whose value is PUT or DELETE
def delete(path, &block)
Sinatra::Event.new(:delete, path, &block)
end
# Run given block after each Event's execution
# Usage:
# before_attend do
# logger.debug "After event attend!"
# end
# or
# before_attend :authorize # authorize is a helper method defined using helpers
#
# Stop execution using - throw :halt
# before_attend do
# throw :halt, 401 unless has_access?
# end
# Throw a Symbol to execute a helper method
# Throw a String to render it as the content
# Throw a Fixnum to set the status
#
def before_attend(filter_name = nil, options ={}, &block)
Sinatra::Event.before_attend(filter_name, options, &block)
end
# Run given block after each Event's execution
# Example:
# after_attend do
# logger.debug "After event attend!"
# end
# or
# after_attend :clean_up # clean_up is a helper method defined using helpers
#
def after_attend(filter_name = nil, options ={}, &block)
Sinatra::Event.after_attend(filter_name, options, &block)
end
# Add methods to each event for use during execution
#
# Example:
# helpers do
# def foo
# 'foo!'
# end
# end
#
# get '/bar' do
# foo
# end
#
# get_it '/bar' # => 'foo!'
#
def helpers(&block)
Sinatra::EventContext.class_eval(&block)
end
# Maps a path to a physical directory containing static files
#
# Example:
# static '/p', 'public'
#
def static(path, root)
Sinatra::StaticEvent.new(path, root)
end
# Execute block if in environment is equal to env (Used for configuration)
def config_for(env = :development)
yield if Sinatra::Options.environment == env.to_sym
end
# Define named layouts (default name is <tt>:layout</tt>)
#
# Examples:
# # Default layout in Erb
# layout do
# '-- <%= yield %> --'
# end
#
# # Named layout in Haml
# layout :for_haml do
# '== XXXX #{yield} XXXX'
# end
#
# # Loads layout named <tt>:"foo.erb"</tt> from file (default behaviour if block is omitted)
# layout 'foo.erb' # looks for foo.erb. This is odd an is being re-thought
#
# def layout(name = :layout, options = {})
# Layouts[name] = unless block_given?
# File.read("%s/%s" % [options[:views_directory] || 'views', name])
# else
# yield
# end
# end
#
# Cool trick:
#
# # Send a one-time layout to renderer method
# get '/cooltrick' do
# erb 'wicked' do
# 'Cool <%= yield %> Trick'
# end
# end
#
# get_it '/cooltrick' # => 'Cool wicked Trick'
#
def layout(name = :layout, options = {})
Sinatra::Renderer::Layouts[name] = unless block_given?
File.read("%s/%s" % [options[:views_directory] || 'views', name])
else
yield
end
end
end
end
include Sinatra::Dsl

View file

@ -1,19 +0,0 @@
module Sinatra
module Environment
extend self
def test?
Options.environment == :test
end
def prepare
Options.parse!(ARGV)
end
def prepare_loggers(logger = Logger.new(open(Options.log_file, 'w')))
[Server, EventContext, Event, Dispatcher].each do |klass|
klass.logger = logger
end
end
end
end

View file

@ -1,244 +0,0 @@
require 'thread'
module Sinatra
module EventManager # :nodoc:
extend self
def reset!
@events.clear if @events
end
def events
@events || []
end
def register_event(event)
(@events ||= []) << event
end
def determine_event(verb, path, if_nil = :present_error)
event = events.find(method(if_nil)) do |e|
e.verb == verb && e.recognize(path)
end
end
def present_error
determine_event(:get, '404', :not_found)
end
def not_found
Event.new(:get, 'not_found', false) do
status 404
if request.path_info == '/' && request.request_method == 'GET'
erb :default_index, :views_directory => SINATRA_ROOT + '/files'
else
erb :not_found, :views_directory => SINATRA_ROOT + '/files'
end
end
end
end
class Event # :nodoc:
cattr_accessor :logger
cattr_accessor :after_filters
cattr_accessor :before_filters
@@mutex = Mutex.new
self.before_filters = []
self.after_filters = []
def self.reset!
self.before_filters.clear
self.after_filters.clear
end
def self.before_attend(method_name = nil, options ={}, &block)
setup_filter(:before_filters, method_name, options, &block)
end
def self.after_attend(method_name = nil, options = {}, &block)
setup_filter(:after_filters, method_name, options, &block)
end
def self.setup_filter(filter_set_name, method_name, options = {}, &block)
raise "Must specify method or block" if method_name.nil? and !block_given?
value = if block_given?
block
else
method_name
end
insert_index = options[:infront] == true ? 0 : -1
send(filter_set_name).insert(insert_index, value)
end
attr_reader :path, :verb
def initialize(verb, path, register = true, &block)
@verb = verb
@path = path
@route = Route.new(path)
@block = block
EventManager.register_event(self) if register
end
def attend(request)
request.params.merge!(@route.params)
context = EventContext.new(request)
run_safely do
caught = catch(:halt) do
call_filters(before_filters, context)
end
body = case caught
when :filter_chain_completed
begin
context.instance_eval(&@block) if @block
rescue => e
context.error e
end
when Symbol
context.send(caught)
when String
caught
when Fixnum
context.status caught
end
context.body context.body || body || ''
call_filters(after_filters, context)
end
context.log_event
context
end
alias :call :attend
def recognize(path)
@route.recognize(path)
end
private
def run_safely
if Options.use_mutex?
@@mutex.synchronize do
yield
end
else
yield
end
end
# Adapted from Merb
# calls a filter chain according to rules.
def call_filters(filter_set, context)
filter_set.each do |filter|
case filter
when Symbol, String
context.send(filter)
when Proc
context.instance_eval(&filter)
end
end
:filter_chain_completed
end
end
class StaticEvent < Event # :nodoc:
def initialize(path, root, register = true)
@root = root
super(:get, path, register)
end
def recognize(path)
filename = physical_path_for(path)
File.exists?(filename) && File.file?(filename)
end
def physical_path_for(path)
path.gsub(/^#{@path}/, @root)
end
def attend(request)
@filename = physical_path_for(request.path_info)
context = EventContext.new(request)
context.body self
context.header 'Content-Type' => MIME_TYPES[File.extname(@filename)[1..-1]]
context.header 'Content-Length' => File.size(@filename).to_s
context
end
def each
File.open(@filename, "rb") do |file|
while part = file.read(8192)
yield part
end
end
end
# :stopdoc:
# From WEBrick.
MIME_TYPES = {
"ai" => "application/postscript",
"asc" => "text/plain",
"avi" => "video/x-msvideo",
"bin" => "application/octet-stream",
"bmp" => "image/bmp",
"class" => "application/octet-stream",
"cer" => "application/pkix-cert",
"crl" => "application/pkix-crl",
"crt" => "application/x-x509-ca-cert",
#"crl" => "application/x-pkcs7-crl",
"css" => "text/css",
"dms" => "application/octet-stream",
"doc" => "application/msword",
"dvi" => "application/x-dvi",
"eps" => "application/postscript",
"etx" => "text/x-setext",
"exe" => "application/octet-stream",
"gif" => "image/gif",
"htm" => "text/html",
"html" => "text/html",
"jpe" => "image/jpeg",
"jpeg" => "image/jpeg",
"jpg" => "image/jpeg",
"lha" => "application/octet-stream",
"lzh" => "application/octet-stream",
"mov" => "video/quicktime",
"mpe" => "video/mpeg",
"mpeg" => "video/mpeg",
"mpg" => "video/mpeg",
"pbm" => "image/x-portable-bitmap",
"pdf" => "application/pdf",
"pgm" => "image/x-portable-graymap",
"png" => "image/png",
"pnm" => "image/x-portable-anymap",
"ppm" => "image/x-portable-pixmap",
"ppt" => "application/vnd.ms-powerpoint",
"ps" => "application/postscript",
"qt" => "video/quicktime",
"ras" => "image/x-cmu-raster",
"rb" => "text/plain",
"rd" => "text/plain",
"rtf" => "application/rtf",
"sgm" => "text/sgml",
"sgml" => "text/sgml",
"tif" => "image/tiff",
"tiff" => "image/tiff",
"txt" => "text/plain",
"xbm" => "image/x-xbitmap",
"xls" => "application/vnd.ms-excel",
"xml" => "text/xml",
"xpm" => "image/x-xpixmap",
"xwd" => "image/x-xwindowdump",
"zip" => "application/zip",
}
# :startdoc:
end
end

View file

@ -1,56 +0,0 @@
module Sinatra
# Sinatra Irb is entered via <tt>ruby myapp.rb -c</tt> (replace myapp.rb with your app filename)
#
# Be sure to also check out Sinatra::TestMethods for more cool stuff when your in Irb
#
module Irb
extend self
# taken from merb
def start! #:nodoc:
Object.send(:include, TestMethods) # added to allow post_to in console
Object.class_eval do
# Reload all Sinatra and App specific files
def reload!
Loader.reload!
end
# Show the +body+ with result info in your text editor!!! Great Job!
def show!(editor = nil)
editor = editor || ENV['EDITOR']
IO.popen(editor, 'w') do |f|
f.puts "<!--"
f.puts result_info
f.puts "-->"
f.puts
f.puts body
end
nil
end
alias :mate :show!
def result_info #:nodoc:
info = <<-end_info
# Status: #{status}
# Headers: #{headers.inspect}
end_info
end
end
ARGV.clear # Avoid passing args to IRB
require 'irb'
require 'irb/completion'
def exit
exit!
end
if File.exists? ".irbrc"
ENV['IRBRC'] = ".irbrc"
end
IRB.start
exit!
end
end
end

View file

@ -1,31 +0,0 @@
require 'set'
module Sinatra
module Loader
extend self
def reload!
silence_warnings do
EventManager.reset!
load_files loaded_files
load $0
end
end
def load_files(*files)
files = files.flatten
files = files.first if files.first.is_a? Set
files.each do |file|
file = File.expand_path(file)
load file
loaded_files << file
end
end
alias_method :load_file, :load_files
def loaded_files
@loaded_files ||= Set.new
end
end
end

View file

@ -1,22 +0,0 @@
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
@stream.flush
end
end
def exception(e)
error "#{e.message}:\n\t#{e.backtrace.join("\n\t")}"
end
end
end

View file

@ -1,49 +0,0 @@
require 'optparse'
module Sinatra
module Options
extend self
attr_with_default :port, 4567
attr_with_default :environment, :development
attr_with_default :console, nil
attr_with_default :use_mutex, false
alias :use_mutex? :use_mutex
def parse!(args)
return if @environment == :test
OptionParser.new do |opts|
opts.on '-p port', '--port port', 'Set the port (default is 4567)' do |port|
@port = port
end
opts.on '-e environment', 'Set the environment (default if development)' do |env|
@environment = env.intern
end
opts.on '-c', '--console', 'Run in console mode' do
@console = true
end
opts.on '-h', '--help', '-?', 'Show this message' do
puts opts
exit!
end
opts.on '-X', '--mutex', 'Use mutex lock when attending events' do
@use_mutex = true
end
end.parse!(ARGV)
end
def log_file
# TODO find a better way that this
if File.basename($0, '.rb') == 'rake_test_loader' # hack to satisfy rake
'%s.log' % environment
else
File.dirname($0) + ('/%s.log' % environment)
end
end
def set_environment(env)
@environment = env
end
end
end

View file

@ -1,15 +0,0 @@
module Rack #:nodoc:
class Request #:nodoc:
def request_method
if @env['REQUEST_METHOD'] == 'POST' && %w(PUT DELETE).include?(params['_method'])
params['_method'].upcase
else
@env['REQUEST_METHOD']
end
end
end
end

View file

@ -1,65 +0,0 @@
module Sinatra
class Route
SYMBOL_FIND = /:[a-z_]+/.freeze
PARENTHETICAL_SEGMENT_STRING = "([^\/.,;?]+)".freeze
attr_reader :regex, :params
def initialize(template)
@template = template.to_s.strip
@default_params = { :format => 'html' }
@params = {}
extract_keys
genereate_route
end
def recognize(path)
@params.clear
param_values = path.match(@regex).captures.compact rescue nil
if param_values
keys = @keys.size < param_values.size ? @keys.concat([:format]) : @keys
@params = @default_params.merge(@keys.zip(param_values).to_hash)
true
else
false
end
end
private
def extract_keys
@keys = @template.scan(SYMBOL_FIND).map { |raw| eval(raw) }
@keys
end
def genereate_route_without_format
template = @template.dup
template.gsub!(/\.:format$/, '')
to_regex_route(template)
end
def genereate_route_with_format
template = @template.dup
if template =~ /\.:format$|\.([\w\d]+)$/
@default_params[:format] = $1 if $1
else
template << '.:format'
end
to_regex_route(template)
end
def to_regex_route(template)
/^#{template.gsub(/\./, '\.').gsub(SYMBOL_FIND, PARENTHETICAL_SEGMENT_STRING)}$/
end
def genereate_route
@regex = Regexp.union(genereate_route_without_format, genereate_route_with_format)
end
end
end

View file

@ -1,57 +0,0 @@
require 'fileutils'
module Sinatra
class Server
cattr_accessor :logger
cattr_accessor :running
def start
begin
tail_thread = tail(Options.log_file)
Rack::Handler::Mongrel.run(Dispatcher.new, :Port => Options.port) do |server|
puts "== Sinatra has taken the stage on port #{server.port}!"
trap("INT") do
server.stop
self.class.running = false
puts "\n== Sinatra has ended his set (crowd applauds)"
end
end
self.class.running = true
rescue Errno::EADDRINUSE => e
puts "== Someone is already performing on port #{Options.port}!"
logger.exception e
rescue => e
logger.exception e
ensure
tail_thread.kill if tail_thread
end
end
private
def tail(log_file)
FileUtils.touch(log_file)
cursor = File.size(log_file)
last_checked = Time.now
tail_thread = Thread.new do
File.open(log_file, 'r') do |f|
loop do
f.seek cursor
if f.mtime > last_checked
last_checked = f.mtime
contents = f.read
cursor += contents.length
print contents
end
sleep 1
end
end
end
tail_thread
end
end
end

View file

@ -1,62 +0,0 @@
require 'uri'
module Sinatra
# These methods are for integration testing without an internet connection. They are available in Test::Unit::TestCase and when in Irb.
module Test
module Methods
# get_it, post_it, put_it, delete_it
# Executes the method and returns the result of the body
#
# options:
# +:params+ a hash of name parameters
#
# Example:
# get_it '/', :name => 'Blake' # => 'Hello Blake!'
#
%w(get post put delete).each do |verb|
module_eval <<-end_eval
def #{verb}_it(path, params = {})
request = Rack::MockRequest.new(Sinatra::Dispatcher.new)
@response = request.#{verb} path, :input => generate_input(params)
body
end
end_eval
end
# The response returned by the Event
def response
@response || Rack::MockResponse.new(404, {}, '')
end
# The status returned by the event
def status
response.status
end
# The text returned by the event
def text
response.body
end
alias :xml :text
alias :html :text
alias :body :text
# The headers returned by the event
def headers
response.headers
end
private
def generate_input(params)
params.map { |k,v| "#{k}=#{URI.escape(v)}" }.join('&')
end
end
end
end

View file

@ -1,39 +0,0 @@
require File.dirname(__FILE__) + '/methods'
module Sinatra
module Test
module Spec
def self.included(base)
silence_warnings do
require File.dirname(__FILE__) + '/../../sinatra'
require 'test/spec'
end
Server.running = true
Options.set_environment :test
Environment.prepare_loggers
EventContext.reraise_errors = true
end
end
end
end
include Sinatra::Test::Spec
class Test::Spec::TestCase
module InstanceMethods
include Sinatra::Test::Methods
end
alias :initialize_orig :initialize
def initialize(name, parent=nil, superclass=Test::Unit::TestCase)
initialize_orig(name, parent, superclass)
@testcase.setup do
Sinatra::EventManager.reset!
Sinatra::Event.reset!
Sinatra::Renderer::Layouts.clear
end
end
end

View file

@ -1,65 +0,0 @@
require "rubygems"
require "rack"
class String
def to_param
URI.escape(self)
end
def from_param
URI.unescape(self)
end
end
class Symbol
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end
end
class Array
def to_hash
self.inject({}) { |h, (k, v)| h[k] = v; h }
end
end
module Sinatra
extend self
def request_types
@request_types ||= %w(GET PUT POST DELETE)
end
def events
@events ||= Hash.new do |hash, key|
hash[key] = [] if request_types.include?(key)
end
end
class Route
URI_CHAR = '[^/?:,&#]'.freeze unless defined?(URI_CHAR)
PARAM = /:(#{URI_CHAR}+)/.freeze unless defined?(PARAM)
def initialize(path, &b)
@path, @block = path, b
@param_keys = []
regex = path.to_s.gsub(PARAM) do
@param_keys << $1.intern
"(#{URI_CHAR}+)"
end
@pattern = /^#{regex}$/
@struct = Struct.new(:block, :params)
end
def match(path)
return nil unless path =~ @pattern
params = @param_keys.zip($~.captures.map(&:from_param)).to_hash
@struct.new(@block, params)
end
end
end

View file

@ -1,104 +0,0 @@
<!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>Sinatra : Classy web-development dressed in a DSL</title>
</head>
<body>
<style type="text/css" media="screen">
body {
background-color: #fff;
color: #333;
font-size: 0.75em;
}
#container {
width: 600px;
margin: 0 auto;
font-size: 1.5em;
}
#container pre {
font-size: .8em;
background-color: #F5F6C9;
width: 100%;
}
#container note {
font-size: .7em;
}
#banner {
width: 600px;
text-align: center;
}
pre {
padding: 10px;
}
.clear {
clear: both;
}
</style>
<div id="container">
<div id="banner">
<img src='logo.png' />
<h2><em>Classy web-development dressed in a DSL</em></h2>
</div>
<div class="clear"></div>
<div>
<div>
<p>
<strong>Install!</strong><br/>
<pre>gem install sinatra -y</pre>
</p>
<p>
<strong>Require!</strong> (any filename you wish)<br/>
<pre>
# lyrics.rb
require 'rubygems'
require 'sinatra'</pre>
<note>yup.. that's it for a sec</note><br />
</p>
<p>
<strong>Run!</strong><br />
<pre>ruby lyrics.rb</pre>
</p>
<p>
<strong>Bask!</strong><br />
<pre>http://localhost:4567</pre>
</p>
<p>
<strong>Write!</strong>
<pre>
get '/' do
"Now that's a fine looking dame!"
end</pre>
</p>
<p>
<strong>Examples!</strong><br />
<pre><a href="http://repo.or.cz/w/sinatra.git?a=tree;f=examples;h=fd7513e49762738ad945adbb2e15bb31528b4207;hb=HEAD">here</a></pre>
</p>
<p>
<strong>Docs!</strong><br />
<pre><a href="http://sinatra.rubyforge.org/doc/">here</a></pre>
</p>
<p>
<strong>Can you <a href="http://digg.com/programming/Sinatra_Classy_web_development_dressed_in_a_DSL">digg</a> it cats?</strong><br />
<pre><a href="http://sinatra.rubyforge.org/doc/">here</a></pre>
</p>
<p>
<strong>Contribute!</strong><br />
<pre><a href="http://repo.or.cz/w/sinatra.git">using git</a></pre>
</p>
</div>
</div>
</div>
</body>
</html>

View file

@ -1,104 +0,0 @@
<!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>Sinatra : Classy web-development dressed in a DSL</title>
</head>
<body>
<style type="text/css" media="screen">
body {
background-color: #fff;
color: #333;
font-size: 0.75em;
}
#container {
width: 600px;
margin: 0 auto;
font-size: 1.5em;
}
#container pre {
font-size: .8em;
background-color: #F5F6C9;
width: 100%;
}
#container note {
font-size: .7em;
}
#banner {
width: 600px;
text-align: center;
}
pre {
padding: 10px;
}
.clear {
clear: both;
}
</style>
<div id="container">
<div id="banner">
<img src='logo.png' />
<h2><em>Classy web-development dressed in a DSL</em></h2>
</div>
<div class="clear"></div>
<div>
<div>
<p>
<strong>Install!</strong><br/>
<pre>gem install sinatra -y</pre>
</p>
<p>
<strong>Require!</strong> (any filename you wish)<br/>
<pre>
# lyrics.rb
require 'rubygems'
require 'sinatra'</pre>
<note>yup.. that's it for a sec</note><br />
</p>
<p>
<strong>Run!</strong><br />
<pre>ruby lyrics.rb</pre>
</p>
<p>
<strong>Bask!</strong><br />
<pre>http://localhost:4567</pre>
</p>
<p>
<strong>Write!</strong>
<pre>
get '/' do
"Now that's a fine looking dame!"
end</pre>
</p>
<p>
<strong>Examples!</strong><br />
<pre><a href="http://repo.or.cz/w/sinatra.git?a=tree;f=examples;h=fd7513e49762738ad945adbb2e15bb31528b4207;hb=HEAD">here</a></pre>
</p>
<p>
<strong>Docs!</strong><br />
<pre><a href="http://sinatra.rubyforge.org/doc/">here</a></pre>
</p>
<p>
<strong>Can you <a href="http://digg.com/programming/Sinatra_Classy_web_development_dressed_in_a_DSL">digg</a> it cats?</strong><br />
<pre><a href="http://sinatra.rubyforge.org/doc/">here</a></pre>
</p>
<p>
<strong>Contribute!</strong><br />
<pre><a href="http://repo.or.cz/w/sinatra.git">using git</a></pre>
</p>
</div>
</div>
</div>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View file

@ -1,2 +0,0 @@
require File.dirname(__FILE__) + '/../lib/sinatra/test/spec'
require 'mocha'

View file

@ -1,87 +0,0 @@
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 "/"
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
it "should use custom error pages if present" do
Sinatra::Event.new(:get, 404) do
body 'custom 404'
end
get_it('/laksdjf').should.equal 'custom 404'
end
it "should reload app files unless in production" do
Sinatra::Event.new(:get, '/') {}
Sinatra::Options.expects(:environment).returns(:production)
Sinatra::Loader.expects(:reload!).never
get_it '/'
Sinatra::Options.expects(:environment).returns(:development)
Sinatra::Loader.expects(:reload!)
get_it '/'
end
it "should not register not_found (otherwise we'll have a newone in the array for every error)" do
Sinatra::EventManager.events.size.should.equal 0
get_it '/blake'
Sinatra::EventManager.events.size.should.equal 0
end
it "should return blocks result if body not called" do
event = Sinatra::Event.new(:get, '/return_block') do
'no body called'
end
get_it '/return_block'
status.should.equal 200
html.should.equal 'no body called'
end
it "should recognize pretty urls" do
Sinatra::Event.new(:get, '/test/:name') do
params[:name]
end
get_it '/test/blake'
body.should.equal 'blake'
end
it "should respond to DELETE and PUT" do
Sinatra::Event.new(:delete, '/') do
request.request_method
end
# Browser only know GET and POST. DELETE and PUT are signaled by passing in a _method paramater
post_it '/', :_method => 'DELETE'
status.should.equal 200
text.should.equal 'DELETE'
end
end

View file

@ -1,44 +0,0 @@
require File.dirname(__FILE__) + '/../helper'
describe "Event" do
it "should return 500 if exception thrown" do
Sinatra::Environment.prepare_loggers stub_everything
Sinatra::EventContext.any_instance.expects(:reraise_errors).returns(false)
event = Sinatra::Event.new(:get, '/') do
raise 'whaaaa!'
end
result = event.attend(stub_everything(:params => {}, :path_info => '/'))
result.status.should.equal 500
end
it "custom error if present" do
Sinatra::Environment.prepare_loggers stub_everything
event = Sinatra::Event.new(:get, '404') do
body 'custom 404'
end
Sinatra::EventManager.expects(:not_found).never
Sinatra::EventManager.determine_event(:get, '/sdf')
end
it "should show default 404 if custom not present" do
Sinatra::EventManager.expects(:not_found)
Sinatra::EventManager.determine_event(:get, '/asdfsasd')
end
it "should not execute event if halted" do
Sinatra::Event.before_filters << lambda { throw :halt, 'whoa!' }
event = Sinatra::Event.new(:get, '/') do
foo
end
event.expects(:foo).never
get_it('/').should.equal 'whoa!'
end
end

View file

@ -1,19 +0,0 @@
require File.dirname(__FILE__) + '/../helper'
context "Filter" do
specify "befores can be in front" do
before_attend :bar
before_attend :foo, :infront => true
Sinatra::Event.before_filters.should.equal [:foo, :bar]
end
specify "afters can be in front" do
after_attend :bar
after_attend :foo, :infront => true
Sinatra::Event.after_filters.should.equal [:foo, :bar]
end
end

View file

@ -1,21 +0,0 @@
require File.dirname(__FILE__) + '/../helper'
context "Haml" do
specify "does layouts" do
layout do
'%h1== Hello #{yield}'
end
get "/" do
haml 'Ben'
end
get_it '/'
body.should.equal "<h1>Hello Ben</h1>\n"
end
end

View file

@ -1,46 +0,0 @@
require File.dirname(__FILE__) + '/../helper'
class Sinatra::EventContext # :nodoc:
def render_foo(template)
require 'erb'
ERB.new(template).result(binding)
end
end
describe "Renderer" do
before(:each) do
@context = Sinatra::EventContext.new(stub())
end
it "should render render a tempalate" do
@context.render('foo', :foo).should.equal 'foo'
end
it "should render with a layout if given" do
result = @context.render('content', :foo) do
'X <%= yield %> X'
end
result.should.equal 'X content X'
end
it "should render default layout if it exists and layout if no layout name given" do
Sinatra::Renderer::Layouts[:layout] = 'X <%= yield %> Y'
@context.render('foo', :foo).should.equal 'X foo Y'
Sinatra::Renderer::Layouts[:foo] = 'Foo <%= yield %> Layout'
@context.render('bar', :foo, :layout => :foo).should.equal 'Foo bar Layout'
end
it "should read template from a file if exists" do
File.expects(:read).with('views/bar.foo').returns('foo content')
@context.render(:bar, :foo).should.equal 'foo content'
File.expects(:read).with('views2/bar.foo').returns('foo content')
@context.render(:bar, :foo, :views_directory => 'views2').should.equal 'foo content'
end
end

View file

@ -1,21 +0,0 @@
require File.dirname(__FILE__) + '/../helper'
describe "Rack::Request" do
it "should return PUT and DELETE based on _method param" do
env = {'REQUEST_METHOD' => 'POST', 'rack.input' => StringIO.new('_method=DELETE')}
Rack::Request.new(env).request_method.should.equal 'DELETE'
env = {'REQUEST_METHOD' => 'POST', 'rack.input' => StringIO.new('_method=PUT')}
Rack::Request.new(env).request_method.should.equal 'PUT'
end
it "should not allow faking" do
env = {'REQUEST_METHOD' => 'POST', 'rack.input' => StringIO.new('_method=GET')}
Rack::Request.new(env).request_method.should.equal 'POST'
env = {'REQUEST_METHOD' => 'GET', 'rack.input' => StringIO.new('_method=POST')}
Rack::Request.new(env).request_method.should.equal 'GET'
end
end

View file

@ -1,21 +0,0 @@
require File.dirname(__FILE__) + '/../helper'
describe "Route" do
it "gives :format for free" do
route = Sinatra::Route.new('/foo/:test/:blake')
route.recognize('/foo/bar/baz').should.equal true
route.params.should.equal :test => 'bar', :blake => 'baz', :format => 'html'
route.recognize('/foo/bar/baz.xml').should.equal true
route.params.should.equal :test => 'bar', :blake => 'baz', :format => 'xml'
end
it "doesn't auto add :format for routes with explicit formats" do
route = Sinatra::Route.new('/foo/:test.xml')
route.recognize('/foo/bar').should.equal false
route.recognize('/foo/bar.xml').should.equal true
route.params.should.equal :test => 'bar', :format => 'xml'
end
end

View file

@ -1 +0,0 @@
You found foo!

View file

@ -1,44 +0,0 @@
require File.dirname(__FILE__) + '/../helper'
require 'stringio'
context "StaticEvent" do
specify "recognizes paths prefixed with it's path" do
File.expects(:exists?).with('/x/bar/test.jpg').returns(true)
File.expects(:file?).with('/x/bar/test.jpg').returns(true)
Sinatra::StaticEvent.new('/foo', '/x/bar').recognize('/foo/test.jpg').should.equal true
File.expects(:exists?).with('/x/bar/test.jpg').returns(false)
Sinatra::StaticEvent.new('/foo', '/x/bar').recognize('/foo/test.jpg').should.equal false
end
specify "sets headers for file type" do
File.expects(:open).with('/x/bar/test.jpg', 'rb').returns(StringIO.new)
File.expects(:size).with('/x/bar/test.jpg').returns(255)
result = Sinatra::StaticEvent.new('/foo', '/x/bar').attend(stub(:path_info => '/foo/test.jpg'))
result.headers.should.equal 'Content-Type' => 'image/jpeg', 'Content-Length' => '255'
result.body.each { }
end
specify "makes sure it is a file and not a directory" do
File.expects(:exists?).with('/x/bar').returns(true)
File.expects(:file?).with('/x/bar').returns(false)
Sinatra::StaticEvent.new('/foo', '/x').recognize('/foo/bar').should.equal false
end
end
context "StaticEvent (In full context)" do
specify "should serve a static file" do
e = static '/x', root = File.dirname(__FILE__) + '/static_files'
File.read(e.physical_path_for('/x/foo.txt')).should.equal 'You found foo!'
get_it '/x/foo.txt'
status.should.equal 200
body.should.equal 'You found foo!'
end
end

View file

@ -1,16 +0,0 @@
require File.dirname(__FILE__) + '/../helper'
describe "Route" do
it "should recognize params in urls" do
route = Sinatra::Route.new('/foo/:test/:blake')
route.recognize('/foo/bar/baz').should.equal true
route.params.should.equal :test => 'bar', :blake => 'baz', :format => 'html'
route.recognize('/foo/bar/baz.xml').should.equal true
route.params.should.equal :test => 'bar', :blake => 'baz', :format => 'xml'
end
end

3
vendor/erb/init.rb vendored
View file

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

41
vendor/erb/lib/erb.rb vendored
View file

@ -1,41 +0,0 @@
module Sinatra
module Erb # :nodoc:
module EventContext
# Renders raw erb in within the events context.
#
# This can be use to if you already have the template on hand and don't
# need a layout. This is speedier than using erb
#
def render_erb(content)
require 'erb'
body ERB.new(content).result(binding)
end
# Renders erb within an event.
#
# Inline example:
#
# get '/foo' do
# erb 'The time is <%= Time.now %>'
# end
#
# Template example:
#
# get '/foo' do
# erb :foo #=> reads and renders view/foo.erb
# end
#
# For options, see Sinatra::Renderer
#
# See also: Sinatra::Renderer
def erb(template, options = {}, &layout)
render(template, :erb, options, &layout)
end
end
end
end

3
vendor/haml/init.rb vendored
View file

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

View file

@ -1,41 +0,0 @@
module Sinatra
module Haml # :nodoc:
module EventContext
# Renders raw haml in within the events context.
#
# This can be use to if you already have the template on hand and don't
# need a layout. This is speedier than using haml
#
def render_haml(template, &block)
require 'haml'
body ::Haml::Engine.new(template).render(self, &block)
end
# Renders Haml within an event.
#
# Inline example:
#
# get '/foo' do
# haml '== The time is #{Time.now}'
# end
#
# Template example:
#
# get '/foo' do
# haml :foo #=> reads and renders view/foo.haml
# end
#
# For options, see Sinatra::Renderer
#
# See also: Sinatra::Renderer
def haml(template, options = {}, &layout)
render(template, :haml, options, &layout)
end
end
end
end