grape 0.0.0.alpha.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grape might be problematic. Click here for more details.

data/.rspec CHANGED
@@ -1,3 +1,3 @@
1
1
  --color
2
2
  --format=nested
3
- --backtrace
3
+ --fail-fast
data/Gemfile CHANGED
@@ -1,8 +1,10 @@
1
1
  gem 'rack'
2
- gem 'rack-mount'
2
+ gem 'rack-mount', '~> 0.6.13'
3
3
  gem 'rack-jsonp'
4
4
 
5
- gem 'activesupport', '~> 3.0.0'
5
+ gem 'json'
6
+ gem 'multi_json'
7
+ gem 'multi_xml'
6
8
 
7
9
  group :development do
8
10
  gem 'rake'
@@ -10,7 +12,7 @@ group :development do
10
12
  end
11
13
 
12
14
  group :test do
13
- gem 'rspec', '>= 2.0.0.beta.19'
14
15
  gem 'rack-test'
16
+ gem 'rspec', '>= 2.1.0'
15
17
  gem 'cucumber', '>= 0.8.5'
16
18
  end
data/Gemfile.lock CHANGED
@@ -1,6 +1,5 @@
1
1
  GEM
2
2
  specs:
3
- activesupport (3.0.0)
4
3
  builder (2.1.2)
5
4
  cucumber (0.8.5)
6
5
  builder (~> 2.1.2)
@@ -17,22 +16,25 @@ GEM
17
16
  gemcutter (>= 0.1.0)
18
17
  git (>= 1.2.5)
19
18
  rubyforge (>= 2.0.0)
19
+ json (1.4.6)
20
20
  json_pure (1.4.3)
21
+ multi_json (0.0.4)
22
+ multi_xml (0.0.1)
21
23
  rack (1.2.1)
22
24
  rack-jsonp (1.0.0)
23
- rack-mount (0.6.9)
25
+ rack-mount (0.6.13)
24
26
  rack (>= 1.0.0)
25
27
  rack-test (0.5.4)
26
28
  rack (>= 1.0)
27
29
  rake (0.8.7)
28
- rspec (2.0.0.beta.19)
29
- rspec-core (= 2.0.0.beta.19)
30
- rspec-expectations (= 2.0.0.beta.19)
31
- rspec-mocks (= 2.0.0.beta.19)
32
- rspec-core (2.0.0.beta.19)
33
- rspec-expectations (2.0.0.beta.19)
34
- diff-lcs (>= 1.1.2)
35
- rspec-mocks (2.0.0.beta.19)
30
+ rspec (2.1.0)
31
+ rspec-core (~> 2.1.0)
32
+ rspec-expectations (~> 2.1.0)
33
+ rspec-mocks (~> 2.1.0)
34
+ rspec-core (2.1.0)
35
+ rspec-expectations (2.1.0)
36
+ diff-lcs (~> 1.1.2)
37
+ rspec-mocks (2.1.0)
36
38
  rubyforge (2.0.4)
37
39
  json_pure (>= 1.1.7)
38
40
  term-ansicolor (1.0.5)
@@ -42,12 +44,14 @@ PLATFORMS
42
44
  ruby
43
45
 
44
46
  DEPENDENCIES
45
- activesupport (~> 3.0.0)
46
47
  cucumber (>= 0.8.5)
47
48
  jeweler
49
+ json
50
+ multi_json
51
+ multi_xml
48
52
  rack
49
53
  rack-jsonp
50
- rack-mount
54
+ rack-mount (~> 0.6.13)
51
55
  rack-test
52
56
  rake
53
- rspec (>= 2.0.0.beta.19)
57
+ rspec (>= 2.1.0)
data/README.rdoc CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  Grape is a REST-like API micro-framework for Ruby. It is built to complement existing web application frameworks such as Rails and Sinatra by providing a simple DSL to easily provide APIs. It has built-in support for common conventions such as multiple formats, subdomain/prefix restriction, and versioning.
6
6
 
