rufus-sixjo 0.1.0

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.txt ADDED
@@ -0,0 +1,87 @@
1
+
2
+ = 'rufus-sixjo'
3
+
4
+ == what is it ?
5
+
6
+ A 'Rack application' for
7
+
8
+
9
+ == features
10
+
11
+ not many.
12
+
13
+
14
+ == getting it
15
+
16
+ sudo gem install -y rufus-sixjo
17
+
18
+ or download[http://rubyforge.org/frs/?group_id=4812] it from RubyForge.
19
+
20
+
21
+ == usage
22
+
23
+ see under the examples/ directory : http://github.com/jmettraux/rufus-sixjo/tree/master/examples
24
+
25
+ It goes like :
26
+
27
+ require 'rubygems'
28
+ require 'rufus/sixjo' # gem 'rufus-sixjo'
29
+
30
+ module ExampleOne
31
+
32
+ extend Rufus::Sixjo
33
+
34
+ get '/toto' do
35
+ "nada at #{request.path_info}"
36
+ end
37
+ end
38
+
39
+ app = Rack::Builder.new do
40
+
41
+ use Rack::CommonLogger
42
+ use Rack::ShowExceptions
43
+ run ExampleOne.new_sixjo_rack_app(nil)
44
+ end
45
+
46
+ Rack::Handler::Mongrel.run app, :Port => 2042
47
+
48
+
49
+ == dependencies
50
+
51
+ the 'rack' gem
52
+
53
+
54
+ == mailing list
55
+
56
+ On the Rufus-Ruby list[http://groups.google.com/group/rufus-ruby] :
57
+
58
+ http://groups.google.com/group/rufus-ruby
59
+
60
+
61
+ == issue tracker
62
+
63
+ http://rubyforge.org/tracker/?atid=18584&group_id=4812&func=browse
64
+
65
+
66
+ == source
67
+
68
+ http://github.com/jmettraux/rufus-sixjo
69
+
70
+ git clone git://github.com/jmettraux/rufus-sixjo.git
71
+
72
+
73
+ == author
74
+
75
+ John Mettraux, jmettraux@gmail.com,
76
+ http://jmettraux.wordpress.com
77
+
78
+
79
+ == the rest of Rufus
80
+
81
+ http://rufus.rubyforge.org
82
+
83
+
84
+ == license
85
+
86
+ MIT
87
+
@@ -0,0 +1,353 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2008, John Mettraux, jmettraux@gmail.com
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+ #++
23
+ #
24
+
25
+ #
26
+ # "made in Japan"
27
+ #
28
+
29
+ require 'erb'
30
+ require 'rack'
31
+
32
+
33
+ class Rack::Request
34
+
35
+ def content
36
+ @env['rack.request.form_vars']
37
+ end
38
+ end
39
+
40
+ class Rack::Response
41
+
42
+ def location= (l)
43
+ header['Location'] = l
44
+ end
45
+ def content_type= (t)
46
+ header['Content-type'] = t
47
+ end
48
+ end
49
+
50
+
51
+ module Rufus
52
+
53
+ module Sixjo
54
+
55
+ VERSION = "0.1.0"
56
+
57
+ #
58
+ # Sixjo's Rack app
59
+ #
60
+ class App
61
+
62
+ attr_reader :environment
63
+
64
+ def initialize (next_app, routes, helpers, configures, options)
65
+
66
+ @next_app = next_app
67
+ @routes = routes || [] # the 'no route' case is rather useless...
68
+ @helpers = helpers || []
69
+
70
+ #@prefix = options[:prefix] || ''
71
+ #@rprefix = Regexp.new(@prefix)
72
+
73
+ @environment = options[:environment] || 'development'
74
+ @environment = @environment.to_s
75
+
76
+ #
77
+ # run the configure blocks
78
+
79
+ (configures || []).each do |envs, block|
80
+ instance_eval(&block) if envs.empty? or envs.include?(@environment)
81
+ end
82
+ end
83
+
84
+ def application
85
+ self
86
+ end
87
+
88
+ def call (env)
89
+
90
+ block = nil
91
+
92
+ begin
93
+ block = lookup_block(env)
94
+ rescue => e
95
+ #puts e
96
+ #puts e.backtrace
97
+ return [ 400, {}, e.to_s ]
98
+ end
99
+
100
+ if block
101
+ Context.service(self, block, @helpers, env)
102
+ elsif @next_app
103
+ @next_app.call(env)
104
+ else
105
+ [ 404, {}, [ "not found #{env['PATH_INFO']}" ] ]
106
+ end
107
+ end
108
+
109
+ protected
110
+
111
+ H_METHODS = [ 'GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS' ]
112
+ R_METHOD = /_method=(put|delete|PUT|DELETE)/
113
+ R_MULTIPART = /^multipart\/form-data;/
114
+
115
+ def lookup_block (env)
116
+
117
+ request_method = get_request_method(env)
118
+
119
+ @routes.each do |verb, route, block|
120
+ next unless request_method == verb
121
+ next unless route.match?(env)
122
+ return block
123
+ end
124
+
125
+ nil
126
+ end
127
+
128
+ def get_request_method (env)
129
+
130
+ rm = env['X-HTTP-Method-Override'] || env['REQUEST_METHOD']
131
+ rm = rm.upcase
132
+
133
+ #puts env.inspect
134
+
135
+ if rm == 'POST'
136
+ md = R_METHOD.match(env['QUERY_STRING'])
137
+ rm = md[1].upcase if md
138
+
139
+ ct = env['CONTENT_TYPE']
140
+
141
+ if ct and R_MULTIPART.match(ct)
142
+ request = Rack::Request.new(env)
143
+ env['_rack_request'] = request # no need to rebuild later
144
+ hidden_method = request.POST['_method']
145
+ rm = hidden_method.upcase if hidden_method
146
+ end
147
+ end
148
+
149
+ raise "unknown HTTP method '#{rm}'" unless H_METHODS.include?(rm)
150
+
151
+ rm
152
+ end
153
+ end
154
+
155
+ #
156
+ # ERB views
157
+ #
158
+ module Erb
159
+
160
+ #
161
+ # a local [context] for ERB views
162
+ #
163
+ class Local
164
+
165
+ def initialize (context, locals)
166
+ @context = context
167
+ @locals = locals
168
+ end
169
+
170
+ def method_missing (m, *args)
171
+
172
+ l = @locals[m.to_sym]
173
+ return l if l != nil
174
+
175
+ @context.send(m, *args)
176
+ end
177
+
178
+ #def application; @context.application; end
179
+ #def request; @context.request; end
180
+ #def response; @context.response; end
181
+
182
+ def get_binding
183
+ binding
184
+ end
185
+ end
186
+
187
+ def erb (template, options = {})
188
+
189
+ content = File.open("views/#{template}.erb").read
190
+
191
+ l = options[:locals]
192
+ l = Local.new(self, l || {}) unless l.is_a?(Local)
193
+
194
+ ::ERB.new(content).result(l.get_binding)
195
+ end
196
+ end
197
+
198
+ #
199
+ # The context in which an HTTP request is handled
200
+ #
201
+ class Context
202
+
203
+ include Erb
204
+
205
+ def metaclass
206
+ class << self
207
+ self
208
+ end
209
+ end
210
+
211
+ attr_reader :application
212
+ attr_reader :request, :response
213
+
214
+ def initialize (app, env)
215
+
216
+ @application = app
217
+ @request = env.delete('_rack_request') || Rack::Request.new(env)
218
+ @response = Rack::Response.new
219
+
220
+ @params = @request.params.merge(@request.env['_ROUTE_PARAMS'])
221
+ @params = @params.inject({}) { |r, (k, v)| r[k.to_sym] = v; r }
222
+ end
223
+
224
+ def self.service (app, block, helpers, env)
225
+
226
+ r = self.new(app, env)
227
+
228
+ helpers.each { |h| r.instance_eval &h }
229
+
230
+ r.metaclass.instance_eval { define_method :call, &block }
231
+
232
+ begin
233
+
234
+ caught = catch :done do
235
+ r.response.body = r.call || []
236
+ nil
237
+ end
238
+
239
+ if caught
240
+ #puts caught.inspect
241
+ r.response.status = caught[0]
242
+ r.response.body = caught[1]
243
+ end
244
+
245
+ rescue Exception => e
246
+
247
+ r.response.status = 500
248
+ r.response.content_type = 'text/plain'
249
+ r.response.body = e.to_s + "\n" + e.backtrace.join("\n")
250
+ end
251
+
252
+ r.response.finish
253
+ end
254
+
255
+ def params
256
+ @params
257
+ end
258
+
259
+ def redirect (path, status=303, body=nil)
260
+ @response.status = status
261
+ @response.location = path
262
+ @response.body = body || "#{status} redirecting to #{path}"
263
+ throw :done
264
+ end
265
+ end
266
+
267
+ #
268
+ # Wrapping all the details about route.match?(path) here...
269
+ #
270
+ class Route
271
+
272
+ C_CHAR = '[^/?:,&#\.]'
273
+ R_PARAM = /:(#{C_CHAR}+)/ # capturing route params
274
+ R_FORMAT = /\.(#{C_CHAR}+)$/ # capturing the resource/file format
275
+
276
+ def initialize (route, options)
277
+
278
+ @param_keys = []
279
+
280
+ @regex = route.gsub(R_PARAM) do
281
+ @param_keys << $1.to_sym
282
+ "(#{C_CHAR}+)" # ready to capture param values
283
+ end
284
+
285
+ @regex = /^#{@regex}(?:\.(#{C_CHAR}+))?$/
286
+
287
+ # TODO : do something with the options :agent, :accept, ...
288
+ end
289
+
290
+ def match? (env)
291
+
292
+ m = env['PATH_INFO'].match(@regex)
293
+
294
+ return false unless m
295
+
296
+ values = m.to_a[1..-1]
297
+ params = @param_keys.zip(values).inject({}) { |r, (k, v)| r[k] = v; r }
298
+
299
+ env['_ROUTE_PARAMS'] = params
300
+
301
+ env['_FORMAT'] = values.last if values.length > @param_keys.length
302
+
303
+ true
304
+ end
305
+ end
306
+
307
+ #--
308
+ # the methods for registering the routes
309
+ #++
310
+ [ :post, :get, :put, :delete ].each do |v|
311
+ module_eval <<-EOS
312
+ def #{v} (rt, opts={}, &blk)
313
+ (@routes ||= []) << [ '#{v.to_s.upcase}', Route.new(rt, opts), blk ]
314
+ end
315
+ EOS
316
+ end
317
+
318
+ #
319
+ # for example :
320
+ #
321
+ # helpers do
322
+ # def hello
323
+ # "hello #{params['who']}"
324
+ # end
325
+ # end
326
+ #
327
+ def helpers (&block)
328
+
329
+ (@helpers ||= []) << block
330
+ end
331
+
332
+ #
333
+ # Code in the 'configure' block will be run inside the application
334
+ # instance.
335
+ #
336
+ def configure (*envs, &block)
337
+
338
+ (@configures ||= []) << [ envs.collect { |e| e.to_s }, block ]
339
+ end
340
+
341
+ #
342
+ # Packages the routing info into a Rack application, suitable for
343
+ # insertion into a Rack app chain.
344
+ #
345
+ # Returns an instance of Rufus::Sixjo::App
346
+ #
347
+ def new_sixjo_rack_app (next_app, options={})
348
+
349
+ App.new(next_app, @routes, @helpers, @configures, options)
350
+ end
351
+ end
352
+ end
353
+
@@ -0,0 +1,52 @@
1
+
2
+ #
3
+ # Testing rufus-sixjo
4
+ #
5
+ # jmettraux at gmail.org
6
+ #
7
+ # Fri Aug 8 15:14:45 JST 2008
8
+ #
9
+
10
+ require 'test/unit'
11
+ require 'testmixins'
12
+
13
+ #
14
+ # the "test" app
15
+ #
16
+ module Simple
17
+ extend Rufus::Sixjo
18
+
19
+ get '/toto' do
20
+ "toto"
21
+ end
22
+
23
+ get '/toto/:id' do
24
+ "toto with id #{params[:id]} .#{request.env['_FORMAT']}"
25
+ end
26
+ end
27
+
28
+ class SimpleTest < Test::Unit::TestCase
29
+ include SixjoTestMixin
30
+
31
+ def setup
32
+ @app = Simple.new_sixjo_rack_app(nil, :environment => 'test')
33
+ end
34
+
35
+ def test_0
36
+
37
+ assert_equal 404, get('/nada').status
38
+
39
+ assert_equal 200, get('/toto').status
40
+ assert_equal "toto", @response.body
41
+
42
+ assert_equal 200, get('/toto/3').status
43
+ assert_equal "toto with id 3 .", @response.body
44
+
45
+ assert_equal 200, get('/toto/3.json').status
46
+ assert_equal "toto with id 3 .json", @response.body
47
+
48
+ assert_equal 200, get('/toto/3.json?q=nada').status
49
+ assert_equal "toto with id 3 .json", @response.body
50
+ end
51
+ end
52
+
@@ -0,0 +1,46 @@
1
+
2
+ #
3
+ # Testing rufus-sixjo
4
+ #
5
+ # jmettraux at gmail.org
6
+ #
7
+ # Sat Aug 9 00:03:47 JST 2008
8
+ #
9
+
10
+ require 'test/unit'
11
+ require 'testmixins'
12
+
13
+ #
14
+ # the "test" app
15
+ #
16
+ module WithHelper
17
+ extend Rufus::Sixjo
18
+
19
+ get '/hello' do
20
+ "hello #{hello}"
21
+ end
22
+
23
+ helpers do
24
+ def hello
25
+ params[:target]
26
+ end
27
+ end
28
+ end
29
+
30
+ class HelpersTest < Test::Unit::TestCase
31
+ include SixjoTestMixin
32
+
33
+ def setup
34
+ @app = WithHelper.new_sixjo_rack_app(nil, :environment => 'test')
35
+ end
36
+
37
+ def test_0
38
+
39
+ assert_equal 200, get('/hello').status
40
+ assert_equal "hello ", @response.body
41
+
42
+ assert_equal 200, get('/hello?target=world').status
43
+ assert_equal "hello world", @response.body
44
+ end
45
+ end
46
+
@@ -0,0 +1,37 @@
1
+
2
+ #
3
+ # Testing rufus-sixjo
4
+ #
5
+ # jmettraux at gmail.org
6
+ #
7
+ # Mon Aug 11 17:23:23 JST 2008
8
+ #
9
+
10
+ require 'test/unit'
11
+ require 'testmixins'
12
+
13
+ #
14
+ # the "test" app
15
+ #
16
+ module RedirectApp
17
+ extend Rufus::Sixjo
18
+
19
+ get '/' do
20
+ redirect '/elsewhere'
21
+ end
22
+ end
23
+
24
+ class RedirectTest < Test::Unit::TestCase
25
+ include SixjoTestMixin
26
+
27
+ def setup
28
+ @app = RedirectApp.new_sixjo_rack_app(nil, :environment => 'test')
29
+ end
30
+
31
+ def test_0
32
+ assert_equal 303, get('/').status
33
+ assert_equal '/elsewhere', @response.location
34
+ assert_equal "303 redirecting to /elsewhere", @response.body
35
+ end
36
+ end
37
+
data/test/ft_3_erb.rb ADDED
@@ -0,0 +1,71 @@
1
+
2
+ #
3
+ # Testing rufus-sixjo
4
+ #
5
+ # jmettraux at gmail.org
6
+ #
7
+ # Mon Aug 11 19:09:58 JST 2008
8
+ #
9
+
10
+ require 'test/unit'
11
+ require 'fileutils'
12
+ require 'testmixins'
13
+
14
+ #
15
+ # the "test" app
16
+ #
17
+ module ErbApp
18
+ extend Rufus::Sixjo
19
+
20
+ get '/' do
21
+ erb 'view0'
22
+ end
23
+
24
+ get '/good' do
25
+ erb 'view0', :locals => { :life => 'good' }
26
+ end
27
+
28
+ get '/good2' do
29
+ erb :view0, :whatever => true, :locals => { :life => 'good' }
30
+ end
31
+
32
+ get '/reckless' do
33
+ erb :view1
34
+ end
35
+ end
36
+
37
+ class ErbTest < Test::Unit::TestCase
38
+ include SixjoTestMixin
39
+
40
+ def setup
41
+
42
+ @app = ErbApp.new_sixjo_rack_app(nil, :environment => 'test')
43
+
44
+ FileUtils.mkdir('views') unless File.exist?('views')
45
+
46
+ fn = 'views/view0.erb'
47
+
48
+ FileUtils.rm(fn) if File.exist?(fn)
49
+ File.open(fn, 'w') { |f| f.write "this is view0, life is <%= life %>" }
50
+
51
+ fn = 'views/view1.erb'
52
+
53
+ FileUtils.rm(fn) if File.exist?(fn)
54
+ File.open(fn, 'w') { |f| f.write "<%= request.path_info %>" }
55
+ end
56
+
57
+ def test_0
58
+
59
+ assert_equal 500, get('/').status
60
+
61
+ assert_equal 200, get('/good').status
62
+ assert_equal 'this is view0, life is good', @response.body.strip
63
+
64
+ assert_equal 200, get('/good2').status
65
+ assert_equal 'this is view0, life is good', @response.body.strip
66
+
67
+ assert_equal 200, get('/reckless').status
68
+ assert_equal '/reckless', @response.body.strip
69
+ end
70
+ end
71
+
@@ -0,0 +1,61 @@
1
+
2
+ #
3
+ # Testing rufus-sixjo
4
+ #
5
+ # jmettraux at gmail.org
6
+ #
7
+ # Tue Aug 12 13:38:16 JST 2008
8
+ #
9
+
10
+ require 'test/unit'
11
+ require 'testmixins'
12
+
13
+ #
14
+ # the "test" app
15
+ #
16
+ module ConfigureApp
17
+ extend Rufus::Sixjo
18
+
19
+ configure do
20
+ $apple = 'pomme'
21
+ @pear = 'poire'
22
+ end
23
+
24
+ configure :production, :development do
25
+ $peach = 'pe^che'
26
+ end
27
+
28
+ get '/' do
29
+ "apple is #{$apple}"
30
+ end
31
+
32
+ get '/pear' do
33
+ "pear is #{application.instance_variable_get(:@pear)}"
34
+ end
35
+
36
+ get '/peach' do
37
+ "peach is #{$peach}"
38
+ end
39
+ end
40
+
41
+ class ConfigureTest < Test::Unit::TestCase
42
+ include SixjoTestMixin
43
+
44
+ def setup
45
+
46
+ @app = ConfigureApp.new_sixjo_rack_app(nil, :environment => 'test')
47
+ end
48
+
49
+ def test_0
50
+
51
+ assert_equal 200, get('/').status
52
+ assert_equal 'apple is pomme', @response.body.strip
53
+
54
+ assert_equal 200, get('/pear').status
55
+ assert_equal 'pear is poire', @response.body.strip
56
+
57
+ assert_equal 200, get('/peach').status
58
+ assert_equal 'peach is', @response.body.strip
59
+ end
60
+ end
61
+
data/test/ft_5_put.rb ADDED
@@ -0,0 +1,97 @@
1
+
2
+ #
3
+ # Testing rufus-sixjo
4
+ #
5
+ # jmettraux at gmail.org
6
+ #
7
+ # Tue Aug 12 23:36:22 JST 2008
8
+ #
9
+
10
+ require 'test/unit'
11
+ require 'testmixins'
12
+
13
+ #
14
+ # the "test" app
15
+ #
16
+ module PutApp
17
+ extend Rufus::Sixjo
18
+
19
+ post '/' do
20
+ #puts request.inspect
21
+ #request.env['rack.input'].read
22
+ request.content
23
+ end
24
+
25
+ put '/car' do
26
+ "put : #{request.content || params[:brand]}"
27
+ end
28
+
29
+ delete '/car/:id' do
30
+ end
31
+ end
32
+
33
+ class PutTest < Test::Unit::TestCase
34
+ include SixjoTestMixin
35
+
36
+ def setup
37
+
38
+ @app = PutApp.new_sixjo_rack_app(nil, :environment => 'test')
39
+ end
40
+
41
+ def test_0
42
+
43
+ #puts post('/', { :input => 'toto' }).body
44
+ assert_equal 200, post('/', { :input => 'toto' }).status
45
+ assert_equal 'toto', @response.body
46
+
47
+ assert_equal 200, put('/car', { :input => 'datsun' }).status
48
+ assert_equal 'put : datsun', @response.body
49
+
50
+ assert_equal 200, post('/car?_method=put', { :input => 'nissan' }).status
51
+ assert_equal 'put : nissan', @response.body
52
+
53
+ assert_equal 404, post('/car', { :input => 'mercedes', :_method => 'put' }).status
54
+ #assert_equal 'put : mercedes', @response.body
55
+
56
+ assert_equal 200, delete('/car/fr154147', {}).status
57
+ assert_equal '', @response.body
58
+ end
59
+
60
+ def test_1
61
+
62
+ assert_equal(
63
+ 200,
64
+ post(
65
+ '/car',
66
+ { :input => 'lada', 'X-HTTP-Method-Override' => 'put' }).status)
67
+ assert_equal 'put : lada', @response.body
68
+
69
+ assert_equal(
70
+ 400,
71
+ post(
72
+ '/car',
73
+ { :input => 'lada', 'X-HTTP-Method-Override' => 'push' }).status)
74
+ assert_equal "unknown HTTP method 'PUSH'", @response.body
75
+ end
76
+
77
+ def test_2
78
+
79
+ data = {
80
+ "_method" => "put",
81
+ "brand" => "ford"
82
+ }
83
+ form_data = encode_multipart(data)
84
+
85
+ assert_equal(
86
+ 200,
87
+ post(
88
+ '/car',
89
+ {
90
+ :input => form_data,
91
+ 'CONTENT_LENGTH' => form_data.length.to_s,
92
+ 'CONTENT_TYPE' => 'multipart/form-data; boundary=AaB03x'
93
+ }).status)
94
+ assert_equal 'put : ford', @response.body
95
+ end
96
+ end
97
+
data/test/test.rb ADDED
@@ -0,0 +1,8 @@
1
+
2
+ require 'ft_0_simple'
3
+ require 'ft_1_helpers'
4
+ require 'ft_2_redirect'
5
+ require 'ft_3_erb'
6
+ require 'ft_4_configure'
7
+ require 'ft_5_put'
8
+
@@ -0,0 +1,40 @@
1
+
2
+ #
3
+ # Testing rufus-sixjo
4
+ #
5
+ # jmettraux at gmail.org
6
+ #
7
+ # Fri Aug 8 18:01:29 JST 2008
8
+ #
9
+
10
+ require 'rubygems'
11
+ require 'rufus/sixjo'
12
+
13
+
14
+ module SixjoTestMixin
15
+
16
+ [ :post, :get, :put, :delete ].each do |v|
17
+ module_eval <<-EOS
18
+ def #{v} (path, options={})
19
+ @response = \
20
+ Rack::MockRequest.new(@app).request('#{v}'.upcase, path, options)
21
+ @response
22
+ end
23
+ EOS
24
+ end
25
+
26
+ MFD_BOUNDARY = "AaB03x"
27
+
28
+ def encode_multipart (data = {})
29
+ ret = ""
30
+ data.each do |key, value|
31
+ next if value == nil or value.strip == ''
32
+ ret << "--#{MFD_BOUNDARY}\r\n"
33
+ ret << "Content-Disposition: form-data; name=\"#{key}\"\r\n\r\n"
34
+ ret << value
35
+ ret << "\r\n"
36
+ end
37
+ ret << "--#{MFD_BOUNDARY}--\r\n"
38
+ end
39
+ end
40
+
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rufus-sixjo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - John Mettraux
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-08-15 00:00:00 +09:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rack
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description:
26
+ email: john at gmail dot com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.txt
33
+ files:
34
+ - lib/rufus
35
+ - lib/rufus/sixjo.rb
36
+ - test/ft_0_simple.rb
37
+ - test/ft_1_helpers.rb
38
+ - test/ft_2_redirect.rb
39
+ - test/ft_3_erb.rb
40
+ - test/ft_4_configure.rb
41
+ - test/ft_5_put.rb
42
+ - test/test.rb
43
+ - test/testmixins.rb
44
+ - README.txt
45
+ has_rdoc: true
46
+ homepage: http://rufus.rubyforge.org/rufus-sixjo
47
+ post_install_message:
48
+ rdoc_options: []
49
+
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ requirements:
65
+ - rack
66
+ rubyforge_project:
67
+ rubygems_version: 1.2.0
68
+ signing_key:
69
+ specification_version: 2
70
+ summary: a rack application
71
+ test_files:
72
+ - test/test.rb