rack-backend-api 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -164,6 +164,52 @@ nice interface using Ajax and getting the best of what the API has to offer.
164
164
  The forms are really meant to be requested via an XHR,
165
165
  so that you have access to style and javascript widgets like a date-picker for example.
166
166
 
167
+ Nevertheless you might want to have a better unobtrusiveness for your javascript, meaning
168
+ you want to be able to wrap the forms yourself with your nice layout.
169
+ That is also valuable if you want to have no javascript at all.
170
+
171
+ This is exactly what the option `_no_wrap` is for. Basically if you want that,
172
+ it is better to have your Backend middleware before the API in the Rack stack:
173
+
174
+ map '/' do
175
+ run Frontend
176
+ end
177
+
178
+ map '/admin' do
179
+ use Rack::Auth::Basic, "your-realm" do |username, password|
180
+ [username, password] == ['username', 'password']
181
+ end
182
+ use Backend
183
+ run BackendAPI
184
+ end
185
+
186
+ Then what you do is that you make your Backend middleware aware that if the GET param
187
+ `_no_wrap` is used, it has to forward the request and then wrap the body:
188
+
189
+ class Backend
190
+ def initialize(app); @app = app; end
191
+ def call(env)
192
+ if Rack::Request.new(env)['_no_wrap']
193
+ status, header, body = @app.call(env)
194
+ res = Rack::Response.new('<!-- ', status, header)
195
+ if body.respond_to? :to_str
196
+ res.write body.to_str
197
+ elsif body.respond_to?(:each)
198
+ body.each { |part|
199
+ res.write part.to_s
200
+ }
201
+ end
202
+ res.write(' -->')
203
+ res.finish
204
+ else
205
+ [200, {'Content-Type'=>'text/plain'}, ['not wrapped']]
206
+ end
207
+ end
208
+ end
209
+
210
+ Here, if the param `_no_wrap` is used, this middleware will ask the response to the API middleware
211
+ and then will create a new Response with the body wrapped between `<!-- ` and ` -->`.
212
+
167
213
  HOW TO PLUG AN ORM
168
214
  ==================
169
215
 
@@ -204,6 +250,7 @@ CHANGE LOG
204
250
  0.0.1 First version
205
251
  0.0.2 Accept CamelCased class names
206
252
  0.0.3 Fix Form mockup
253
+ 0.0.4 Partial available not only via XHR but also via `_no_wrap` param
207
254
 
208
255
  COPYRIGHT
209
256
  =========
data/lib/backend_api.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  class BackendAPI
2
- VERSION = [0,0,3]
2
+ VERSION = [0,0,4]
3
3
  WRAP = <<-EOT
4
4
  <!doctype html>
5
5
  <html>
@@ -51,7 +51,7 @@ class BackendAPI
51
51
  def get
52
52
  @model_instance ||= @model_class.backend_post
53
53
  @model_instance.backend_put @req['model']
54
- form = @model_instance.backend_form(@req.path, @req['fields'], :destination => @req['_destination'], :submit_text => @req['_submit_text'] )
54
+ form = @model_instance.backend_form(@req.path, @req['fields'], :destination => @req['_destination'], :submit_text => @req['_submit_text'], :no_wrap => @req['_no_wrap'])
55
55
  @res.write(wrap_form(form))
56
56
  end
57
57
 
@@ -102,14 +102,14 @@ class BackendAPI
102
102
  @res.redirect(::Rack::Utils::unescape(@req['_destination']))
103
103
  end
104
104
  else
105
- form = @model_instance.backend_form(@req.path, @req['model'].keys, :destination => @req['_destination'], :submit_text => @req['_submit_text'])
105
+ form = @model_instance.backend_form(@req.path, @req['model'].keys, :destination => @req['_destination'], :submit_text => @req['_submit_text'], :no_wrap => @req['_no_wrap'])
106
106
  @res.write(wrap_form(form))
107
107
  @res.status=400 # Bad Request
108
108
  end
109
109
  end
110
110
 
111
111
  def wrap_form(form)
112
- if @req.xhr?
112
+ if @req['_no_wrap'] || @req.xhr?
113
113
  form
114
114
  else
115
115
  WRAP % [@model_class_name, form]
@@ -27,6 +27,7 @@ module ::Sequel::Plugins::RackBackendApiAdapter
27
27
  o << "<input type='hidden' name='_method' value='#{opts[:method] || method}' />\n"
28
28
  o << "<input type='hidden' name='_destination' value='#{opts[:destination]}' />\n" unless opts[:destination].nil?
29
29
  o << "<input type='hidden' name='_submit_text' value='#{opts[:submit_text]}' />\n" unless opts[:submit_text].nil?
30
+ o << "<input type='hidden' name='_no_wrap' value='#{opts[:no_wrap]}' />\n" unless opts[:no_wrap].nil?
30
31
  o << "<input type='submit' name='save' value='#{opts[:submit_text] || 'SAVE'}' />\n"
31
32
  o << "</form>\n"
