lunetas 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.md +6 -0
- data/Rakefile +47 -0
- data/VERSION +1 -0
- data/examples/config.ru +3 -0
- data/examples/testing.rb +29 -0
- data/lib/lunetas.rb +11 -0
- data/lib/lunetas/bag.rb +33 -0
- data/lib/lunetas/candy.rb +186 -0
- data/lib/lunetas/error.rb +42 -0
- data/spec/lunetas/bag_spec.rb +40 -0
- data/spec/lunetas/candy_spec.rb +106 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +38 -0
- metadata +143 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Iván Valdés (@ivanvc)
|
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.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "lunetas"
|
8
|
+
gem.summary = %Q{Rack micro framework intended for APIs}
|
9
|
+
gem.description = %Q{This is a micro framework based in Rack, inspired in Sinatra, camping and many others. The intention is to have fast responses for simple API calls. The base unit of this framework are the classes, which registers a regular expression that will match this resource.}
|
10
|
+
gem.email = "iv@nvald.es"
|
11
|
+
gem.homepage = "http://github.com/ivanvc/lunetas"
|
12
|
+
gem.authors = ["Iván Valdés (@ivanvc)"]
|
13
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
+
gem.add_development_dependency "yard", ">= 0"
|
15
|
+
gem.add_development_dependency "shotgun", ">= 0"
|
16
|
+
gem.add_dependency "rack", ">= 0"
|
17
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
18
|
+
end
|
19
|
+
Jeweler::GemcutterTasks.new
|
20
|
+
rescue LoadError
|
21
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
22
|
+
end
|
23
|
+
|
24
|
+
require 'spec/rake/spectask'
|
25
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
26
|
+
spec.libs << 'lib' << 'spec'
|
27
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
28
|
+
end
|
29
|
+
|
30
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
31
|
+
spec.libs << 'lib' << 'spec'
|
32
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
33
|
+
spec.rcov = true
|
34
|
+
end
|
35
|
+
|
36
|
+
task :spec => :check_dependencies
|
37
|
+
|
38
|
+
task :default => :spec
|
39
|
+
|
40
|
+
begin
|
41
|
+
require 'yard'
|
42
|
+
YARD::Rake::YardocTask.new
|
43
|
+
rescue LoadError
|
44
|
+
task :yardoc do
|
45
|
+
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
46
|
+
end
|
47
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
data/examples/config.ru
ADDED
data/examples/testing.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require '../lib/lunetas'
|
2
|
+
|
3
|
+
class Testing
|
4
|
+
include Lunetas::Candy
|
5
|
+
matches '/hello/(\w+)', :name
|
6
|
+
|
7
|
+
def get
|
8
|
+
"Hello #{@name}! #{params[:chunky]}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def post
|
12
|
+
"Hey #{@name}, I see you're testing the POST method :)"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class AnotherTest
|
17
|
+
include Lunetas::Candy
|
18
|
+
matches '^/(\d+)$', :number
|
19
|
+
|
20
|
+
def get
|
21
|
+
"Is #{@number} your lucky number?"
|
22
|
+
end
|
23
|
+
|
24
|
+
def other_verb(verb)
|
25
|
+
if verb == 'TEAPOT'
|
26
|
+
"I ain't a teapot!"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/lunetas.rb
ADDED
data/lib/lunetas/bag.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# This is the module that keeps the register of all the Lunetas. It will add the
|
2
|
+
# classes to a register, and whenever rack receives a call, it delegates it.
|
3
|
+
# If Lunetas is not run as a stand alone rack application, then this module
|
4
|
+
# lacks of responsability, ie. Running as a Rails Metal.
|
5
|
+
module Lunetas::Bag
|
6
|
+
# Registers new classes to a given regular expression. It should be called from
|
7
|
+
# a Luneta.
|
8
|
+
# @param [Regexp] regex the regular expression for this Luneta Class.
|
9
|
+
# @param [Luneta] candy the class that owns the regular expresion.
|
10
|
+
def self.register(regex, candy)
|
11
|
+
# TODO: Log: "Registering #{regex.inspect} #{candy.inspect}"
|
12
|
+
@@candies ||= {}
|
13
|
+
@@candies[regex] = candy
|
14
|
+
end
|
15
|
+
|
16
|
+
# Rack's call method. Will be called with the env, from rack. If it matches
|
17
|
+
# a regular expression, it will start a new instance of the propiertary class.
|
18
|
+
# If there's no matching class, it will return a 404.
|
19
|
+
#
|
20
|
+
# @param [Hash] env the rack's env.
|
21
|
+
# @return [Array] the rack response.
|
22
|
+
def self.call(env)
|
23
|
+
@url_match = nil
|
24
|
+
match_regex = @@candies.keys.find do |regex|
|
25
|
+
@url_match = env['PATH_INFO'].match(regex)
|
26
|
+
end
|
27
|
+
unless match_regex
|
28
|
+
return [404, {"Content-Type" => "text/html", "X-Cascade" => "pass"}, ["Not Found"]]
|
29
|
+
end
|
30
|
+
candy = @@candies[match_regex].new(env, @url_match.to_a)
|
31
|
+
candy.bite
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
# This module should be included in any resource that should be exposed with
|
2
|
+
# an API. Then the method matches should be called in order to register the
|
3
|
+
# path for this resource.
|
4
|
+
# @example Simple example
|
5
|
+
# class Testing
|
6
|
+
# include Lunetas::Candy
|
7
|
+
# matches '/test'
|
8
|
+
#
|
9
|
+
# def get
|
10
|
+
# "This is what I answer then calling GET '/test'"
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
module Lunetas::Candy
|
14
|
+
module InstanceMethods
|
15
|
+
# The matched url-regex for this resource.
|
16
|
+
attr_reader :url
|
17
|
+
attr_accessor :url_params
|
18
|
+
# The initialization of a class that includes a Candy, should be done
|
19
|
+
# with rack environment and the url matches from its regular expression.
|
20
|
+
# It will register all the passed url parameters from #matches as new
|
21
|
+
# instance variables.
|
22
|
+
# @param [Hash] env the Rack env.
|
23
|
+
# @param [Array] url_matches the matches from its regex. In most cases
|
24
|
+
# (MatchData instance).to_a
|
25
|
+
def initialize(env, url_matches)
|
26
|
+
@req = Rack::Request.new(env)
|
27
|
+
@_url_params = url_matches
|
28
|
+
self.url_params = url_matches
|
29
|
+
@url = @_url_params.shift
|
30
|
+
begin
|
31
|
+
self.class._url_params.each_with_index do |option, index|
|
32
|
+
instance_variable_set "@#{option}", url_param(index)
|
33
|
+
end
|
34
|
+
# Provide an authentication method. Probably a method
|
35
|
+
# from the Lunetas::Bag.
|
36
|
+
# authenticate!
|
37
|
+
# rescue Lunetas::Error::AuthenticationError
|
38
|
+
# @_error = Lunetas::Error::AuthenticationError
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns the url parameter from the regular expresion. If a captured
|
43
|
+
# block is given, then they will be added in order of appearance.
|
44
|
+
# @param [Fixnum] index the index of the captured block.
|
45
|
+
# @return [String] the captured block.
|
46
|
+
def url_param(index)
|
47
|
+
@_url_params[index]
|
48
|
+
end
|
49
|
+
|
50
|
+
# Bites the Candy (a.k.a process this resource).
|
51
|
+
#
|
52
|
+
# @return [Array] a standard rack response.
|
53
|
+
def bite
|
54
|
+
raise @_error if @_error
|
55
|
+
before
|
56
|
+
response(handle_call)
|
57
|
+
rescue Exception => e
|
58
|
+
response(e, e.code)
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
def handle_call
|
63
|
+
case @req.request_method
|
64
|
+
when 'GET'
|
65
|
+
get
|
66
|
+
when 'POST'
|
67
|
+
post
|
68
|
+
when 'PUT'
|
69
|
+
put
|
70
|
+
when 'DELETE'
|
71
|
+
delete
|
72
|
+
when 'HEAD'
|
73
|
+
head
|
74
|
+
when 'TRACE'
|
75
|
+
trace
|
76
|
+
when 'OPTIONS'
|
77
|
+
options
|
78
|
+
else
|
79
|
+
response = other_verb(@req.request_method)
|
80
|
+
raise Lunetas::Error::APIError unless response
|
81
|
+
response
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def xhr?
|
86
|
+
@req.xhr?
|
87
|
+
end
|
88
|
+
|
89
|
+
def params
|
90
|
+
@req.params
|
91
|
+
end
|
92
|
+
|
93
|
+
# TODO: Polish this
|
94
|
+
# def authenticate!
|
95
|
+
# @current_user = User.where(:single_access_token => token).first
|
96
|
+
# raise Lunetas::Error::AuthenticationError unless @current_user
|
97
|
+
# end
|
98
|
+
|
99
|
+
def response(object, code = 200)
|
100
|
+
[code, {'Content-Type' => "application/json"}, [object.to_s]]
|
101
|
+
end
|
102
|
+
|
103
|
+
# The following methods should be overwritten by the including class
|
104
|
+
def before
|
105
|
+
nil
|
106
|
+
end
|
107
|
+
|
108
|
+
def get
|
109
|
+
raise Lunetas::Error::APIError
|
110
|
+
end
|
111
|
+
|
112
|
+
def post
|
113
|
+
raise Lunetas::Error::APIError
|
114
|
+
end
|
115
|
+
|
116
|
+
def put
|
117
|
+
raise Lunetas::Error::APIError
|
118
|
+
end
|
119
|
+
|
120
|
+
def delete
|
121
|
+
raise Lunetas::Error::APIError
|
122
|
+
end
|
123
|
+
|
124
|
+
def head
|
125
|
+
raise Lunetas::Error::APIError
|
126
|
+
end
|
127
|
+
|
128
|
+
def trace
|
129
|
+
raise Lunetas::Error::APIError
|
130
|
+
end
|
131
|
+
|
132
|
+
def options
|
133
|
+
raise Lunetas::Error::APIError
|
134
|
+
end
|
135
|
+
|
136
|
+
def other_verb(verb)
|
137
|
+
raise Lunetas::Error::APIError
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
module ClassMethods
|
142
|
+
attr_reader :_url_params
|
143
|
+
|
144
|
+
# Support to be runned as a Rails Metal.
|
145
|
+
# @param [Hash] env the Rack env.
|
146
|
+
# @return [Array] a standard Rack response.
|
147
|
+
def call(env)
|
148
|
+
url_match = env['PATH_INFO'].match(@_regex)
|
149
|
+
if url_match
|
150
|
+
call = new(env, url_match.to_a)
|
151
|
+
call.process
|
152
|
+
else
|
153
|
+
[404, {"Content-Type" => "text/html", "X-Cascade" => "pass"}, ["Not Found"]]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
private
|
158
|
+
# Registers a new regular expression. Will add it to the Lunetas::Bag.
|
159
|
+
# Will convert the regex to a Regular Expression, if passing a String. It
|
160
|
+
# also receives the instance variables for the matches of the regex.
|
161
|
+
# @example Regular expression as a Regexp
|
162
|
+
# matches /\/test\/\w+/
|
163
|
+
# @example Regular expression as a double quoted string
|
164
|
+
# matches "\\/test\\/\\w+"
|
165
|
+
# @example Regular expression as a single quoted string (my favorite)
|
166
|
+
# matches '/test/\w+'
|
167
|
+
# @example Passing instance variables that will be set for the captures
|
168
|
+
# matches '/test/(\d+)\.(\w+)', :id, :format
|
169
|
+
# @param [String, Regexp] regex the regular expression for this resource.
|
170
|
+
# @param [Array<Symbol, String>] url_params the instance variables that will
|
171
|
+
# be set for the captures from the regex.
|
172
|
+
def matches(regex, *url_params)
|
173
|
+
@_regex = regex
|
174
|
+
unless Regexp === @_regex
|
175
|
+
@_regex = Regexp.new(@_regex)
|
176
|
+
end
|
177
|
+
@_url_params = url_params
|
178
|
+
Lunetas::Bag.register(@_regex, self)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.included(receiver)
|
183
|
+
receiver.send :include, InstanceMethods
|
184
|
+
receiver.send :extend, ClassMethods
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Lunetas::Error
|
2
|
+
class BaseError < StandardError
|
3
|
+
def to_json
|
4
|
+
{'error' => message}.to_json
|
5
|
+
end
|
6
|
+
def code
|
7
|
+
400
|
8
|
+
end
|
9
|
+
def message
|
10
|
+
"Error"
|
11
|
+
end
|
12
|
+
def to_s
|
13
|
+
message
|
14
|
+
end
|
15
|
+
end
|
16
|
+
class AuthenticationError < BaseError
|
17
|
+
def code
|
18
|
+
401
|
19
|
+
end
|
20
|
+
def message
|
21
|
+
"Permission denied"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class BuildError < BaseError
|
26
|
+
def code
|
27
|
+
405
|
28
|
+
end
|
29
|
+
def message
|
30
|
+
"Build error"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class APIError < BaseError
|
35
|
+
def code
|
36
|
+
404
|
37
|
+
end
|
38
|
+
def message
|
39
|
+
"API route error"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Lunetas::Bag do
|
4
|
+
|
5
|
+
describe "register" do
|
6
|
+
before(:each) do
|
7
|
+
@luneta_class, @luneta_object = mock_candy
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should register a new class' do
|
11
|
+
Lunetas::Bag.register(/test/, @luneta_class)
|
12
|
+
@luneta_object.should_receive(:bite)
|
13
|
+
Lunetas::Bag.call(mock_env('/test'))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "call" do
|
18
|
+
before(:each) do
|
19
|
+
@luneta_class, @luneta_object = mock_candy
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should return a 404 if no matching path' do
|
23
|
+
Lunetas::Bag.call(mock_env('/123')).first.should == 404
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should return the bite of the called' do
|
27
|
+
Lunetas::Bag.register(/chunky/, @luneta_class)
|
28
|
+
@luneta_class.should_receive(:new).and_return(@luneta_object)
|
29
|
+
@luneta_object.should_receive(:bite).once
|
30
|
+
Lunetas::Bag.call(mock_env('/chunky')).first.should == 200
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should pass the matched regex and matches' do
|
34
|
+
Lunetas::Bag.register(/bacon\/(bbacon)/, @luneta_class)
|
35
|
+
env = mock_env('/bacon/bbacon')
|
36
|
+
@luneta_class.should_receive(:new).with(env, ['bacon/bbacon', 'bbacon'])
|
37
|
+
Lunetas::Bag.call(env)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Lunetas::Candy::InstanceMethods do
|
4
|
+
describe '.initialize' do
|
5
|
+
before(:each) do
|
6
|
+
@instance = TestClass.new(mock_env('/just_a_test'), ['/just_a_test', 'a', 'b'])
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should set the url variable' do
|
10
|
+
@instance.url.should == '/just_a_test'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should set the url params' do
|
14
|
+
@instance.url_param(0).should == 'a'
|
15
|
+
@instance.url_param(1).should == 'b'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '.url_param' do
|
20
|
+
it 'should be accasible through its index' do
|
21
|
+
instance = TestClass.new(mock_env('/just_a_test'), ['/just_a_test', 'a'])
|
22
|
+
instance.url_param(0).should == 'a'
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should have none if no matches' do
|
26
|
+
instance = TestClass.new(mock_env('/just_a_test'), ['/just_a_test'])
|
27
|
+
instance.url_param(0).should be_nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '.bite' do
|
32
|
+
before(:each) do
|
33
|
+
@instance = TestClass.new(mock_env('/just_a_test'), ['/just_a_test', 'a'])
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should call the before method' do
|
37
|
+
@instance.should_receive(:before).once
|
38
|
+
@instance.bite
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should call to the response' do
|
42
|
+
@instance.should_receive(:response).once.and_return('')
|
43
|
+
@instance.bite
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should answer with the raised error' do
|
47
|
+
test_exception = TestException.new
|
48
|
+
@instance.should_receive(:before).and_raise(test_exception)
|
49
|
+
@instance.should_receive(:response).with(test_exception, 400)
|
50
|
+
@instance.bite
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should call to the get method' do
|
54
|
+
@instance.should_receive(:get)
|
55
|
+
@instance.bite
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should render the given response' do
|
59
|
+
@instance.bite.last.should == ['Chunky Bacon']
|
60
|
+
end
|
61
|
+
|
62
|
+
%w{post put delete head trace options}.each do |verb|
|
63
|
+
it 'should call to the #{verb} method if called with #{verb.upcase}' do
|
64
|
+
mock_env = mock_env('/just_a_test')
|
65
|
+
mock_env['REQUEST_METHOD'] = verb.upcase
|
66
|
+
@instance = TestClass.new(mock_env, ['/just_a_test'])
|
67
|
+
@instance.should_receive(verb)
|
68
|
+
@instance.bite
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should return an API Error to #{verb.upcase} if no defined' do
|
72
|
+
mock_env = mock_env('/just_a_test')
|
73
|
+
mock_env['REQUEST_METHOD'] = verb.upcase
|
74
|
+
@instance = TestClass.new(mock_env, ['/just_a_test'])
|
75
|
+
@instance.should_receive(verb).and_raise(Lunetas::Error::APIError)
|
76
|
+
@instance.bite.last.should == ["API route error"]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should call to other_verb with the passed method' do
|
81
|
+
mock_env = mock_env('/just_a_test')
|
82
|
+
mock_env['REQUEST_METHOD'] = 'TEAPOT'
|
83
|
+
@instance = TestClass.new(mock_env, ['/just_a_test'])
|
84
|
+
@instance.should_receive(:other_verb).with('TEAPOT')
|
85
|
+
@instance.bite
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should call to other_verb with the passed method and return the response if method handled' do
|
89
|
+
mock_env = mock_env('/just_a_test')
|
90
|
+
mock_env['REQUEST_METHOD'] = 'TEAPOT'
|
91
|
+
@instance = TestClass.new(mock_env, ['/just_a_test'])
|
92
|
+
@instance.should_receive(:other_verb).with('TEAPOT').and_return('TEAPOT YEAH')
|
93
|
+
@instance.bite.last.should == ['TEAPOT YEAH']
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should call to other_verb with the passed method and return error if method not handled' do
|
97
|
+
mock_env = mock_env('/just_a_test')
|
98
|
+
mock_env['REQUEST_METHOD'] = 'TEAPOT'
|
99
|
+
@instance = TestClass.new(mock_env, ['/just_a_test'])
|
100
|
+
@instance.should_receive(:other_verb).with('TEAPOT')
|
101
|
+
@instance.bite.last.should == ['API route error']
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require 'lunetas'
|
4
|
+
require 'spec'
|
5
|
+
require 'spec/autorun'
|
6
|
+
|
7
|
+
Spec::Runner.configure do |config|
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
def mock_candy
|
12
|
+
body = [200, {'Content-Type' => 'text/html'}, ["body"]]
|
13
|
+
luneta_object = mock(:Luneta, :bite => body)
|
14
|
+
[mock(:Luneta, :new => luneta_object), luneta_object]
|
15
|
+
end
|
16
|
+
|
17
|
+
def mock_env(path)
|
18
|
+
Rack::MockRequest.env_for(path)
|
19
|
+
end
|
20
|
+
|
21
|
+
class TestClass
|
22
|
+
include Lunetas::Candy
|
23
|
+
matches '/just_a_test'
|
24
|
+
def get
|
25
|
+
'Chunky Bacon'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class TestException < StandardError
|
30
|
+
def code
|
31
|
+
400
|
32
|
+
end
|
33
|
+
def message
|
34
|
+
'a'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
metadata
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lunetas
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 31
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 0.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- "Iv\xC3\xA1n Vald\xC3\xA9s (@ivanvc)"
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-08-21 00:00:00 -05:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 13
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 2
|
33
|
+
- 9
|
34
|
+
version: 1.2.9
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: yard
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 3
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
version: "0"
|
49
|
+
type: :development
|
50
|
+
version_requirements: *id002
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
name: shotgun
|
53
|
+
prerelease: false
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 3
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
type: :development
|
64
|
+
version_requirements: *id003
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: rack
|
67
|
+
prerelease: false
|
68
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
hash: 3
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
version: "0"
|
77
|
+
type: :runtime
|
78
|
+
version_requirements: *id004
|
79
|
+
description: This is a micro framework based in Rack, inspired in Sinatra, camping and many others. The intention is to have fast responses for simple API calls. The base unit of this framework are the classes, which registers a regular expression that will match this resource.
|
80
|
+
email: iv@nvald.es
|
81
|
+
executables: []
|
82
|
+
|
83
|
+
extensions: []
|
84
|
+
|
85
|
+
extra_rdoc_files:
|
86
|
+
- LICENSE
|
87
|
+
- README.md
|
88
|
+
files:
|
89
|
+
- .document
|
90
|
+
- .gitignore
|
91
|
+
- LICENSE
|
92
|
+
- README.md
|
93
|
+
- Rakefile
|
94
|
+
- VERSION
|
95
|
+
- examples/config.ru
|
96
|
+
- examples/testing.rb
|
97
|
+
- lib/lunetas.rb
|
98
|
+
- lib/lunetas/bag.rb
|
99
|
+
- lib/lunetas/candy.rb
|
100
|
+
- lib/lunetas/error.rb
|
101
|
+
- spec/lunetas/bag_spec.rb
|
102
|
+
- spec/lunetas/candy_spec.rb
|
103
|
+
- spec/spec.opts
|
104
|
+
- spec/spec_helper.rb
|
105
|
+
has_rdoc: true
|
106
|
+
homepage: http://github.com/ivanvc/lunetas
|
107
|
+
licenses: []
|
108
|
+
|
109
|
+
post_install_message:
|
110
|
+
rdoc_options:
|
111
|
+
- --charset=UTF-8
|
112
|
+
require_paths:
|
113
|
+
- lib
|
114
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
hash: 3
|
120
|
+
segments:
|
121
|
+
- 0
|
122
|
+
version: "0"
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
none: false
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
hash: 3
|
129
|
+
segments:
|
130
|
+
- 0
|
131
|
+
version: "0"
|
132
|
+
requirements: []
|
133
|
+
|
134
|
+
rubyforge_project:
|
135
|
+
rubygems_version: 1.3.7
|
136
|
+
signing_key:
|
137
|
+
specification_version: 3
|
138
|
+
summary: Rack micro framework intended for APIs
|
139
|
+
test_files:
|
140
|
+
- spec/lunetas/bag_spec.rb
|
141
|
+
- spec/lunetas/candy_spec.rb
|
142
|
+
- spec/spec_helper.rb
|
143
|
+
- examples/testing.rb
|