7
- class Twitter < Grape::Base
7
+ class Twitter::API < Grape::Base
8
8
  subdomain 'api'
9
9
  version '1'
10
10
  formats :xml, :json
@@ -30,6 +30,15 @@ Grape is a REST-like API micro-framework for Ruby. It is built to complement exi
30
30
  end
31
31
  end
32
32
 
33
+ # Rack endpoint
34
+ Twitter::API.statuses.timelines.get(:public_timeline)
35
+
36
+ class Twitter::API::User < Grape::Resource::ActiveRecord
37
+ represents ::User
38
+
39
+ property :status, lambda{|u| u.latest_status}, Twitter::API::Status
40
+ end
41
+
33
42
  == Note on Patches/Pull Requests
34
43
 
35
44
  * Fork the project.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0.alpha.2
1
+ 0.1.0
data/grape.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{grape}
8
- s.version = "0.0.0.alpha.2"
8
+ s.version = "0.1.0"
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Michael Bleigh"]
12
- s.date = %q{2010-08-30}
12
+ s.date = %q{2010-11-13}
13
13
  s.description = %q{A Ruby framework for rapid API development with great conventions.}
14
14
  s.email = %q{michael@intridea.com}
15
15
  s.extra_rdoc_files = [
@@ -30,18 +30,26 @@ Gem::Specification.new do |s|
30
30
  "autotest/discover.rb",
31
31
  "grape.gemspec",
32
32
  "lib/grape.rb",
33
+ "lib/grape/api.rb",
34
+ "lib/grape/endpoint.rb",
35
+ "lib/grape/middleware/auth/basic.rb",
33
36
  "lib/grape/middleware/auth/oauth2.rb",
34
37
  "lib/grape/middleware/base.rb",
35
38
  "lib/grape/middleware/error.rb",
36
39
  "lib/grape/middleware/formatter.rb",
37
40
  "lib/grape/middleware/prefixer.rb",
38
41
  "lib/grape/middleware/versioner.rb",
42
+ "lib/grape/middleware_stack.rb",
43
+ "spec/grape/api_spec.rb",
44
+ "spec/grape/endpoint_spec.rb",
45
+ "spec/grape/middleware/auth/basic_spec.rb",
39
46
  "spec/grape/middleware/auth/oauth2_spec.rb",
40
47
  "spec/grape/middleware/base_spec.rb",
41
48
  "spec/grape/middleware/error_spec.rb",
42
49
  "spec/grape/middleware/formatter_spec.rb",
43
50
  "spec/grape/middleware/prefixer_spec.rb",
44
51
  "spec/grape/middleware/versioner_spec.rb",
52
+ "spec/grape/middleware_stack_spec.rb",
45
53
  "spec/grape_spec.rb",
46
54
  "spec/spec_helper.rb"
47
55
  ]
@@ -51,12 +59,16 @@ Gem::Specification.new do |s|
51
59
  s.rubygems_version = %q{1.3.7}
52
60
  s.summary = %q{A Ruby framework for rapid API development.}
53
61
  s.test_files = [
54
- "spec/grape/middleware/auth/oauth2_spec.rb",
62
+ "spec/grape/api_spec.rb",
63
+ "spec/grape/endpoint_spec.rb",
64
+ "spec/grape/middleware/auth/basic_spec.rb",
65
+ "spec/grape/middleware/auth/oauth2_spec.rb",
55
66
  "spec/grape/middleware/base_spec.rb",
56
67
  "spec/grape/middleware/error_spec.rb",
57
68
  "spec/grape/middleware/formatter_spec.rb",
58
69
  "spec/grape/middleware/prefixer_spec.rb",
59
70
  "spec/grape/middleware/versioner_spec.rb",
71
+ "spec/grape/middleware_stack_spec.rb",
60
72
  "spec/grape_spec.rb",
61
73
  "spec/spec_helper.rb"
62
74
  ]
