raisin 0.0.1 → 0.0.2
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.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:
|