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 CHANGED
@@ -18,7 +18,137 @@ Or install it yourself as:
18
18
 
19
19
  ## Usage
20
20
 
21
- Soon
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
- class_attribute :middleware_stack
16
- self.middleware_stack = Raisin::MiddlewareStack.new
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(name) do |env|
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
@@ -1,3 +1,3 @@
1
1
  module Raisin
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
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.1
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-11-13 00:00:00.000000000 Z
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: