rack-restful-controller 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,80 @@
1
+ # Rack::RESTfulController
2
+
3
+ I had a crazy idea the other day. Write a class that _looks_ like a "RESTful" Rails controller. Pass it to Rack. And with the help of a little middleware action... voilà!
4
+
5
+ Only today, when I fleshed it out completely did I think, "This could be useful for writing a quick prototype then moving it to Rails when it's ready." It's _probably_ useful for that too.
6
+
7
+ This is the fruition of those things.
8
+
9
+ ## Install
10
+
11
+ gem install rack-restful-controller -s http://gemcutter.org
12
+
13
+ ## Usage
14
+
15
+ ### config.ru
16
+
17
+ require 'rack/restful-controller'
18
+
19
+ class Foo
20
+ def index
21
+ "this is the index" # return a string, it becomes [200, {...}, ["this is the index"]]
22
+ end
23
+
24
+ def show
25
+ end
26
+
27
+ def create
28
+ [302, {'Location' => '/42', ...}, ["body"]] # return an array, and it's just passed along to Rack
29
+ end
30
+
31
+ def edit
32
+ end
33
+
34
+ def update
35
+ end
36
+
37
+ def destroy
38
+ end
39
+
40
+ def foo
41
+ end
42
+
43
+ def bar
44
+ end
45
+ end
46
+
47
+ use Rack::RESTfulController, :collection => {:foo => :get}, :member => {:bar => :get}
48
+ run Rack::RESTfulController.as(Foo)
49
+
50
+ ## Caveats
51
+
52
+ * Rack::RESTfulController#call isn't really that robust, but it works. Welcome to suggestions.
53
+ * I don't really like the name of Rack::RESTfulController.as, but it was the best I could think of at the time.
54
+
55
+ ## TODO
56
+
57
+ * TEST
58
+ * Write a *few* helper methods; redirect_to, *_path, *_url
59
+
60
+ ## License
61
+
62
+ Copyright (c) 2009 Ryan Carmelo Briones &lt;<ryan.briones@brionesandco.com>&gt;
63
+
64
+ Permission is hereby granted, free of charge, to any person obtaining a copy
65
+ of this software and associated documentation files (the "Software"), to deal
66
+ in the Software without restriction, including without limitation the rights
67
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
68
+ copies of the Software, and to permit persons to whom the Software is
69
+ furnished to do so, subject to the following conditions:
70
+
71
+ The above copyright notice and this permission notice shall be included in
72
+ all copies or substantial portions of the Software.
73
+
74
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
75
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
76
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
77
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
78
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
79
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
80
+ THE SOFTWARE.
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+
4
+ spec = Gem::Specification.new do |s|
5
+ s.name = 'rack-restful-controller'
6
+ s.version = '0.0.1'
7
+ s.homepage = 'http://github.com/ryanbriones/rack-restful-controller'
8
+ s.summary = 'Rack application, "RESTful" Rails style.'
9
+ s.files = FileList['[A-Z]*', 'lib/rack/restful-controller.rb']
10
+ s.has_rdoc = false
11
+ s.author = 'Ryan Carmelo Briones'
12
+ s.email = 'ryan.briones@brionesandco.com'
13
+
14
+ s.add_dependency 'rack', '>=1.0.0'
15
+ end
16
+
17
+ package_task = Rake::GemPackageTask.new(spec) {}
18
+
19
+ task :build_gemspec do
20
+ File.open("#{spec.name}.gemspec", "w") do |f|
21
+ f.write spec.to_ruby
22
+ end
23
+ end
24
+
25
+ task :default => [:build_gemspec, :gem]
@@ -0,0 +1,92 @@
1
+ module Rack
2
+ class RESTfulController
3
+ @@collection_methods = {}
4
+ @@member_methods = {:edit => :get}
5
+
6
+ module App
7
+ def call(env)
8
+ @request = Rack::Request.new(env)
9
+ @params = (@request.params || {}).merge(env['restful.params'])
10
+
11
+ if env['restful.action'] && respond_to?(env['restful.action'])
12
+ body = send(env['restful.action'])
13
+ case body
14
+ when String
15
+ [200, {'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s}, [body]]
16
+ when Array
17
+ body
18
+ end
19
+ else
20
+ body = "Not Found: #{@request.path}"
21
+ [404, {'Content-Type' => 'text/plain', 'Content-Length' => body.length.to_s}, [body]]
22
+ end
23
+ end
24
+ end
25
+
26
+ def self.as(klass)
27
+ a = klass.new
28
+ a.extend(App)
29
+ a
30
+ end
31
+
32
+ def initialize(app, options = {})
33
+ @app = app
34
+ @options = options
35
+
36
+ if(options.include?(:collection))
37
+ @@collection_methods.merge!(options[:collection])
38
+ end
39
+
40
+ if(options.include?(:member))
41
+ @@member_methods.merge!(options[:member])
42
+ end
43
+ end
44
+
45
+ def call(env)
46
+ req = Rack::Request.new(env)
47
+
48
+ env['restful.params'] = {}
49
+
50
+ if req.get? && req.path == '/'
51
+ env['restful.action'] = :index
52
+ elsif req.get? && (match = req.path.match(/^\/(.+?)(?:\/(.+))?$/))
53
+ if(match[2] && @@member_methods[match[2].to_sym] == :get)
54
+ env['restful.action'] = match[2].to_sym
55
+ env['restful.params'] = {'id' => match[1]}
56
+ elsif(match[2] && @@member_methods[match[2].to_sym] != :get)
57
+ elsif(!match[2] && @@collection_methods[match[1].to_sym] == :get)
58
+ env['restful.action'] = match[1].to_sym
59
+ else
60
+ env['restful.action'] = :show
61
+ env['restful.params'] = {'id' => match[1]}
62
+ end
63
+ elsif req.post? && req.path == '/'
64
+ env['restful.action'] = :create
65
+ elsif (req.put? || mimic_put?(req)) && (match = req.path.match(/^\/(.+?)(?:\/(.+))?$/))
66
+ if(match[2] && @@member_methods[match[2].to_sym] == :put)
67
+ env['restful.action'] = match[2].to_sym
68
+ env['restful.params'] = {'id' => match[1]}
69
+ elsif(match[2] && @@member_methods[match[2].to_sym] != :put)
70
+ else
71
+ env['restful.action'] = :update
72
+ env['restful.params'] = {'id' => match[1]}
73
+ end
74
+ elsif (req.delete? || mimic_delete?(req)) && (match = req.path.match(/^\/(.+)$/))
75
+ env['restful.action'] = :destroy
76
+ env['restful.params'] = {'id' => match[1]}
77
+ end
78
+
79
+ env['restful.params'].merge!('action' => env['restful.action'].to_s)
80
+
81
+ @app.call(env)
82
+ end
83
+
84
+ def mimic_put?(req)
85
+ req.post? && req.params['_method'] == 'put'
86
+ end
87
+
88
+ def mimic_delete?(req)
89
+ req.post? && req.params['_method'] == 'delete'
90
+ end
91
+ end
92
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-restful-controller
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Carmelo Briones
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-26 00:00:00 -04: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: 1.0.0
24
+ version:
25
+ description:
26
+ email: ryan.briones@brionesandco.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - Rakefile
35
+ - README.markdown
36
+ - lib/rack/restful-controller.rb
37
+ has_rdoc: true
38
+ homepage: http://github.com/ryanbriones/rack-restful-controller
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options: []
43
+
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.3.5
62
+ signing_key:
63
+ specification_version: 3
64
+ summary: Rack application, "RESTful" Rails style.
65
+ test_files: []
66
+