frankrb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/frank.gemspec +22 -0
  2. data/lib/frank.rb +54 -0
  3. data/rakefile +8 -0
  4. data/test/frank.rb +109 -0
  5. data/test/helper.rb +8 -0
  6. metadata +83 -0
@@ -0,0 +1,22 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "frankrb"
3
+ s.version = "0.0.1"
4
+ s.summary = "A proof of concept originally conceived while writing a blog post."
5
+ s.description = "Frank tries to demonstrate how to write a basic Sinatra-ish clone."
6
+ s.authors = ["Cyril David"]
7
+ s.email = ["me@cyrildavid.com"]
8
+ s.homepage = "http://github.com/cyx/frankrb"
9
+
10
+ s.files = Dir[
11
+ "LICENSE",
12
+ "README",
13
+ "rakefile",
14
+ "lib/**/*.rb",
15
+ "*.gemspec",
16
+ "test/*.*"
17
+ ]
18
+
19
+ s.add_dependency "rack"
20
+ s.add_development_dependency "cutest"
21
+ s.add_development_dependency "capybara"
22
+ end
@@ -0,0 +1,54 @@
1
+ require "rack"
2
+
3
+ class Frank
4
+ def self.get(path, &block)
5
+ handlers["GET"] << [matcher(path), block]
6
+ end
7
+
8
+ def self.post(path, &block)
9
+ handlers["POST"] << [matcher(path), block]
10
+ end
11
+
12
+ def self.put(path, &block)
13
+ handlers["PUT"] << [matcher(path), block]
14
+ end
15
+
16
+ def self.delete(path, &block)
17
+ handlers["DELETE"] << [matcher(path), block]
18
+ end
19
+
20
+ def self.matcher(path)
21
+ # handle the case where the path has a variable
22
+ # e.g. /post/:id
23
+ re = path.gsub(/\:[^\/]+/, "([^\\/]+)")
24
+
25
+ %r{\A#{trim_trailing_slash(re)}\z}
26
+ end
27
+
28
+ def self.trim_trailing_slash(str)
29
+ str.gsub(/\/$/, "")
30
+ end
31
+
32
+ def self.handlers
33
+ @handlers ||= Hash.new { |h, k| h[k] = [] }
34
+ end
35
+
36
+ def self.request
37
+ Thread.current[:request]
38
+ end
39
+
40
+ def self.call(env)
41
+ res = Rack::Response.new
42
+
43
+ handlers[env["REQUEST_METHOD"]].each do |matcher, block|
44
+ if match = trim_trailing_slash(env["PATH_INFO"]).match(matcher)
45
+ Thread.current[:request] = Rack::Request.new(env)
46
+
47
+ break res.write(block.call(*match.captures))
48
+ end
49
+ end
50
+
51
+ res.status = 404 if res.empty?
52
+ res.finish
53
+ end
54
+ end
@@ -0,0 +1,8 @@
1
+ desc "Run all tests"
2
+ task :test do
3
+ require "cutest"
4
+
5
+ Cutest.run_file "./test/frank.rb"
6
+ end
7
+
8
+ task :default => :test
@@ -0,0 +1,109 @@
1
+ require_relative "helper"
2
+
3
+ class Blog < Frank
4
+ get "/" do
5
+ "Main Blog"
6
+ end
7
+
8
+ get "/post/:id" do |id|
9
+ "Displaying post #{id}"
10
+ end
11
+ end
12
+
13
+ class Support < Frank
14
+ get "/" do
15
+ "Main Support Site"
16
+ end
17
+
18
+ get "/submit" do
19
+ "<form method='post'><textarea name='issue'></textarea>" +
20
+ "<input type='submit' name='submit' value='Help'></form>"
21
+ end
22
+
23
+ post "/submit" do
24
+ "Received issue: %s" % request.params["issue"]
25
+ end
26
+ end
27
+
28
+ class Docs < Frank
29
+ get "/" do
30
+ "We're here to help!"
31
+ end
32
+
33
+ get "/download" do
34
+ "Download our documentation in PDF or read it online!"
35
+ end
36
+ end
37
+
38
+ class Home < Frank
39
+ get "/" do
40
+ "Homepage"
41
+ end
42
+
43
+ get "/about" do
44
+ "About"
45
+ end
46
+ end
47
+
48
+ def helloapp
49
+ builder = Rack::Builder.new
50
+
51
+ builder.map "/blog" do
52
+ run Blog
53
+ end
54
+
55
+ builder.map "/docs" do
56
+ run Docs
57
+ end
58
+
59
+ builder.map "/support" do
60
+ run Support
61
+ end
62
+
63
+ builder.run Home
64
+
65
+ return builder.to_app
66
+ end
67
+
68
+ prepare do
69
+ Capybara.app = helloapp
70
+ end
71
+
72
+ scope do
73
+ test "home" do
74
+ visit "/"
75
+ assert_equal "Homepage", page.source
76
+ end
77
+
78
+ test "about" do
79
+ visit "/about"
80
+ assert_equal "About", page.source
81
+ end
82
+
83
+ test "docs" do
84
+ visit "/docs"
85
+ assert_equal "We're here to help!", page.source
86
+
87
+ # Also works with trailing slashes
88
+ visit "/docs/"
89
+ assert_equal "We're here to help!", page.source
90
+
91
+ # Also works with trailing slash + a query string
92
+ visit "/docs/?foo=bar"
93
+ assert_equal "We're here to help!", page.source
94
+ end
95
+
96
+ test "support" do
97
+ visit "/support/submit"
98
+
99
+ fill_in "issue", with: "I need help!"
100
+ click_button "Help"
101
+
102
+ assert_equal "Received issue: I need help!", page.source
103
+ end
104
+
105
+ test "blog" do
106
+ visit "/blog/post/1234/"
107
+ assert_equal "Displaying post 1234", page.source
108
+ end
109
+ end
@@ -0,0 +1,8 @@
1
+ require_relative "../lib/frank"
2
+
3
+ require "cutest"
4
+ require "capybara/dsl"
5
+
6
+ class Cutest::Scope
7
+ include Capybara::DSL
8
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: frankrb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Cyril David
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rack
16
+ requirement: &2156228740 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2156228740
25
+ - !ruby/object:Gem::Dependency
26
+ name: cutest
27
+ requirement: &2156228100 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *2156228100
36
+ - !ruby/object:Gem::Dependency
37
+ name: capybara
38
+ requirement: &2156264720 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *2156264720
47
+ description: Frank tries to demonstrate how to write a basic Sinatra-ish clone.
48
+ email:
49
+ - me@cyrildavid.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - rakefile
55
+ - lib/frank.rb
56
+ - frank.gemspec
57
+ - test/frank.rb
58
+ - test/helper.rb
59
+ homepage: http://github.com/cyx/frankrb
60
+ licenses: []
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 1.8.16
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: A proof of concept originally conceived while writing a blog post.
83
+ test_files: []