32
33
  o
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'rack-backend-api'
3
- s.version = "0.0.3"
3
+ s.version = "0.0.4"
4
4
  s.platform = Gem::Platform::RUBY
5
5
  s.summary = "A Rack middleware that provides a simple API for your Admin section"
6
6
  s.description = "The purpose of this Rack Middleware is to provide an API that interfaces with database actions in order to build a CMS."
@@ -22,6 +22,27 @@ def wrap(title, form) #mock wrapped versions of forms when not XHR
22
22
  BackendAPI::WRAP % [title,form]
23
23
  end
24
24
 
25
+ class WrappingMiddleware
26
+ def initialize(app); @app = app; end
27
+ def call(env)
28
+ if Rack::Request.new(env)['_no_wrap']
29
+ status, header, body = @app.call(env)
30
+ res = Rack::Response.new('<!-- ', status, header)
31
+ if body.respond_to? :to_str
32
+ res.write body.to_str
33
+ elsif body.respond_to?(:each)
34
+ body.each { |part|
35
+ res.write part.to_s
36
+ }
37
+ end
38
+ res.write(' -->')
39
+ res.finish
40
+ else
41
+ [200, {'Content-Type'=>'text/plain'}, ['not wrapped']]
42
+ end
43
+ end
44
+ end
45
+
25
46
  describe 'API Misc' do
26
47
  should "Send 404 X-cascade if no response at the bottom of the Rack stack - Builder::run" do
27
48
  res = req_lint(BackendAPI.new).get('/zzz')
@@ -85,9 +106,16 @@ describe 'API Post' do
85
106
  res.headers['Location']=='http://www.domain.com/list.xml'
86
107
  Haiku.order(:id).last.title.should=='Destination Summer'
87
108
  end
88
- should "keep destination until form is validated" do
109
+ should "Keep _destination until form is validated" do
89
110
  req_lint(BackendAPI.new).post('/haiku', :params => {'_destination' => '/', 'model' => {'title' => '13'}}).body.should.match(/name='_destination'.*value='\/'/)
90
111
  end
112
+ should "Keep _no_wrap until form is validated" do
113
+ compared = Haiku.new.set('title' => '13')
114
+ compared.valid?
115
+ res = req_lint(WrappingMiddleware.new(BackendAPI.new)).post('/haiku', :params => {'_no_wrap' => 'true', 'model' => {'title' => '13'}})
116
+ res.body.should==('<!-- '+compared.backend_form('/haiku',['title'], {:no_wrap=>'true'})+' -->')
117
+ res.body.should.match(/name='_no_wrap'.*value='true'/)
118
+ end
91
119
  end
92
120
 
93
121
  describe 'API Get' do
@@ -106,8 +134,10 @@ describe 'API Get' do
106
134
  req_lint(BackendAPI.new).get('/haiku', :params => {'model' => update}).body.should==wrap('Haiku', Haiku.new.set(update).backend_form('/haiku'))
107
135
  req_lint(BackendAPI.new).get('/haiku/3', :params => {'model' => update}).body.should==wrap('Haiku', Haiku[3].set(update).backend_form('/haiku/3'))
108
136
  end
109
- should "Return a partial if the request is XHR" do
137
+ should "Return a partial if the request is XHR or param _no_wrap is used" do
110
138
  req_lint(BackendAPI.new).get('/haiku', "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest").body.should==Haiku.new.backend_form('/haiku')
139
+ req_lint(BackendAPI.new).get('/haiku?_no_wrap=true').body.should==Haiku.new.backend_form('/haiku', nil, {:no_wrap=>'true'})
140
+ req_lint(WrappingMiddleware.new(BackendAPI.new)).get('/haiku?_no_wrap=true').body.should==('<!-- '+Haiku.new.backend_form('/haiku', nil, {:no_wrap=>'true'})+' -->')
111
141
  end
112
142
  end
113
143
 
@@ -149,6 +179,13 @@ describe 'API Put' do
149
179
  should "keep destination until form is validated" do
150
180
  req_lint(BackendAPI.new).put('/haiku/3', :params => {'_destination' => '/', 'model' => {'title' => '13'}}).body.should.match(/name='_destination'.*value='\/'/)
151
181
  end
182
+ should "Keep _no_wrap until form is validated" do
183
+ compared = Haiku[3].set('title' => '13')
184
+ compared.valid?
185
+ res = req_lint(WrappingMiddleware.new(BackendAPI.new)).post('/haiku/3', :params => {'_no_wrap' => 'true', 'model' => {'title' => '13'}})
186
+ res.body.should==('<!-- '+compared.backend_form('/haiku/3',['title'], {:no_wrap=>'true'})+' -->')
187
+ res.body.should.match(/name='_no_wrap'.*value='true'/)
188
+ end
152
189
  end
153
190
 
154
191
  describe 'API Delete' do
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-backend-api
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 3
10
- version: 0.0.3
9
+ - 4
10
+ version: 0.0.4
11
11
  platform: ruby
12
12
  authors:
13
13
  - Mickael Riga
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-07-19 00:00:00 +01:00
18
+ date: 2011-07-21 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies: []
21
21