frankrb 0.0.1

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.
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: []