@@ -67,24 +79,30 @@ Gem::Specification.new do |s|
67
79
 
68
80
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
69
81
  s.add_runtime_dependency(%q<rack>, [">= 0"])
70
- s.add_runtime_dependency(%q<rack-mount>, [">= 0"])
82
+ s.add_runtime_dependency(%q<rack-mount>, ["~> 0.6.13"])
71
83
  s.add_runtime_dependency(%q<rack-jsonp>, [">= 0"])
72
- s.add_runtime_dependency(%q<activesupport>, ["~> 3.0.0"])
84
+ s.add_runtime_dependency(%q<json>, [">= 0"])
85
+ s.add_runtime_dependency(%q<multi_json>, [">= 0"])
86
+ s.add_runtime_dependency(%q<multi_xml>, [">= 0"])
73
87
  s.add_development_dependency(%q<rake>, [">= 0"])
74
88
  s.add_development_dependency(%q<jeweler>, [">= 0"])
75
89
  else
76
90
  s.add_dependency(%q<rack>, [">= 0"])
77
- s.add_dependency(%q<rack-mount>, [">= 0"])
91
+ s.add_dependency(%q<rack-mount>, ["~> 0.6.13"])
78
92
  s.add_dependency(%q<rack-jsonp>, [">= 0"])
79
- s.add_dependency(%q<activesupport>, ["~> 3.0.0"])
93
+ s.add_dependency(%q<json>, [">= 0"])
94
+ s.add_dependency(%q<multi_json>, [">= 0"])
95
+ s.add_dependency(%q<multi_xml>, [">= 0"])
80
96
  s.add_dependency(%q<rake>, [">= 0"])
81
97
  s.add_dependency(%q<jeweler>, [">= 0"])
82
98
  end
83
99
  else
84
100
  s.add_dependency(%q<rack>, [">= 0"])
85
- s.add_dependency(%q<rack-mount>, [">= 0"])
101
+ s.add_dependency(%q<rack-mount>, ["~> 0.6.13"])
86
102
  s.add_dependency(%q<rack-jsonp>, [">= 0"])
87
- s.add_dependency(%q<activesupport>, ["~> 3.0.0"])
103
+ s.add_dependency(%q<json>, [">= 0"])
104
+ s.add_dependency(%q<multi_json>, [">= 0"])
105
+ s.add_dependency(%q<multi_xml>, [">= 0"])
88
106
  s.add_dependency(%q<rake>, [">= 0"])
89
107
  s.add_dependency(%q<jeweler>, [">= 0"])
90
108
  end
data/lib/grape.rb CHANGED
@@ -1,10 +1,22 @@
1
1
  require 'rack'
2
2
  require 'rack/builder'
3
3
 
