raisin 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +131 -1
- data/lib/raisin/api.rb +4 -8
- data/lib/raisin/version.rb +1 -1
- metadata +2 -2
data/README.md
CHANGED
@@ -18,7 +18,137 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
-
|
21
|
+
Raisin is composed of two main elements : a router and a lists of API. An API is a file containing your endpoints,
|
22
|
+
with their paths, implementation and documentation. The router is where you modelize your API, saying which
|
23
|
+
API goes to which version.
|
24
|
+
|
25
|
+
Under the hood, raisin will generate classes (one for each enpoint), enabling us to use unit test for them, but keeping it transparent for Rails router.
|
26
|
+
|
27
|
+
Here's a basic example of an API
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
class UsersAPI < Raisin::API
|
31
|
+
get '/users' do
|
32
|
+
expose(:user) { User.all }
|
33
|
+
end
|
34
|
+
|
35
|
+
post do
|
36
|
+
expose(:user) { User.new(params[:user]) }
|
37
|
+
|
38
|
+
response do
|
39
|
+
user.save
|
40
|
+
respond_with(user)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
### Endpoints
|
47
|
+
|
48
|
+
Each endoint is defined by the http verb used to access it, its path and its implementation. When the path is omitted, raisin will default it to '/'. And since we are in the UsersAPI, raisin will set a prefix to 'users'. So the `post do` is equivalent to `post '/users' do`.
|
49
|
+
Same for the get method, since its path is the same as the prefix, it can be omitted.
|
50
|
+
|
51
|
+
The `expose` method allows you to create variables elegantly and to access it in your endpoints body or your views (in you gems like jbuilder or rabl-rails). These exposed variables are evaluated in the response block so you have access to everything (like the params object).
|
52
|
+
|
53
|
+
The response block is where your endpoint logic goes. It can be optionnal, as you can see in the get method. If no response is specified, raisin will behave like a a standart rails controller method (thus trying to render a file with tht same name as the endpoint or fallback to API rendering)
|
54
|
+
|
55
|
+
We talk about the name of the endpoint but how is it determine? raisin is smart enough to recognize basic CRUD operations and RESTful endpoint
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
class UsersAPI < Raisin::API
|
59
|
+
get '/users' {} # index
|
60
|
+
post '/users' {} # create
|
61
|
+
|
62
|
+
put '/users/:id/foo' # foo
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
You can see theses names if you run `rake routes` in your console. If you prefer to name your endpoint yourself, you can do it by passing an `:as` option
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
get '/users', as: :my_method_name
|
70
|
+
```
|
71
|
+
|
72
|
+
### Namespaces
|
73
|
+
|
74
|
+
You often have endpoint that have a portion of their path in commons, a namespace in raisin. The most used is RESTful applications is the "member" namespace, that look like `/resource_name/:id`.
|
75
|
+
|
76
|
+
raisin provides both generic namespace and member out of the box
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
class UsersAPI < Raisin::API
|
80
|
+
namespace 'foo' do
|
81
|
+
get '/bar' {} # GET /foo/bar
|
82
|
+
end
|
83
|
+
|
84
|
+
member do
|
85
|
+
put do # PUT /users/:id
|
86
|
+
response do
|
87
|
+
user.update_attributes(params[:user])
|
88
|
+
respond_with(user)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
```
|
94
|
+
|
95
|
+
You see that in the `update` method we used a user variable. This is because you can also expose variable for a whole namespace, which does member automatically (the variable name will be the resource name singularize, 'user' in our example)
|
96
|
+
|
97
|
+
Namespaces can be nested.
|
98
|
+
|
99
|
+
### Miscellanous
|
100
|
+
|
101
|
+
You can add `single_resource` in your API for single resources.
|
102
|
+
|
103
|
+
Resources can be nested just as regular Rails. For example
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
class CommentsAPI < Raisin::API
|
107
|
+
nested_into_resource :posts
|
108
|
+
|
109
|
+
get '/comments/:id' do # GET /posts/:post_id/comments/:id
|
110
|
+
expose(:comment) { post.comments.find(params[:id]) }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
```
|
114
|
+
|
115
|
+
### Router
|
116
|
+
|
117
|
+
raisin router is similar to the `routes.rb` in Rails. APIs that appears at the top have precedence on the ones after. Versionning is done by encapsulating APIs inside `version` block. `:all` can be used is a part of your api is accessible for all versions.
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
# /app/api/my_api.rb
|
121
|
+
class MyApi < Raisin::Router
|
122
|
+
version :v2, using: :header, vendor: 'mycompany' do
|
123
|
+
mount CommentsApi
|
124
|
+
end
|
125
|
+
|
126
|
+
version [:v2, :v1] do
|
127
|
+
mount PostsApi
|
128
|
+
mount UsersApi
|
129
|
+
end
|
130
|
+
|
131
|
+
version :all do
|
132
|
+
mount LoginApi
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# /config/routes.rb
|
137
|
+
|
138
|
+
mount_api MyApi
|
139
|
+
```
|
140
|
+
|
141
|
+
Versionning can be done via the HTTP Accept header (application/vnd.mycompany-v1+json for example) or via the URL
|
142
|
+
(/v1/users/). When using the header versionning, the vendor must be set. These options can be set globally when configuring raisin.
|
143
|
+
|
144
|
+
## Configuration
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
Raisin.configure do |c|
|
148
|
+
c.version.using = :header
|
149
|
+
c.version.vendor = 'mycompany'
|
150
|
+
end
|
151
|
+
```
|
22
152
|
|
23
153
|
## Contributing
|
24
154
|
|
data/lib/raisin/api.rb
CHANGED
@@ -5,18 +5,14 @@ module Raisin
|
|
5
5
|
@args = args
|
6
6
|
end
|
7
7
|
end
|
8
|
-
|
9
|
-
def build(action, app=nil, &block)
|
10
|
-
super(app, &block)
|
11
|
-
end
|
12
8
|
end
|
13
9
|
|
14
10
|
class API
|
15
|
-
|
16
|
-
|
11
|
+
cattr_accessor :middleware_stack
|
12
|
+
@@middleware_stack = Raisin::MiddlewareStack.new
|
17
13
|
|
18
14
|
def self.action(name, klass = ActionDispatch::Request)
|
19
|
-
middleware_stack.build
|
15
|
+
middleware_stack.build do |env|
|
20
16
|
self.const_get(name.camelize).new.dispatch(:call, klass.new(env))
|
21
17
|
end
|
22
18
|
end
|
@@ -51,10 +47,10 @@ module Raisin
|
|
51
47
|
end
|
52
48
|
|
53
49
|
def self.inherited(subclass)
|
50
|
+
super
|
54
51
|
subclass.reset
|
55
52
|
subclass.middleware_stack = self.middleware_stack.dup
|
56
53
|
subclass.action_klass = self.action_klass.dup
|
57
|
-
super
|
58
54
|
end
|
59
55
|
|
60
56
|
def self.api_name
|
data/lib/raisin/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: raisin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-12-04 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: An opiniated micro-framework to easily build elegant API on top of Rails
|
15
15
|
email:
|