bebop 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.markdown ADDED
@@ -0,0 +1,111 @@
1
+ Bebop
2
+ =====
3
+
4
+ Bebop is small Sinatra/Monk extension for DRY resource based routing. It provides targeted filters, path helpers, nested resources, printable routing information, and familiar action methods like new, show, destroy, update, and index.
5
+
6
+ The name comes from its happy partnering with the [Monk](http://monkrb.com) glue framework, as Thelonius Monk is considered to be the father of bebop.
7
+
8
+
9
+ dependencies
10
+ ------------
11
+
12
+ * Sinatra
13
+ * ActiveSupport
14
+
15
+ install
16
+ -------
17
+
18
+ Make sure you have gemcutter.org as one of your sources:
19
+
20
+ gem sources -a http://gemcutter.org
21
+
22
+ Then:
23
+
24
+ gem install bebop
25
+
26
+ verify
27
+ ------
28
+
29
+ Requires rspec version 1.2.9 or higher
30
+
31
+ cd /path/to/bebop; spec spec
32
+
33
+ sample
34
+ ------
35
+
36
+ If you were using an Active Record model Foo:
37
+
38
+ require 'bebop'
39
+ require 'sinatra'
40
+ require 'foo'
41
+
42
+ class MyApp < Sinatra::Base
43
+ register Bebop
44
+
45
+ resource :foos do |foos|
46
+
47
+ # GET /foos/:foo_id
48
+ foos.show do
49
+ @foo = Foo.find(params[:foo_id])
50
+ haml :'foos/show'
51
+ end
52
+
53
+ # GET /foos/new
54
+ foos.new do
55
+ @foo = Foo.new
56
+ haml :'foos/new'
57
+ end
58
+ end
59
+ end
60
+
61
+ more detail
62
+ -----------
63
+
64
+ See the examples directory. You can play with each of the examples as follows:
65
+
66
+ $ pwd
67
+ /path/to/bebop
68
+ $ ruby examples/routes.rb
69
+ == Sinatra/0.9.4 has taken the stage on 4567 for development with backup from Thin
70
+ >> Thin web server (v1.2.4 codename Flaming Astroboy)
71
+ >> Maximum connections set to 1024
72
+ >> Listening on 0.0.0.0:4567, CTRL+C to stop
73
+
74
+ routes
75
+ ------
76
+
77
+ Run your sinatra/monk app with the PROUTES env variable set to view the routes created with the resource method
78
+
79
+ $ ruby my_app.rb PROUTES=true
80
+
81
+ or
82
+
83
+ $ thor monk:start PROUTES=true
84
+
85
+ NOTE: planning to change the formatting soon, as it currently sucks
86
+
87
+ license
88
+ -------
89
+
90
+ (The MIT License)
91
+
92
+ Copyright (c) 2010 FIX
93
+
94
+ Permission is hereby granted, free of charge, to any person obtaining
95
+ a copy of this software and associated documentation files (the
96
+ 'Software'), to deal in the Software without restriction, including
97
+ without limitation the rights to use, copy, modify, merge, publish,
98
+ distribute, sublicense, and/or sell copies of the Software, and to
99
+ permit persons to whom the Software is furnished to do so, subject to
100
+ the following conditions:
101
+
102
+ The above copyright notice and this permission notice shall be
103
+ included in all copies or substantial portions of the Software.
104
+
105
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
106
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
107
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
108
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
109
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
110
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
111
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'rake'
2
+ require 'spec/rake/spectask'
3
+
4
+ desc "Run all examples with RCov"
5
+ Spec::Rake::SpecTask.new('specs_with_rcov') do |t|
6
+ t.spec_files = FileList['spec/**/*.rb']
7
+ t.rcov = true
8
+ t.rcov_opts = ['--exclude spec', '--exclude "gems/*"', '--exclude "bebop.rb"' ]
9
+ end
data/bebop.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'bebop'
3
+ s.version = '0.1.0'
4
+ s.date = '2010-1-10'
5
+
6
+ s.summary = s.description = "A small Sinatra/Monk extension for resource routing"
7
+
8
+ s.authors = ["John Bender"]
9
+ s.homepage = 'http://github.com/johnbender/bebop'
10
+ s.email = 'john.m.bender@gmail.com'
11
+
12
+ # = MANIFEST =
13
+ s.files = %w[
14
+ README.markdown
15
+ Rakefile
16
+ bebop.gemspec
17
+ examples/filters.rb
18
+ examples/routes.rb
19
+ lib/bebop/ext.rb
20
+ lib/bebop.rb
21
+ spec/bebop_spec.rb
22
+ ]
23
+ # = MANIFEST =
24
+ s.add_dependency 'sinatra', '>= 0.9.4'
25
+ s.add_dependency 'activesupport', '>= 2.3.5'
26
+
27
+ s.add_development_dependency 'rspec', '>=1.2.9'
28
+
29
+ s.has_rdoc = false
30
+ s.require_paths = %w[lib]
31
+ s.rubyforge_project = 'bebop'
32
+ s.rubygems_version = '1.3.5'
33
+ end
@@ -0,0 +1,60 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'bebop')
2
+ require 'sinatra'
3
+
4
+ class MyApp < Sinatra::Base
5
+ register Bebop
6
+
7
+ resource :foos do |foos|
8
+ # Bebop provides some simple targeting for before and after filters, with the
9
+ # caveat that they must be defined before the routes they target within the resource block
10
+ # To have your filter run before all routes under a given resource and its child resources
11
+ # pass :all as the first parameter
12
+ #
13
+ foos.before :all do
14
+ @all = 'all'
15
+ end
16
+
17
+ # To have your filter run before a specific route, the route must be one of the seven helper
18
+ # routes (see example/routes.rb) or specify the :identifier parameter
19
+ #
20
+ foos.before :new do
21
+ @new = 'new'
22
+ end
23
+
24
+ foos.new do
25
+ "#{@all} #{@new}" # => 'all new'
26
+ end
27
+
28
+ # You can target the vanila methods by providing the :identifier hash option
29
+ #
30
+ # GET /foos/baz
31
+ foos.get '/baz', :identifier => :new do
32
+ @new # => 'new'
33
+ end
34
+
35
+ # You can also specify a before filter for nested routes by using the child resource name
36
+ #
37
+ foos.before :bars do
38
+ @bars = 'some bars'
39
+ end
40
+
41
+ foos.resource :bars do |bars|
42
+ bars.get '/some_bars' do
43
+ @bars # => 'some bars'
44
+ end
45
+ end
46
+
47
+ foos.get '/bak' do
48
+ @bars # => nil
49
+ end
50
+
51
+ # Finally you can specify many different methods in your filters by passing many identifiers
52
+ #
53
+ foos.before :bak, :baz do
54
+ @bak_baz = "bak 'n' baz"
55
+ end
56
+
57
+ foos.get('/something', :identifier => :bak) { @bak_baz }
58
+ foos.get('/anything', :identifier => :baz) { @bak_baz }
59
+ end
60
+ end
@@ -0,0 +1,79 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'bebop')
2
+ require 'sinatra'
3
+
4
+ class MyApp < Sinatra::Base
5
+ register Bebop
6
+
7
+ resource :foos do |foos|
8
+
9
+ # Any of the traditional sinatra methods called on the block parameter
10
+ # will take the first argument (or an empty string) and apply it to
11
+ # the resource base
12
+ #
13
+ # GET /foos/baz
14
+ foos.get '/baz' do
15
+ 'baz'
16
+ end
17
+
18
+ # There are 7 helper methods for the traditional resource actions. They
19
+ # are index, new, create, update, edit, destroy, and show. Each is a wrapper
20
+ # for the corresponding Sinatra method
21
+ #
22
+ # GET /foos
23
+ foos.index {}
24
+
25
+ # For actions that require parameters the parameter name is derived from the singularized
26
+ # name of the resource with '_id' appended.
27
+ #
28
+ # GET /foos/:foo_id
29
+ foos.show {}
30
+
31
+ # GET /foos/new
32
+ foos.new {}
33
+
34
+ # POST /foos
35
+ foos.create {}
36
+
37
+ # PUT /foos/:foo_id
38
+ foos.update {}
39
+
40
+ # GET /foos/:foo_id/edit
41
+ foos.edit {}
42
+
43
+ # DELETE /foos/:foo_id
44
+ foos.destroy {}
45
+
46
+ # For each of the helper methods, and any generic method (eg foos.get) that specifies the :identifier
47
+ # option, bebop will define a relative path helper. See the nested resource below for the nameing of those
48
+ # methods
49
+ #
50
+ # POST /foos/do/redirect
51
+ foos.get 'do/redirect' do
52
+ # Redirects to /foos/1
53
+ redirect foos_show_path(1)
54
+ end
55
+
56
+ # If you want to represent the relationship of your models through nested resources use
57
+ # the resource method with the block parameter and all new routes will be nested and
58
+ # parameterized properly
59
+ #
60
+ # Prefix all with /foos/:foo_id
61
+ foos.resource :bars do |bars|
62
+
63
+ # GET /foos/:foo_id/bars/:bar_id/edit
64
+ bars.edit do
65
+ "foo: #{params[:foo_id]} bar: #{params[:bar_id]}"
66
+ end
67
+
68
+ bars.get '/redirect' do
69
+
70
+ # The route helper method naming convention is simple and easy to remember as it follows
71
+ # the order of nesting for the given route starting with the original parent resource and
72
+ # ending with the method identifier.
73
+ #
74
+ # Redirects to /foos/1/bars/2/edit
75
+ redirect foos_bars_edit_path(1, 2)
76
+ end
77
+ end
78
+ end
79
+ end
data/lib/bebop.rb ADDED
@@ -0,0 +1,4 @@
1
+ libdir = File.dirname(__FILE__)
2
+ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
3
+
4
+ require 'bebop/ext'
data/lib/bebop/ext.rb ADDED
@@ -0,0 +1,184 @@
1
+ require 'active_support'
2
+
3
+ module Bebop
4
+ class InvalidPathArgumentError < ArgumentError; end
5
+ PARAM_REGEX = /:[a-zA-Z0-9_]+/
6
+
7
+ def resource(name, &block)
8
+ resource = ResourceRouter.new
9
+ resource.resource(name, &block)
10
+ resource.routes.each do |method, route, options, block, helper|
11
+ send(method, route, options, &block)
12
+ define_route_helper(helper, route) if helper
13
+ end
14
+ resource.print if ENV['PROUTES']
15
+ end
16
+
17
+ def define_route_helper(helper, route)
18
+ define_method helper do |*args|
19
+ unless route.scan(PARAM_REGEX).length == args.length
20
+ raise InvalidPathArgumentError.new("invalid number of parameters #{args.length} for: #{route}")
21
+ end
22
+
23
+ args.inject(route.dup) do |acc, arg|
24
+ #handle fixnums and ar objects
25
+ arg = (arg.kind_of?(Fixnum) ? arg : arg.id)
26
+ acc.sub!(PARAM_REGEX, arg.to_s)
27
+ end
28
+ end
29
+ end
30
+
31
+
32
+ class ResourceRouter
33
+ attr_accessor :routes
34
+
35
+ def initialize(parent_resources=[], before_all=[], after_all=[])
36
+ @current_resource = parent_resources.pop
37
+ @parent_resources = parent_resources
38
+ @before, @after, @routes = before_all, after_all, []
39
+ end
40
+
41
+ def get(route, options={}, &block)
42
+ add_route(:get, route, options, block)
43
+ end
44
+
45
+ def put(route, options={}, &block)
46
+ add_route(:put, route, options, block)
47
+ end
48
+
49
+ def post(route, options={}, &block)
50
+ add_route(:post, route, options, block)
51
+ end
52
+
53
+ def delete(route, options={}, &block)
54
+ add_route(:delete, route, options, block)
55
+ end
56
+
57
+ def head(route, options={}, &block)
58
+ add_route(:head, route, options, block)
59
+ end
60
+
61
+ def new(options={}, &block)
62
+ get 'new', options.merge(:identifier => :new), &block
63
+ end
64
+
65
+ def create(options={}, &block)
66
+ post '' , options.merge(:identifier => :create), &block
67
+ end
68
+
69
+ def edit(options={}, &block)
70
+ get append_token(resource_identifier, 'edit') , options.merge(:identifier => :edit), &block
71
+ end
72
+
73
+ def index(options={}, &block)
74
+ get '', options.merge(:identifier => :index), &block
75
+ end
76
+
77
+ def show(route=nil, options={}, &block)
78
+ get append_token(resource_identifier, (route || '').to_s), options.merge(:identifier => route || :show), &block
79
+ end
80
+
81
+ def destroy(options={}, &block)
82
+ delete resource_identifier, options.merge(:identifier => :destroy), &block
83
+ end
84
+
85
+ def update(options={}, &block)
86
+ put resource_identifier, options.merge(:identifier => :update), &block
87
+ end
88
+
89
+ def before(*params, &block)
90
+ add_filter(@before, params, block)
91
+ end
92
+
93
+ def after(*params, &block)
94
+ add_filter(@after, params, block)
95
+ end
96
+
97
+ def resource(name, &block)
98
+ before_filters = filters(@before, :all, name)
99
+ after_filters = filters(@after, :all, name)
100
+
101
+ router = self.class.new(all_resources + [name], before_filters, after_filters)
102
+ yield(router)
103
+ @routes += router.routes
104
+ end
105
+
106
+ def print
107
+ #TODO 6! 6! Block parameters, Ah Ah Ah! -> probably need route objects
108
+ @routes.each do |method, route, options, block, helper, identifier|
109
+ puts "#{route}"
110
+ puts " method: #{method.to_s.upcase}"
111
+ puts " helper: #{helper}" if helper
112
+ puts " identifier: #{identifier}" if identifier
113
+ puts
114
+ end
115
+ end
116
+
117
+ private
118
+
119
+ def all_resources
120
+ #in the initial call to resource there is current_resource
121
+ @current_resource ? @parent_resources + [@current_resource] : @parent_resources
122
+ end
123
+
124
+ def resource_identifier(resource=@current_resource)
125
+ ":#{resource.to_s.singularize}_id"
126
+ end
127
+
128
+ def add_filter(type, params, block)
129
+ params = [:all] if params.empty?
130
+ type << {:routes => params, :block => block}
131
+ end
132
+
133
+ def add_route(method, route, options, block)
134
+ identifier =options[:identifier]
135
+ route = append_to_path(route)
136
+ block = add_filters_to_block(block, identifier, method)
137
+ helper = route_helper(identifier)
138
+
139
+ #Sinatra doesn't like the spurious options
140
+ options.delete(:identifier)
141
+
142
+ @routes << [method, route, options, block, helper]
143
+ end
144
+
145
+ def append_to_path(str)
146
+ append_token(append_token(parent_resource_path, @current_resource), str)
147
+ end
148
+
149
+ def parent_resource_path
150
+ @parent_resources.inject('') do |acc, x|
151
+ append_token(append_token(acc, x), resource_identifier(x))
152
+ end
153
+ end
154
+
155
+ def append_token(l, tkn)
156
+ tkn = tkn.to_s
157
+ tkn = "/#{tkn}" unless tkn.empty? || tkn =~ /^\//
158
+ "#{l}#{tkn}"
159
+ end
160
+
161
+ def route_helper(identifier)
162
+ helper_tokens = (@parent_resources.dup << @current_resource) << identifier
163
+ "#{helper_tokens.join('_')}_path".to_sym
164
+ end
165
+
166
+ def add_filters_to_block(block, identifier, method)
167
+ before = filters(@before, identifier, method, :all, @current_resource)
168
+ after = filters(@after, identifier, method, :all, @current_resource)
169
+ Proc.new do
170
+ before.each { |f| instance_eval( &f[:block] ) }
171
+ result = instance_eval(&block)
172
+ after.each { |f| instance_eval(&f[:block]) }
173
+ result
174
+ end
175
+ end
176
+
177
+ def filters(list, *identifiers)
178
+ list.select do |filter|
179
+ rs = filter[:routes]
180
+ !(rs & identifiers).empty?
181
+ end
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,201 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'bebop')
2
+ require 'rack/test'
3
+ require 'sinatra'
4
+
5
+ class TestClass < Sinatra::Base
6
+ register Bebop
7
+ def self.global
8
+ @@global
9
+ end
10
+ def self.global=(val)
11
+ @@global = val
12
+ end
13
+ end
14
+
15
+ describe Bebop do
16
+ include Rack::Test::Methods
17
+
18
+ def app
19
+ @test_app ||= TestClass.new
20
+ @test_app
21
+ end
22
+
23
+ before :all do
24
+ app
25
+ @class = TestClass
26
+ use_bebop
27
+ end
28
+
29
+ before :each do
30
+ TestClass.global = nil
31
+ end
32
+
33
+ it "should define route helpers properly for routes specifying an identifier" do
34
+ @class.instance_methods.should include('foos_bars_index_path')
35
+ @class.instance_methods.should include('foos_create_path')
36
+ end
37
+
38
+ it "should provide the correct relative url from the route helpers" do
39
+ @test_app.foos_bars_index_path(1).should == '/foos/1/bars'
40
+ @test_app.foos_bars_update_path(1,2).should == '/foos/1/bars/2'
41
+ end
42
+
43
+ it "should raise an error when the wrong number of paramters are passed to a route helper" do
44
+ lambda {@test_app.foos_bars_update_path(1)}.should raise_error(Bebop::InvalidPathArgumentError)
45
+ end
46
+
47
+ it "should define a route with new for the new method" do
48
+ get '/foos/new'
49
+ last_response.body.should == "new"
50
+ end
51
+
52
+ it "should define a route with an identifer and append edit for the edit method" do
53
+ get '/foos/1/edit'
54
+ last_response.body.should == 'edit 1'
55
+ end
56
+
57
+ it "shoud define a route with an identifer for show and recieve the proper parameters" do
58
+ get '/foos/1/bars/2'
59
+ last_response.body.should == 'show 1 2'
60
+ end
61
+
62
+ it "should respond correctly when the route is consulted" do
63
+ post '/foos'
64
+ last_response.body.should match(/#{BEFORE_ALL}/)
65
+ end
66
+
67
+ it "should call before and after blocks correctly based on the identifier" do
68
+ put '/foos/1'
69
+ last_response.body.should match(/#{BEFORE_UPDATE}/)
70
+
71
+ post '/foos'
72
+ last_response.body.should_not match(/#{BEFORE_UPDATE}/)
73
+ end
74
+
75
+ it "should correctly append any vanilla sinatra method with the resource prefix" do
76
+ get '/foos/arbitrary'
77
+ last_response.body.should == 'baz'
78
+ end
79
+
80
+ it "should not call before and after blocks in a nested resource based on the identifer" do
81
+ put '/foos/1/bars/1'
82
+ last_response.body.should_not match(/#{BEFORE_UPDATE}/)
83
+ end
84
+
85
+ it "should call before and after all blocks on all resource routes" do
86
+ put '/foos/1'
87
+ last_response.body.should match(/#{BEFORE_ALL}/)
88
+
89
+ post '/foos'
90
+ last_response.body.should match(/#{BEFORE_ALL}/)
91
+
92
+ get '/foos/1/bars'
93
+ last_response.body.should match(/#{BEFORE_ALL}/)
94
+
95
+ delete '/foos/1/bars/1'
96
+ last_response.body.should match(/#{BEFORE_ALL}/)
97
+
98
+ put '/foos/1/bars/1'
99
+ last_response.body.should match(/#{BEFORE_ALL}/)
100
+ end
101
+
102
+ it "should call before and after resource blocks only on the nested resource routes" do
103
+ get '/foos/1/bars'
104
+ last_response.body.should match(/#{BEFORE_BARS}/)
105
+
106
+ delete '/foos/1/bars/1'
107
+ last_response.body.should match(/#{BEFORE_BARS}/)
108
+ end
109
+
110
+ it "should not call before and after resource blocks on non nested resource blocks" do
111
+ post '/foos'
112
+ last_response.body.should_not match(/#{BEFORE_BARS}/)
113
+ end
114
+
115
+ it "should call before and after filters without any identifier specified before all routes" do
116
+ put '/foos/1'
117
+ last_response.body.should match(/#{BEFORE_ALL_2}/)
118
+
119
+ post '/foos'
120
+ last_response.body.should match(/#{BEFORE_ALL_2}/)
121
+
122
+ get '/foos/1/bars'
123
+ last_response.body.should match(/#{BEFORE_ALL_2}/)
124
+
125
+ delete '/foos/1/bars/1'
126
+ last_response.body.should match(/#{BEFORE_ALL_2}/)
127
+
128
+ put '/foos/1/bars/1'
129
+ last_response.body.should match(/#{BEFORE_ALL_2}/)
130
+ end
131
+
132
+ it "should call before and after filters that specify multiple identifiers before the proper routes" do
133
+ post '/foos'
134
+ TestClass.global.should == AFTER_VALUE
135
+
136
+ put '/foos/1'
137
+ TestClass.global.should == AFTER_VALUE
138
+ end
139
+
140
+ it "should not call before and after filters that specify multiple parameters on anyting else" do
141
+ get '/foos/new'
142
+ TestClass.global = nil
143
+ end
144
+
145
+ it "should not prepend previous nested routes on non nested routes that follow" do
146
+ get '/foos/do/something'
147
+ last_response.body.should == 'success'
148
+ end
149
+
150
+ it "should produce correct routes for more than 2 levels of nesting"
151
+
152
+ BEFORE_BARS = '__before_bars__'
153
+ BEFORE_UPDATE = '__before_update__'
154
+ BEFORE_ALL = '__all__'
155
+ BEFORE_ALL_2 = '__2all__'
156
+ AFTER_VALUE = '__after__'
157
+
158
+ def use_bebop
159
+ # ENV['PROUTES']='t'
160
+ @class.resource :foos do |foo|
161
+
162
+ foo.before :all do
163
+ @all = BEFORE_ALL
164
+ end
165
+
166
+ foo.before do
167
+ @all2 = BEFORE_ALL_2
168
+ end
169
+
170
+ foo.before :update do
171
+ @update = BEFORE_UPDATE
172
+ end
173
+
174
+ foo.before :bars do
175
+ @bars = BEFORE_BARS
176
+ end
177
+
178
+ foo.after :create, :update do
179
+ TestClass.global = AFTER_VALUE
180
+ end
181
+
182
+ foo.get(:arbitrary) { 'baz' }
183
+
184
+ foo.create { "#{@all2}#{@all}#{@update}#{@bars}" }
185
+ foo.update { "#{@all2}#{@all}#{@update}#{@bars}" }
186
+
187
+ foo.new { "new" }
188
+ foo.edit { "edit #{params[:foo_id]}" }
189
+
190
+ foo.resource :bars do |bar|
191
+ bar.index { "#{@all2}#{@all}#{@update}#{@bars}" }
192
+ bar.update { "#{@all2}#{@all}#{@update}#{@bars}" }
193
+ bar.destroy { "#{@all2}#{@all}#{@update}#{@bars}" }
194
+
195
+ bar.show { "show #{params[:foo_id]} #{params[:bar_id]}" }
196
+ end
197
+
198
+ foo.get('/do/something') { 'success' }
199
+ end
200
+ end
201
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bebop
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - John Bender
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-10 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: sinatra
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.9.4
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: activesupport
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.3.5
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: rspec
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.2.9
44
+ version:
45
+ description: A small Sinatra/Monk extension for resource routing
46
+ email: john.m.bender@gmail.com
47
+ executables: []
48
+
49
+ extensions: []
50
+
51
+ extra_rdoc_files: []
52
+
53
+ files:
54
+ - README.markdown
55
+ - Rakefile
56
+ - bebop.gemspec
57
+ - examples/filters.rb
58
+ - examples/routes.rb
59
+ - lib/bebop/ext.rb
60
+ - lib/bebop.rb
61
+ - spec/bebop_spec.rb
62
+ has_rdoc: true
63
+ homepage: http://github.com/johnbender/bebop
64
+ licenses: []
65
+
66
+ post_install_message:
67
+ rdoc_options: []
68
+
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: "0"
82
+ version:
83
+ requirements: []
84
+
85
+ rubyforge_project: bebop
86
+ rubygems_version: 1.3.5
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: A small Sinatra/Monk extension for resource routing
90
+ test_files: []
91
+