4
- require 'grape/middleware/base'
5
- require 'grape/middleware/prefixer'
6
- require 'grape/middleware/versioner'
7
- require 'grape/middleware/formatter'
8
- require 'grape/middleware/error'
9
-
10
- require 'grape/middleware/auth/oauth2'
4
+ module Grape
5
+ autoload :API, 'grape/api'
6
+ autoload :Endpoint, 'grape/endpoint'
7
+ autoload :MiddlewareStack, 'grape/middleware_stack'
8
+ autoload :Client, 'grape/client'
9
+
10
+ module Middleware
11
+ autoload :Base, 'grape/middleware/base'
12
+ autoload :Prefixer, 'grape/middleware/prefixer'
13
+ autoload :Versioner, 'grape/middleware/versioner'
14
+ autoload :Formatter, 'grape/middleware/formatter'
15
+ autoload :Error, 'grape/middleware/error'
16
+
17
+ module Auth
18
+ autoload :OAuth2, 'grape/middleware/auth/oauth2'
19
+ autoload :Basic, 'grape/middleware/auth/basic'
20
+ end
21
+ end
22
+ end
data/lib/grape/api.rb ADDED
@@ -0,0 +1,174 @@
1
+ require 'rack/mount'
2
+ require 'rack/auth/basic'
3
+
4
+ module Grape
5
+ class API
6
+ module Helpers; end
7
+
8
+ class << self
9
+ attr_reader :route_set
10
+
11
+ def reset!
12
+ @settings = [{}]
13
+ @route_set = Rack::Mount::RouteSet.new
14
+ @prototype = nil
15
+ end
16
+
17
+ def call(env)
18
+ puts "#{env['REQUEST_METHOD']} #{env['PATH_INFO']}"
19
+ route_set.freeze.call(env)
20
+ end
21
+
22
+ # Settings are a stack, so when we
23
+ # want to access them they are merged
24
+ # in the order pushed.
25
+ def settings
26
+ @settings.inject({}){|f,h| f.merge!(h); f}
27
+ end
28
+
29
+ def settings_stack
30
+ @settings
31
+ end
32
+
33
+ def set(key, value)
34
+ @settings.last[key.to_sym] = value
35
+ end
36
+
37
+ # Define a root prefix for your entire
38
+ # API. For instance, if you had an api
39
+ # that you wanted to be namespaced at
40
+ # `/api/` you would do this:
41
+ #
42
+ # prefix '/api'
43
+ def prefix(prefix = nil)
44
+ prefix ? set(:root_prefix, prefix) : settings[:root_prefix]
45
+ end
46
+
47
+ def version(*new_versions, &block)
48
+ new_versions.any? ? nest(block){ set(:version, new_versions) } : settings[:version]
49
+ end
50
+
51
+ def default_format(new_format = nil)
52
+ new_format ? set(:default_format, new_format.to_sym) : settings[:default_format]
53
+ end
54
+
55
+ # Add helper methods that will be accessible from any
56
+ # endpoint within this namespace (and child namespaces).
57
+ #
58
+ # class ExampleAPI
59
+ # helpers do
60
+ # def current_user
61
+ # User.find_by_id(params[:token])
62
+ # end
63
+ # end
64
+ # end
65
+ def helpers(&block)
66
+ if block_given?
67
+ m = settings_stack.last[:helpers] || Module.new
68
+ m.class_eval &block
69
+ set(:helpers, m)
70
+ else
71
+ m = Module.new
72
+ settings_stack.each do |s|
73
+ m.send :include, s[:helpers] if s[:helpers]
74
+ end
75
+ m
76
+ end
77
+ end
78
+
79
+ def auth(type = nil, options = {}, &block)
80
+ if type
81
+ set(:auth, {:type => type.to_sym, :proc => block}.merge(options))
82
+ else
83
+ settings[:auth]
84
+ end
85
+ end
86
+
87
+ # Add HTTP Basic authorization to the API.
88
+ #
89
+ # @param [Hash] options A hash of options.
90
+ # @option options [String] :realm "API Authorization" The HTTP Basic realm.
91
+ def http_basic(options = {}, &block)
92
+ options[:realm] ||= "API Authorization"
93
+ auth :http_basic, options, &block
94
+ end
95
+
96
+ def route_set
97
+ @route_set ||= Rack::Mount::RouteSet.new
98
+ end
99
+
100
+ def compile_path(path)
101
+ parts = []
102
+ parts << prefix if prefix
103
+ parts << ':version' if version
104
+ parts << namespace if namespace
105
+ parts << path
106
+ Rack::Mount::Utils.normalize_path(parts.join('/'))
107
+ end
108
+
109
+ def route(method, path_info, &block)
110
+ route_set.add_route(build_endpoint(&block),
111
+ :path_info => Rack::Mount::Strexp.compile(compile_path(path_info)),
112
+ :request_method => method
113
+ )
114
+ end
115
+
116
+ def build_endpoint(&block)
117
+
118
+ b = Rack::Builder.new
119
+ b.use Grape::Middleware::Error
120
+ b.use Rack::Auth::Basic, settings[:auth][:realm], &settings[:auth][:proc] if settings[:auth] && settings[:auth][:type] == :http_basic
121
+ b.use Grape::Middleware::Prefixer, :prefix => prefix if prefix
122
+ b.use Grape::Middleware::Versioner, :versions => (version if version.is_a?(Array)) if version
123
+ b.use Grape::Middleware::Formatter, :default_format => default_format || :json
124
+
125
+ endpoint = Grape::Endpoint.new(&block)
126
+ endpoint.send :extend, helpers
127
+ b.run endpoint
128
+
129
+ b.to_app
130
+ end
131
+
132
+ def get(path_info = '', &block); route('GET', path_info, &block) end
133
+ def post(path_info = '', &block); route('POST', path_info, &block) end
134
+ def put(path_info = '', &block); route('PUT', path_info, &block) end
135
+ def head(path_info = '', &block); route('HEAD', path_info, &block) end
136
+ def delete(path_info = '', &block); route('DELETE', path_info, &block) end
137
+
138
+ def namespace(space = nil, &block)
139
+ if space || block_given?
140
+ nest(block) do
141
+ set(:namespace, space.to_s) if space
142
+ end
143
+ else
144
+ Rack::Mount::Utils.normalize_path(settings_stack.map{|s| s[:namespace]}.join('/'))
145
+ end
146
+ end
147
+
148
+ # Execute first the provided block, then each of the
149
+ # block passed in. Allows for simple 'before' setups
150
+ # of settings stack pushes.
151
+ def nest(*blocks, &block)
152
+ blocks.reject!{|b| b.nil?}
153
+ if blocks.any?
154
+ settings_stack << {}
155
+ instance_eval &block
156
+ blocks.each{|b| instance_eval &b}
157
+ settings_stack.pop
158
+ else
159
+ instance_eval &block
160
+ end
161
+ end
162
+
163
+ alias_method :group, :namespace
164
+ alias_method :resource, :namespace
165
+ alias_method :resources, :namespace
166
+
167
+ def inherited(subclass)
168
+ subclass.reset!
169
+ end
170
+ end
171
+
172
+ reset!
173
+ end
174
+ end
@@ -0,0 +1,65 @@
1
+ require 'rack'
2
+ require 'grape'
3
+
4
+ module Grape
5
+ # An Endpoint is the proxy scope in which all routing
6
+ # blocks are executed. In other words, any methods
7
+ # on the instance level of this class may be called
8
+ # from inside a `get`, `post`, etc. block.
9
+ class Endpoint
10
+ def initialize(&block)
11
+ @block = block
12
+ end
13
+
14
+ attr_reader :env, :request
15
+
16
+ def params
17
+ @params ||= request.params.merge(env['rack.routing_args'] || {}).inject({}) do |h,(k,v)|
18
+ h[k.to_s] = v
19
+ h[k.to_sym] = v
20
+ h
21
+ end
22
+ end
23
+
24
+ def version; env['api.version'] end
25
+
26
+ def error!(message, status=403)
27
+ throw :error, :message => message, :status => status
28
+ end
29
+
30
+ # Set or retrieve the HTTP status code.
31
+ def status(status = nil)
32
+ if status
33
+ @status = status
34
+ else
35
+ return @status if @status
36
+ case request.request_method.to_s.upcase
37
+ when 'POST'
38
+ 201
39
+ else
40
+ 200
41
+ end
42
+ end
43
+ end
44
+
45
+ # Set an individual header or retrieve
46
+ # all headers that have been set.
47
+ def header(key = nil, val = nil)
48
+ if key
49
+ val ? @header[key.to_s] = val : @header.delete(key.to_s)
50
+ else
51
+ @header
52
+ end
53
+ end
54
+
55
+ def call(env)
56
+ @env = env
57
+ @request = Rack::Request.new(@env)
58
+ @header = {}
59
+
60
+ response_text = instance_eval &@block
61
+
62
+ [status, header, [response_text]]
63
+ end
64
+ end
65
+ end