mirror of
https://github.com/sinatra/sinatra
synced 2023-03-27 23:18:01 -04:00
starting again
This commit is contained in:
parent
03626a1ec4
commit
e53fb2bcad
53 changed files with 60 additions and 2225 deletions
|
@ -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
22
LICENSE
|
@ -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.
|
52
Manifest
52
Manifest
|
@ -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
119
README
|
@ -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
|
35
RakeFile
35
RakeFile
|
@ -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
|
|
@ -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
|
|
@ -1 +0,0 @@
|
|||
Hello <%= params[:name].capitalize || 'World' %>!
|
|
@ -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>
|
|
@ -1,9 +0,0 @@
|
|||
<h2>Error!</h2>
|
||||
|
||||
<h3>
|
||||
<%= @error.message %>
|
||||
</h3>
|
||||
|
||||
<div id="backtrace">
|
||||
<%= @error.backtrace.join('<br/>') %>
|
||||
</div>
|
BIN
files/logo.png
BIN
files/logo.png
Binary file not shown.
Before Width: | Height: | Size: 26 KiB |
|
@ -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>
|
105
lib/sinatra.rb
105
lib/sinatra.rb
|
@ -1,50 +1,65 @@
|
|||
# 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.
|
||||
require "rubygems"
|
||||
require "rack"
|
||||
|
||||
%w(rubygems rack).each do |library|
|
||||
begin
|
||||
require library
|
||||
rescue LoadError
|
||||
raise "== Sinatra cannot run without #{library} installed"
|
||||
class String
|
||||
def to_param
|
||||
URI.escape(self)
|
||||
end
|
||||
|
||||
def from_param
|
||||
URI.unescape(self)
|
||||
end
|
||||
end
|
||||
|
||||
SINATRA_ROOT = File.dirname(__FILE__) + '/..'
|
||||
|
||||
require File.dirname(__FILE__) + '/sinatra/loader'
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -1,5 +0,0 @@
|
|||
class Array
|
||||
def to_hash
|
||||
self.inject({}) { |h, (k, v)| h[k] = v; h }
|
||||
end
|
||||
end
|
|
@ -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
|
|
@ -1,7 +0,0 @@
|
|||
class Hash
|
||||
|
||||
def symbolize_keys
|
||||
self.inject({}) { |h,(k,v)| h[k.to_sym] = v; h }
|
||||
end
|
||||
|
||||
end
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -1,5 +0,0 @@
|
|||
class Symbol
|
||||
def to_proc
|
||||
Proc.new { |*args| args.shift.__send__(self, *args) }
|
||||
end
|
||||
end
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
104
site/index.htm
104
site/index.htm
|
@ -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>
|
104
site/index.html
104
site/index.html
|
@ -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>
|
BIN
site/logo.png
BIN
site/logo.png
Binary file not shown.
Before Width: | Height: | Size: 26 KiB |
|
@ -1,2 +0,0 @@
|
|||
require File.dirname(__FILE__) + '/../lib/sinatra/test/spec'
|
||||
require 'mocha'
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -1 +0,0 @@
|
|||
You found foo!
|
|
@ -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
|
|
@ -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
3
vendor/erb/init.rb
vendored
|
@ -1,3 +0,0 @@
|
|||
require File.dirname(__FILE__) + '/lib/erb'
|
||||
|
||||
Sinatra::EventContext.send(:include, Sinatra::Erb::EventContext)
|
41
vendor/erb/lib/erb.rb
vendored
41
vendor/erb/lib/erb.rb
vendored
|
@ -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
3
vendor/haml/init.rb
vendored
|
@ -1,3 +0,0 @@
|
|||
require File.dirname(__FILE__) + '/lib/haml'
|
||||
|
||||
Sinatra::EventContext.send(:include, Sinatra::Haml::EventContext)
|
41
vendor/haml/lib/haml.rb
vendored
41
vendor/haml/lib/haml.rb
vendored
|
@ -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
|
Loading…
Reference in a new issue