mojito 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Max Trense
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,52 @@
1
+ h1. mojito - Next level ruby webframework
2
+
3
+ p. Mojito is a lean and simple webframework.
4
+
5
+ p. As the name implies mojito derives from cuba (https://github.com/soveran/cuba). Many thanks to Michel and the cuba sources for giving me some major insights on web-application-simplicity!
6
+
7
+ h2. Installing
8
+
9
+ bc. $ gem install mojito
10
+
11
+ h2. Your first application
12
+
13
+ p. The easiest way to start with mojito is to use a plain config.ru script to develop and configure your application.
14
+
15
+ bc.. $ cat config.ru
16
+ require 'mojito'
17
+
18
+ FirstApp = Mojito.application do
19
+ on GET(), PATH('/hello/:name') do |name|
20
+ write "Hello #{name}! How are you?"
21
+ content_type :plain
22
+ ok!
23
+ end
24
+ end
25
+
26
+ run FirstApp
27
+
28
+ p. This installs a handler for GET requests to a path of /hello/ followed by a name (actually this notation catches all but a slash '/'). You can start this application by running @rackup@ from the same directory:
29
+
30
+ bc. $ rackup
31
+
32
+ p. This starts a http-server on port 9292. Now try to call your handler through curl:
33
+
34
+ bc. $ curl http://localhost:9292/hello/Fred
35
+ Hello Fred! How are you?
36
+
37
+ p. Please be aware that although this way is easy to start with it tends to messy very quick if your project becomes more complex, so please read on...
38
+
39
+ h2. Contributing to mojito
40
+
41
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
42
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
43
+ * Fork the project.
44
+ * Start a feature/bugfix branch.
45
+ * Commit and push until you are happy with your contribution.
46
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
47
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
48
+
49
+ h2. Copyright
50
+
51
+ p. Copyright (c) 2012 Max Trense. See LICENSE.txt for further details.
52
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/lib/mojito.rb ADDED
@@ -0,0 +1,150 @@
1
+ # encoding: UTF-8
2
+ require 'rack'
3
+ require 'slick/logging'
4
+
5
+ module Mojito
6
+ require 'mojito/utils/status_codes'
7
+ require 'mojito/helpers'
8
+ require 'mojito/rendering'
9
+ require 'mojito/matchers'
10
+
11
+ R = Rendering
12
+ M = Matchers
13
+ H = Helpers
14
+
15
+ def self.included(type)
16
+ type.instance_exec do
17
+ ALL_HELPERS.reverse.each do |mod|
18
+ include mod
19
+ end
20
+ end
21
+ end
22
+
23
+ def self.base_application(*helpers, &block)
24
+ Class.new.tap do |cl|
25
+ cl.instance_exec do
26
+ include Mojito::Base
27
+ helpers.reverse.each do |helper|
28
+ include helper
29
+ extend helper::ClassMethods if helper.const_defined? :ClassMethods
30
+ end
31
+ end
32
+ cl.routes &block if block
33
+ end
34
+ end
35
+
36
+ def self.application(*helpers, &block)
37
+ Class.new.tap do |cl|
38
+ cl.instance_exec do
39
+ include Mojito
40
+ helpers.reverse.each do |helper|
41
+ include helper
42
+ extend helper::ClassMethods if helper.const_defined? :ClassMethods
43
+ end
44
+ end
45
+ cl.routes &block if block
46
+ end
47
+ end
48
+
49
+ module Base
50
+
51
+ def self.included(type)
52
+ type.extend ClassMethods
53
+ end
54
+
55
+ def initialize(env)
56
+ @__env = env
57
+ end
58
+
59
+ def env
60
+ @__env
61
+ end
62
+
63
+ def request
64
+ @__request ||= Rack::Request.new(env)
65
+ end
66
+
67
+ def response
68
+ @__response ||= Rack::Response.new
69
+ end
70
+
71
+ def captures
72
+ @__captures ||= []
73
+ end
74
+
75
+ def locals
76
+ @__locals ||= {}
77
+ end
78
+
79
+ def script_name
80
+ env['SCRIPT_NAME']
81
+ end
82
+
83
+ def path_info
84
+ env['PATH_INFO']
85
+ end
86
+
87
+ def halt!(resp = response)
88
+ throw :halt, case resp
89
+ when Rack::Response
90
+ resp.finish
91
+ when Array
92
+ resp
93
+ when Symbol, Integer
94
+ response.status = STATUS[resp].code
95
+ response.finish
96
+ else
97
+ [500, { 'Content-Type' => 'application/octet-stream' }, []]
98
+ end
99
+ end
100
+
101
+ def dispatch
102
+ instance_exec &self.class.routes if self.class.routes
103
+ Rack::Response.new [], 404, 'Content-Type' => 'application/octet-stream'
104
+ end
105
+
106
+ def on(*matchers, &block)
107
+ env_backup = env.dup
108
+ param_size = captures.length
109
+ return unless matchers.all? {|m| __match?(m) }
110
+ params = captures[param_size..-1][0..block.arity].collect {|p| Rack::Utils.unescape(p) }
111
+ instance_exec *params, &block
112
+ ensure
113
+ @__env = env_backup
114
+ end
115
+
116
+ def __match?(matcher)
117
+ case matcher
118
+ when String, Regexp
119
+ instance_exec &Matchers::PATH(matcher)
120
+ when Proc
121
+ instance_exec &matcher
122
+ else
123
+ matcher
124
+ end
125
+ end
126
+
127
+ module ClassMethods
128
+
129
+ def call(env)
130
+ catch :halt do
131
+ new(env).dispatch
132
+ end
133
+ end
134
+
135
+ def routes(&block)
136
+ @__routing = block if block
137
+ @__routing
138
+ end
139
+
140
+ def mock_request
141
+ Rack::MockRequest.new self
142
+ end
143
+
144
+ end
145
+
146
+ end
147
+
148
+ ALL_HELPERS = [Mojito::Matchers, Mojito::Rendering, Mojito::Helpers::ExceptionHandling, Mojito::Base]
149
+
150
+ end
@@ -0,0 +1,7 @@
1
+ # encoding: UTF-8
2
+
3
+ module Mojito::Helpers
4
+
5
+ require 'mojito/helpers/exception_handling'
6
+
7
+ end
@@ -0,0 +1,84 @@
1
+ # encoding: UTF-8
2
+
3
+ module Mojito
4
+
5
+ class MojitoException < Exception
6
+
7
+ def initialize(status = 500, message = STATUS[status].message)
8
+ super(message)
9
+ @status = Mojito::STATUS[status].code
10
+ end
11
+
12
+ attr_reader :status
13
+
14
+ def to_response
15
+ Rack::Response.new [], status, 'Content-Type' => 'application/octet-stream'
16
+ end
17
+
18
+ end
19
+
20
+ module Helpers
21
+
22
+ module ExceptionHandling
23
+
24
+ def self.included(type)
25
+ type.extend ClassMethods
26
+ type.instance_exec do
27
+ old_dispatch = instance_method(:dispatch)
28
+ define_method :dispatch do
29
+ begin
30
+ old_dispatch.bind(self).call
31
+ rescue Exception => e
32
+ __handle_error e
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ def raise(exception)
39
+ backtrace = caller[1..-1]
40
+ Kernel.raise case exception
41
+ when Symbol, Integer
42
+ Mojito::MojitoException.new(exception)
43
+ when Exception
44
+ exception
45
+ else
46
+ RuntimeError.new(exception)
47
+ end.tap {|e| e.set_backtrace backtrace }
48
+ end
49
+
50
+ def __handle_error(exception)
51
+ if handler = case exception
52
+ when MojitoException
53
+ self.class.error_handlers[exception.status]
54
+ when Exception
55
+ self.class.error_handlers[exception.class]
56
+ end
57
+ instance_exec &handler
58
+ end
59
+ puts "Exception: #{exception.inspect}"
60
+ raise exception
61
+ end
62
+
63
+ module ClassMethods
64
+
65
+ def on_error(type, &block)
66
+ case type
67
+ when Symbol, Integer
68
+ error_handlers[Mojito::STATUS[type].code] = block
69
+ when Class
70
+ error_handlers[type] = block
71
+ end
72
+ end
73
+
74
+ def error_handlers
75
+ @__error_handlers ||= {}
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: UTF-8
2
+
3
+ module Mojito::Matchers
4
+
5
+ require 'mojito/matchers/methods'
6
+ require 'mojito/matchers/path'
7
+ require 'mojito/matchers/virtual_host'
8
+
9
+ include Methods
10
+ include Path
11
+ include VirtualHost
12
+
13
+ extend Path
14
+ extend VirtualHost
15
+
16
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: UTF-8
2
+
3
+ module Mojito::Matchers
4
+
5
+ module Methods
6
+
7
+ def METHOD(method)
8
+ proc { request.request_method == method.to_s.upcase }
9
+ end
10
+
11
+ def GET
12
+ METHOD(:get)
13
+ end
14
+
15
+ def HEAD
16
+ METHOD(:head)
17
+ end
18
+
19
+ def POST
20
+ METHOD(:post)
21
+ end
22
+
23
+ def PUT
24
+ METHOD(:put)
25
+ end
26
+
27
+ def DELETE
28
+ METHOD(:delete)
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,35 @@
1
+ # encoding: UTF-8
2
+
3
+ module Mojito::Matchers
4
+
5
+ module Path
6
+
7
+ def PATH(pattern)
8
+ consume_path = proc do |pattern|
9
+ if match = path_info.match(%r<\A/#{pattern}(?=/|\z)>)
10
+ env['SCRIPT_NAME'] = match.to_s
11
+ env['PATH_INFO'] = match.post_match
12
+ locals.update match.names.inject({}) {|hash, name| hash[name.to_sym] = match[name] ; hash }
13
+ captures.push *match.captures
14
+ true
15
+ else
16
+ false
17
+ end
18
+ end
19
+ proc do
20
+ if p = case pattern
21
+ when String
22
+ pattern.gsub(%r{/?:\?\w+}) {|name| "(?:/(?<#{name[2..-1]}>[^/]+))?" }.gsub(%r{:\w+}) {|name| "(?<#{name[1..-1]}>[^/]+)" }
23
+ when Regexp
24
+ pattern
25
+ end
26
+ instance_exec p, &consume_path
27
+ else
28
+ false
29
+ end
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: UTF-8
2
+
3
+ module Mojito::Matchers
4
+
5
+ module VirtualHost
6
+
7
+ def HOST(pattern)
8
+ proc do
9
+ case pattern
10
+ when String
11
+ /#{pattern.gsub('**', '[^:]+').gsub('*', '[^:.]+')}/ === request.host_with_port
12
+ when Array
13
+ pattern.any? {|p| /#{p.gsub('**', '[^:]+').gsub('*', '[^:.]+')}/ === request.host_with_port }
14
+ when Regexp
15
+ pattern === request.host_with_port
16
+ end
17
+ end
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: UTF-8
2
+
3
+ module Mojito::Rendering
4
+
5
+ require 'mojito/rendering/content'
6
+ require 'mojito/rendering/content_types'
7
+ require 'mojito/rendering/delegation'
8
+ require 'mojito/rendering/status_codes'
9
+
10
+ include Content
11
+ include ContentTypes
12
+ include Delegation
13
+ include StatusCodes
14
+
15
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: UTF-8
2
+
3
+ module Mojito::Rendering
4
+
5
+ module Content
6
+
7
+ def write(content)
8
+ response.write content
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: UTF-8
2
+
3
+ module Mojito::Rendering
4
+
5
+ module ContentTypes
6
+ require 'mime/types'
7
+
8
+ def content_type(type = :html, charset = 'UTF-8')
9
+ t = case type
10
+ when :plain
11
+ MIME::Types.type_for 'txt'
12
+ else
13
+ MIME::Types.type_for type.to_s
14
+ end.first
15
+ response['Content-Type'] = t.to_s + (t.ascii? ? "; charset=#{charset}" : '')
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: UTF-8
2
+
3
+ module Mojito::Rendering
4
+
5
+ module Delegation
6
+
7
+ def run(app)
8
+ halt! app
9
+ end
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,39 @@
1
+ # encoding: UTF-8
2
+
3
+ module Mojito::Rendering
4
+
5
+ module StatusCodes
6
+
7
+ def ok!
8
+ response.status = 200
9
+ halt!
10
+ end
11
+
12
+ def not_found!
13
+ response.status = 404
14
+ halt!
15
+ end
16
+
17
+ def internal_server_error!
18
+ response.status = 500
19
+ halt!
20
+ end
21
+
22
+ def unavailable!
23
+ response.status = 503
24
+ halt!
25
+ end
26
+
27
+ def redirect(target, status = 302)
28
+ response['Location'] = target
29
+ response.status = status
30
+ end
31
+
32
+ def redirect!(target, status = 302)
33
+ redirect target, status
34
+ halt!
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,64 @@
1
+ # encoding: UTF-8
2
+
3
+ module Mojito
4
+
5
+ HttpStatusCode = Struct.new :code, :symbol, :message
6
+ STATUS = {}
7
+
8
+ [
9
+ HttpStatusCode.new(100, :continue, 'Continue'),
10
+ HttpStatusCode.new(101, :switching_protocols, 'Switching Protocols'),
11
+ HttpStatusCode.new(102, :processing, 'Processing'),
12
+ HttpStatusCode.new(103, :checkpoint, 'Checkpoint'),
13
+ HttpStatusCode.new(122, :request_uri_too_long, 'Request-URI too long'),
14
+ HttpStatusCode.new(200, :ok, 'OK'),
15
+ HttpStatusCode.new(201, :created, 'Created'),
16
+ HttpStatusCode.new(202, :accepted, 'Accepted'),
17
+ HttpStatusCode.new(203, :non_authoritative_information, 'Non-Authoritative Information'),
18
+ HttpStatusCode.new(204, :no_content, 'No Content'),
19
+ HttpStatusCode.new(205, :reset_content, 'Reset Content'),
20
+ HttpStatusCode.new(206, :partial_content, 'Partial Content'),
21
+ HttpStatusCode.new(207, :multi_status, 'Multi-Status'),
22
+ HttpStatusCode.new(208, :already_reported, 'Already Reported'),
23
+ HttpStatusCode.new(226, :im_used, 'IM Used'),
24
+ HttpStatusCode.new(300, :multiple_choices, 'Multiple Choices'),
25
+ HttpStatusCode.new(301, :moved_permanently, 'Moved Permanently'),
26
+ HttpStatusCode.new(302, :found, 'Found'),
27
+ HttpStatusCode.new(303, :see_other, 'See Other'),
28
+ HttpStatusCode.new(304, :not_modified, 'Not Modified'),
29
+ HttpStatusCode.new(305, :use_proxy, 'Use Proxy'),
30
+ HttpStatusCode.new(306, :switch_proxy, 'Switch Proxy'),
31
+ HttpStatusCode.new(307, :temporary_redirect, 'Temporary Redirect'),
32
+ HttpStatusCode.new(308, :resume_incomplete, 'Resume Incomplete'),
33
+ HttpStatusCode.new(400, :bad_request, 'Bad Request'),
34
+ HttpStatusCode.new(401, :unauthorized, 'Unauthorized'),
35
+ HttpStatusCode.new(402, :payment_required, 'Payment Required'),
36
+ HttpStatusCode.new(403, :forbidden, 'Forbidden'),
37
+ HttpStatusCode.new(404, :not_found, 'Not Found'),
38
+ HttpStatusCode.new(405, :method_not_allowed, 'Method Not Allowed'),
39
+ HttpStatusCode.new(406, :not_acceptable, 'Not Acceptable'),
40
+ HttpStatusCode.new(407, :proxy_authentication_required, 'Proxy Authentication Required'),
41
+ HttpStatusCode.new(408, :request_timeout, 'Request Timeout'),
42
+ HttpStatusCode.new(409, :conflict, 'Conflict'),
43
+ HttpStatusCode.new(410, :gone, 'Gone'),
44
+ HttpStatusCode.new(411, :length_required, 'Length Required'),
45
+ HttpStatusCode.new(412, :precondition_failed, 'Precondition Failed'),
46
+ HttpStatusCode.new(413, :request_entity_too_large, 'Request Entity Too Large'),
47
+ HttpStatusCode.new(414, :request_uri_too_long, 'Request-URI Too Long'),
48
+ HttpStatusCode.new(415, :unsupported_media_type, 'Unsupported Media Type'),
49
+ HttpStatusCode.new(416, :request_range_not_satisfiable, 'Request Range Not Satisfiable'),
50
+ HttpStatusCode.new(417, :expectation_failed, 'Expectation Failed'),
51
+ HttpStatusCode.new(418, :im_a_teapot, 'I\'m a teapot'),
52
+ HttpStatusCode.new(419, :enhance_your_calm, 'Enhance Your Calm'),
53
+ HttpStatusCode.new(500, :internal_server_error, 'Internal Server Error'),
54
+ HttpStatusCode.new(501, :not_implemented, 'Not Implemented'),
55
+ HttpStatusCode.new(502, :bad_gateway, 'Bad Gateway'),
56
+ HttpStatusCode.new(503, :service_unavailable, 'Service Unavailable'),
57
+ HttpStatusCode.new(504, :gateway_timeout, 'Gateway Timeout'),
58
+ HttpStatusCode.new(505, :http_version_not_supported, 'HTTP Version Not Supported'),
59
+ ].each do |sc|
60
+ STATUS[sc.code] = sc
61
+ STATUS[sc.symbol] = sc
62
+ end
63
+
64
+ end
@@ -0,0 +1,89 @@
1
+ # encoding: UTF-8
2
+ require 'mojito'
3
+
4
+ describe Mojito::Matchers::Methods do
5
+
6
+ subject do
7
+ Mojito.application Mojito::Matchers::Methods do
8
+ on GET() do write 'get' ; halt! end
9
+ on POST() do write 'post' ; halt! end
10
+ on HEAD() do write 'head' ; halt! end
11
+ on PUT() do write 'put' ; halt! end
12
+ on DELETE() do write 'delete' ; halt! end
13
+ on METHOD(:options) do write 'options' ; halt! end
14
+ end.mock_request
15
+ end
16
+
17
+ it { subject.get('/').body.should == 'get' }
18
+ it { subject.post('/').body.should == 'post' }
19
+ it { subject.head('/').body.should == 'head' }
20
+ it { subject.put('/').body.should == 'put' }
21
+ it { subject.delete('/').body.should == 'delete' }
22
+ it { subject.request('OPTIONS', '/').body.should == 'options' }
23
+
24
+ end
25
+
26
+ describe Mojito::Matchers::Path do
27
+
28
+ subject { Mojito.application.new Rack::MockRequest.env_for('http://localhost/hello/world/rest') }
29
+
30
+ it do
31
+ subject.send(:__match?, Mojito::M::PATH('hello'))
32
+ subject.captures.should be_empty
33
+ subject.locals.should be_empty
34
+ subject.path_info.should == '/world/rest'
35
+ end
36
+
37
+ it do
38
+ subject.send(:__match?, 'hello')
39
+ subject.captures.should be_empty
40
+ subject.locals.should be_empty
41
+ subject.path_info.should == '/world/rest'
42
+ end
43
+
44
+ it do
45
+ subject.send(:__match?, Mojito::M::PATH('hello/:name'))
46
+ subject.captures.should == ['world']
47
+ subject.locals.should == { :name => 'world' }
48
+ subject.path_info.should == '/rest'
49
+ end
50
+
51
+ it do
52
+ subject.send(:__match?, 'hello/:name')
53
+ subject.captures.should == ['world']
54
+ subject.locals.should == { :name => 'world' }
55
+ subject.path_info.should == '/rest'
56
+ end
57
+
58
+ it do
59
+ subject.send(:__match?, Mojito::M::PATH(%r{hello/(?<name>[^/]+)}))
60
+ subject.captures.should == ['world']
61
+ subject.locals.should == { :name => 'world' }
62
+ subject.path_info.should == '/rest'
63
+ end
64
+
65
+ it do
66
+ subject.send(:__match?, %r{hello/(?<name>[^/]+)})
67
+ subject.captures.should == ['world']
68
+ subject.locals.should == { :name => 'world' }
69
+ subject.path_info.should == '/rest'
70
+ end
71
+
72
+ end
73
+
74
+ describe Mojito::Matchers::VirtualHost do
75
+
76
+ subject do
77
+ Mojito.application Mojito::Matchers::VirtualHost do
78
+ on HOST('localhost') do write 'localhost' ; halt! end
79
+ on HOST('test:8080') do write 'test' ; halt! end
80
+ end.mock_request
81
+ end
82
+
83
+ it { subject.get('http://localhost:4444/').body.should == 'localhost' }
84
+ it { subject.get('http://localhost/').body.should == 'localhost' }
85
+ it { subject.get('http://localhost:80/').body.should == 'localhost' }
86
+ it { subject.get('http://test:8080/').body.should == 'test' }
87
+ it { subject.get('http://test/').status.should == 404 }
88
+
89
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: UTF-8
2
+ require 'mojito'
3
+
4
+ describe Mojito::Rendering::Content do
5
+
6
+ subject do
7
+ Mojito.base_application Mojito::Rendering::Content do
8
+ on do write 'test content' ; halt! end
9
+ end.mock_request
10
+ end
11
+
12
+ it { subject.get('/').body.should == 'test content' }
13
+
14
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: UTF-8
2
+ require 'mojito'
3
+
4
+ describe Mojito do
5
+
6
+ context do
7
+ subject { Mojito.application {} }
8
+ it { subject.ancestors.should include(Mojito::Base) }
9
+ it { subject.should respond_to(:call) }
10
+ end
11
+
12
+ context do
13
+ subject { Mojito.application(Mojito::Matchers::Path).new Rack::MockRequest.env_for('http://localhost/hello/world/rest') }
14
+ it { subject.env.should_not be_nil }
15
+ it { subject.request.should be_kind_of(Rack::Request) }
16
+ it { subject.captures.should be_empty }
17
+ it { subject.locals.should be_empty }
18
+ it do
19
+ subject.send(:__match?, proc { request.host == 'localhost' })
20
+ subject.captures.should be_empty
21
+ subject.locals.should be_empty
22
+ subject.path_info.should == '/hello/world/rest'
23
+ end
24
+ end
25
+
26
+ context do
27
+ subject do
28
+ Mojito.application do
29
+
30
+ end
31
+ end
32
+ end
33
+
34
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mojito
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Max Trense
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rack
16
+ requirement: &6514840 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.4.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *6514840
25
+ - !ruby/object:Gem::Dependency
26
+ name: mime-types
27
+ requirement: &6514180 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '1.18'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *6514180
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &6513520 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 2.8.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *6513520
47
+ - !ruby/object:Gem::Dependency
48
+ name: rdoc
49
+ requirement: &7041900 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '3.12'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *7041900
58
+ - !ruby/object:Gem::Dependency
59
+ name: bundler
60
+ requirement: &7040840 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 1.0.0
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *7040840
69
+ - !ruby/object:Gem::Dependency
70
+ name: jeweler
71
+ requirement: &7039960 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 1.8.3
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *7039960
80
+ - !ruby/object:Gem::Dependency
81
+ name: rcov
82
+ requirement: &7038500 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *7038500
91
+ description: A simple yet powerful webframework largely inspired by Rum and Cuba
92
+ email: dev@trense.info
93
+ executables: []
94
+ extensions: []
95
+ extra_rdoc_files:
96
+ - LICENSE.txt
97
+ - README.textile
98
+ files:
99
+ - LICENSE.txt
100
+ - VERSION
101
+ - lib/mojito.rb
102
+ - lib/mojito/helpers.rb
103
+ - lib/mojito/helpers/exception_handling.rb
104
+ - lib/mojito/matchers.rb
105
+ - lib/mojito/matchers/methods.rb
106
+ - lib/mojito/matchers/path.rb
107
+ - lib/mojito/matchers/virtual_host.rb
108
+ - lib/mojito/rendering.rb
109
+ - lib/mojito/rendering/content.rb
110
+ - lib/mojito/rendering/content_types.rb
111
+ - lib/mojito/rendering/delegation.rb
112
+ - lib/mojito/rendering/status_codes.rb
113
+ - lib/mojito/utils/status_codes.rb
114
+ - spec/mojito/matchers_spec.rb
115
+ - spec/mojito/rendering_spec.rb
116
+ - spec/mojito_spec.rb
117
+ - README.textile
118
+ homepage: http://github.com/mtrense/mojito
119
+ licenses:
120
+ - MIT
121
+ post_install_message:
122
+ rdoc_options: []
123
+ require_paths:
124
+ - lib
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ! '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
+ none: false
133
+ requirements:
134
+ - - ! '>='
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ requirements: []
138
+ rubyforge_project:
139
+ rubygems_version: 1.8.17
140
+ signing_key:
141
+ specification_version: 3
142
+ summary: A simple yet powerful webframework largely inspired by Rum and Cuba
143
+ test_files: []