swerling-synfeld 0.0.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +13 -1
- data/README.rdoc +105 -66
- data/README.txt +105 -66
- data/Rakefile +9 -1
- data/TODO +1 -2
- data/example/public/erb_files/erb_test.erb +7 -1
- data/example/public/haml_files/home.haml +5 -1
- data/example/public/html_files/html_test.html +1 -0
- data/example/public/images/beef_interstellar_thm.jpg +0 -0
- data/example/public/images/rails.png +0 -0
- data/example/try_me.rb +39 -31
- data/example/try_me.ru +5 -2
- data/lib/synfeld.rb +6 -2
- data/lib/synfeld/base.rb +168 -81
- data/lib/synfeld_info.rb +1 -1
- data/synfeld.gemspec +12 -8
- data/work/rackmount-test.ru +59 -0
- metadata +9 -5
data/History.txt
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
== 0.0.3 / 2009-09-12
|
2
|
+
|
3
|
+
* switch from rack-router to rack-mount for routing
|
4
|
+
|
5
|
+
== 0.0.3 / 2009-09-12
|
6
|
+
|
7
|
+
* ruby1.9 compat
|
8
|
+
|
9
|
+
== 0.0.2 / 2009-07-18
|
10
|
+
|
11
|
+
* Add some static types.
|
12
|
+
|
1
13
|
== 0.0.1 / 2009-07-18
|
2
14
|
|
3
|
-
* initial
|
15
|
+
* initial releases
|
data/README.rdoc
CHANGED
@@ -1,57 +1,48 @@
|
|
1
|
-
|
1
|
+
== *Synfeld*
|
2
2
|
|
3
3
|
by {Steven Swerling}[http://tab-a.slot-z.net]
|
4
4
|
|
5
5
|
{rdoc}[http://tab-a.slot-z.net] | {github}[http://www.github.com/swerling/synfeld]
|
6
6
|
|
7
|
-
==
|
7
|
+
== Description
|
8
8
|
|
9
9
|
Synfeld is a web application framework that does practically nothing.
|
10
10
|
|
11
|
-
|
11
|
+
Synfeld is little more than a small wrapper for Rack::Mount (see http://github.com/josh/rack-mount). If you want a web framework that is mostly just going to serve up json blobs, and occasionally serve up some simple content (eg. help files) and media, Synfeld makes that easy.
|
12
12
|
|
13
|
-
The sample app below shows pretty much everything
|
13
|
+
The sample app below shows pretty much everything there is to know about synfeld, in particular:
|
14
14
|
|
15
|
-
|
15
|
+
* How to define routes.
|
16
|
+
* Simple rendering of erb, haml, html, json, and static files.
|
17
|
+
* In the case of erb and haml, passing variables into the template is demonstrated.
|
18
|
+
* A dynamic action where the status code, headers, and body are created 'manually' (/my/special/route below)
|
19
|
+
* A simple way of creating format sensitive routes (/alphabet.html vs. /alphabet.json)
|
20
|
+
* The erb demo link also demos the rendering of a partial (not visible in the code below, you have to look at the template file examples/public/erb_files/erb_test.erb).
|
16
21
|
|
17
|
-
==
|
22
|
+
== Synopsis/Example
|
18
23
|
|
19
24
|
Here is an example Synfeld application (foo_app.rb):
|
20
25
|
|
26
|
+
require 'synfeld'
|
27
|
+
require 'json'
|
28
|
+
|
21
29
|
class FooApp < Synfeld::App
|
22
30
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
r.map "/haml_test", :get, :to => self, :with => { :action => "haml_test" }
|
34
|
-
r.map "/erb_test", :get, :to => self, :with => { :action => "erb_test" }
|
35
|
-
|
36
|
-
# These next 2 have to come last
|
37
|
-
r.map "/:anything_else", :get, :to => self, :with => { :action => "handle_static" }
|
38
|
-
r.map "/", :get, :to => self, :with => { :action => "home" }
|
39
|
-
end
|
31
|
+
def add_routes
|
32
|
+
add_route "/yap/:yap_variable", :action => "yap"
|
33
|
+
add_route "/html_test", :action => "html_test"
|
34
|
+
add_route "/haml_test", :action => "haml_test"
|
35
|
+
add_route "/erb_test", :action => "erb_test"
|
36
|
+
add_route '/alphabet.:format', :action => "alphabet"
|
37
|
+
add_route "/my/special/route", :action => "my_special_route",
|
38
|
+
:extra_parm1 => 'really',
|
39
|
+
:extra_parm2 => 'truly'
|
40
|
+
add_route '/', :action => "home"
|
40
41
|
end
|
41
42
|
|
42
43
|
# files are looked up relative to the root directory specified in initialize
|
43
44
|
def home
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
def my_special_route
|
48
|
-
self.response[:status_code] = 200
|
49
|
-
self.response[:headers]['Content-Type'] = 'text/html'
|
50
|
-
self.response[:body] = <<-HTML
|
51
|
-
<html>
|
52
|
-
<body>I'm <i>special</i>.</body>
|
53
|
-
</html>
|
54
|
-
HTML
|
45
|
+
render_haml('haml_files/home.haml')
|
55
46
|
end
|
56
47
|
|
57
48
|
def yap
|
@@ -59,40 +50,82 @@ Here is an example Synfeld application (foo_app.rb):
|
|
59
50
|
end
|
60
51
|
|
61
52
|
def html_test
|
62
|
-
|
53
|
+
render_html('html_files/html_test.html')
|
63
54
|
end
|
64
55
|
|
65
56
|
def haml_test
|
66
|
-
|
57
|
+
render_haml('haml_files/haml_test.haml', :ran100 => Kernel.rand(100) + 1, :time => Time.now)
|
67
58
|
end
|
68
59
|
|
69
60
|
def erb_test
|
70
|
-
|
61
|
+
render_erb('erb_files/erb_test.erb', :ran100 => Kernel.rand(100) + 1, :time => Time.now)
|
71
62
|
end
|
72
63
|
|
64
|
+
def alphabet
|
65
|
+
alphabet = ('a'..'z').collect{|ch|ch}
|
66
|
+
case params[:format]
|
67
|
+
when 'html'
|
68
|
+
return "<html><body>#{alphabet.join("<br/>")}</body></html>"
|
69
|
+
when 'json'
|
70
|
+
hash = {:desc => 'here is the alphabet', :alphabet => alphabet}
|
71
|
+
render_json hash.to_json
|
72
|
+
else
|
73
|
+
raise "Format not recognized: #{params[:format]}"
|
74
|
+
end
|
75
|
+
end
|
73
76
|
|
77
|
+
def my_special_route
|
78
|
+
self.response[:status_code] = 200
|
79
|
+
self.response[:headers]['Content-Type'] = 'text/html'
|
80
|
+
self.response[:body] = <<-HTML
|
81
|
+
<html>
|
82
|
+
<body>I'm <i>special</i>,
|
83
|
+
#{self.params[:extra_parm1]} and #{self.params[:extra_parm2]}</body>
|
84
|
+
</html>
|
85
|
+
HTML
|
86
|
+
end
|
74
87
|
end
|
75
88
|
|
76
89
|
And here is an example rack config, foo_app.ru:
|
77
90
|
|
78
91
|
require '/path/to/foo_app.rb'
|
79
|
-
|
92
|
+
use Rack::CommonLogger, logger = Logger.new('/tmp/synfeld.log')
|
93
|
+
foo_app = FooApp.new( :logger => logger, :root_dir => '/path/to/root/dir' )
|
94
|
+
run foo_app.as_rack_app
|
80
95
|
|
81
96
|
Run FooApp w/ rackup or shotgun:
|
82
97
|
|
83
|
-
rackup
|
98
|
+
rackup foo_app.ru -p 3000
|
84
99
|
|
85
100
|
or
|
86
101
|
|
87
|
-
shotgun
|
102
|
+
shotgun foo_app.ru -p 3000
|
103
|
+
|
104
|
+
== Features
|
105
|
+
|
106
|
+
==== The Router
|
107
|
+
|
108
|
+
When a Synfeld application starts up, it will call your app's 'add_routes' method, where you have to create your routes using the #add_route method. Example calls to add_route:
|
109
|
+
|
110
|
+
1. add_route %r{/some/path/(?:<somevar>.*)}, :action => "haml_test"
|
111
|
+
2. add_route "/some/otherpath/:somevar", :action => "haml_test"
|
112
|
+
3. add_route "/yet/anotherpath/:var", :action => "haml_test", :method => 'post', :furthermore => 'art is dead'
|
88
113
|
|
89
|
-
|
114
|
+
* At minimum, you have to provide the route and the :action to #add_route.
|
115
|
+
* When a route is passed as a regex (the 1st add_route line above), it is passed straight through to rackmount as is, so rackmount's rules apply.
|
116
|
+
* When using the convenience notation of the second add_route line above, the '/some/path/:somevar' is converted to a rackmount regex route under the covers, and :somevar will be passed to your app as a param (this is shown in the example code's #yap and #my_special_route methods).
|
117
|
+
* The 3rd add_route example shows how you can set any additional parameters on the route by adding associations onto the end of the route (this is also shown in #my_special_route in the example application above).
|
118
|
+
* If you happen to have a parameter called ':method', it will determine the request method required for the route (eg. 'get', 'put', 'post'). If the :method is not passed in, 'get' is assumed.
|
119
|
+
|
120
|
+
Note that rack-mount is an evolving project, so the examples above may have to be tweaked a bit in the future.
|
121
|
+
|
122
|
+
==== The Response
|
90
123
|
|
91
124
|
When a Synfeld application handles a rack request, it
|
92
125
|
|
93
|
-
1. Duplicates
|
94
|
-
2. Sets @response, @params, @env (the rack env)
|
95
|
-
3. Calls the action that
|
126
|
+
1. Duplicates itself (so it's thread safe)
|
127
|
+
2. Sets @response, @params, @env (@env is just the rack env)
|
128
|
+
3. Calls the action that the route that matched.
|
96
129
|
|
97
130
|
The @response is a hash used to return the rack status code, headers hash, and body. Actions may do what they please with the response. Default response:
|
98
131
|
|
@@ -103,47 +136,52 @@ The @response is a hash used to return the rack status code, headers hash, and b
|
|
103
136
|
}
|
104
137
|
|
105
138
|
|
106
|
-
Actions are expected to side-effect the :status_code, :headers, and :body if the defaults are not appropriate. As a convenience, if an action returns a string, it is assumed that that string is the :body. An exception is thrown if the :body is not set to something.
|
107
|
-
|
108
|
-
As the example app above shows, you can "serve" templated content in the form of 'haml' or 'erb' files.
|
139
|
+
Actions are expected to side-effect the :status_code, :headers, and :body if the defaults are not appropriate. As a convenience, if an action returns a string, it is assumed that that string is to be used as the response[:body]. An exception is thrown if the :body is not set to something. The 'Content-Length' header will be derived from the body's size.
|
109
140
|
|
110
|
-
|
141
|
+
As the example app above shows, you can serve templated content in the form of 'haml' or 'erb' files (the #erb_test and #haml_test methods in the code above).
|
111
142
|
|
112
|
-
|
143
|
+
Synfeld can currenty serve up the following types of static files:
|
113
144
|
|
114
145
|
js, css, png, gif, jpg, jpeg, html
|
115
146
|
|
116
|
-
|
147
|
+
Synfeld can currently render the following dynamic content:
|
148
|
+
|
149
|
+
erb, haml, json
|
150
|
+
|
151
|
+
Additional file types can be added upon request. Or you can just look at the synfeld code, which is tiny, then roll your own render method.
|
117
152
|
|
118
|
-
|
153
|
+
You can pass local variables to erb and haml.
|
119
154
|
|
120
|
-
|
155
|
+
Rendering 'partials' is trivial and is demonstrated in the included sample application file examples/public/erb_files/erb_test.erb.
|
121
156
|
|
122
|
-
That's
|
157
|
+
==== That's It
|
123
158
|
|
124
|
-
|
159
|
+
Synfeld just gives you a thread-safe rack-based web framework that consists of just a little more than a router. There's really not much to see. If you want caching, security, session access, etc, it is assumed you will add those as Rack middleware.
|
160
|
+
|
161
|
+
== Problems
|
125
162
|
|
126
163
|
None known.
|
127
164
|
|
128
|
-
==
|
165
|
+
== Requirements
|
129
166
|
|
167
|
+
* ruby (either 1.8.X or 1.9.X)
|
130
168
|
* ruby, rubygems, rack, rack-router
|
131
169
|
* For rack-router, see http://github.com/carllerche/rack-router
|
132
170
|
|
133
|
-
==
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
to you will have to clone it and build it yourself.
|
139
|
-
|
140
|
-
Then:
|
171
|
+
== Install
|
172
|
+
|
173
|
+
1. [install rack if necessary]
|
174
|
+
2. gem install josh-rack-mount --source=http://gems.github.com
|
175
|
+
3. gem install swerling-synfeld --source http://gems.github.com
|
141
176
|
|
142
|
-
|
177
|
+
(note: I noticed sometimes josh-rack-mount will complain about rack version
|
178
|
+
not being high enough, even if you are already on version 1.0.0. If that happens,
|
179
|
+
you have to clone the rack-mount repo locally and just build the rack-mount gem
|
180
|
+
yourself)
|
143
181
|
|
144
|
-
==
|
182
|
+
== License
|
145
183
|
|
146
|
-
(
|
184
|
+
(the MIT License)
|
147
185
|
|
148
186
|
Copyright (c) 2009 Steven Swerling
|
149
187
|
|
@@ -165,3 +203,4 @@ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
165
203
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
166
204
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
167
205
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
206
|
+
|
data/README.txt
CHANGED
@@ -1,57 +1,48 @@
|
|
1
|
-
|
1
|
+
== *Synfeld*
|
2
2
|
|
3
3
|
by {Steven Swerling}[http://tab-a.slot-z.net]
|
4
4
|
|
5
5
|
{rdoc}[http://tab-a.slot-z.net] | {github}[http://www.github.com/swerling/synfeld]
|
6
6
|
|
7
|
-
==
|
7
|
+
== Description
|
8
8
|
|
9
9
|
Synfeld is a web application framework that does practically nothing.
|
10
10
|
|
11
|
-
|
11
|
+
Synfeld is little more than a small wrapper for Rack::Mount (see http://github.com/josh/rack-mount). If you want a web framework that is mostly just going to serve up json blobs, and occasionally serve up some simple content (eg. help files) and media, Synfeld makes that easy.
|
12
12
|
|
13
|
-
The sample app below shows pretty much everything
|
13
|
+
The sample app below shows pretty much everything there is to know about synfeld, in particular:
|
14
14
|
|
15
|
-
|
15
|
+
* How to define routes.
|
16
|
+
* Simple rendering of erb, haml, html, json, and static files.
|
17
|
+
* In the case of erb and haml, passing variables into the template is demonstrated.
|
18
|
+
* A dynamic action where the status code, headers, and body are created 'manually' (/my/special/route below)
|
19
|
+
* A simple way of creating format sensitive routes (/alphabet.html vs. /alphabet.json)
|
20
|
+
* The erb demo link also demos the rendering of a partial (not visible in the code below, you have to look at the template file examples/public/erb_files/erb_test.erb).
|
16
21
|
|
17
|
-
==
|
22
|
+
== Synopsis/Example
|
18
23
|
|
19
24
|
Here is an example Synfeld application (foo_app.rb):
|
20
25
|
|
26
|
+
require 'synfeld'
|
27
|
+
require 'json'
|
28
|
+
|
21
29
|
class FooApp < Synfeld::App
|
22
30
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
r.map "/haml_test", :get, :to => self, :with => { :action => "haml_test" }
|
34
|
-
r.map "/erb_test", :get, :to => self, :with => { :action => "erb_test" }
|
35
|
-
|
36
|
-
# These next 2 have to come last
|
37
|
-
r.map "/:anything_else", :get, :to => self, :with => { :action => "handle_static" }
|
38
|
-
r.map "/", :get, :to => self, :with => { :action => "home" }
|
39
|
-
end
|
31
|
+
def add_routes
|
32
|
+
add_route "/yap/:yap_variable", :action => "yap"
|
33
|
+
add_route "/html_test", :action => "html_test"
|
34
|
+
add_route "/haml_test", :action => "haml_test"
|
35
|
+
add_route "/erb_test", :action => "erb_test"
|
36
|
+
add_route '/alphabet.:format', :action => "alphabet"
|
37
|
+
add_route "/my/special/route", :action => "my_special_route",
|
38
|
+
:extra_parm1 => 'really',
|
39
|
+
:extra_parm2 => 'truly'
|
40
|
+
add_route '/', :action => "home"
|
40
41
|
end
|
41
42
|
|
42
43
|
# files are looked up relative to the root directory specified in initialize
|
43
44
|
def home
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
def my_special_route
|
48
|
-
self.response[:status_code] = 200
|
49
|
-
self.response[:headers]['Content-Type'] = 'text/html'
|
50
|
-
self.response[:body] = <<-HTML
|
51
|
-
<html>
|
52
|
-
<body>I'm <i>special</i>.</body>
|
53
|
-
</html>
|
54
|
-
HTML
|
45
|
+
render_haml('haml_files/home.haml')
|
55
46
|
end
|
56
47
|
|
57
48
|
def yap
|
@@ -59,40 +50,82 @@ Here is an example Synfeld application (foo_app.rb):
|
|
59
50
|
end
|
60
51
|
|
61
52
|
def html_test
|
62
|
-
|
53
|
+
render_html('html_files/html_test.html')
|
63
54
|
end
|
64
55
|
|
65
56
|
def haml_test
|
66
|
-
|
57
|
+
render_haml('haml_files/haml_test.haml', :ran100 => Kernel.rand(100) + 1, :time => Time.now)
|
67
58
|
end
|
68
59
|
|
69
60
|
def erb_test
|
70
|
-
|
61
|
+
render_erb('erb_files/erb_test.erb', :ran100 => Kernel.rand(100) + 1, :time => Time.now)
|
71
62
|
end
|
72
63
|
|
64
|
+
def alphabet
|
65
|
+
alphabet = ('a'..'z').collect{|ch|ch}
|
66
|
+
case params[:format]
|
67
|
+
when 'html'
|
68
|
+
return "<html><body>#{alphabet.join("<br/>")}</body></html>"
|
69
|
+
when 'json'
|
70
|
+
hash = {:desc => 'here is the alphabet', :alphabet => alphabet}
|
71
|
+
render_json hash.to_json
|
72
|
+
else
|
73
|
+
raise "Format not recognized: #{params[:format]}"
|
74
|
+
end
|
75
|
+
end
|
73
76
|
|
77
|
+
def my_special_route
|
78
|
+
self.response[:status_code] = 200
|
79
|
+
self.response[:headers]['Content-Type'] = 'text/html'
|
80
|
+
self.response[:body] = <<-HTML
|
81
|
+
<html>
|
82
|
+
<body>I'm <i>special</i>,
|
83
|
+
#{self.params[:extra_parm1]} and #{self.params[:extra_parm2]}</body>
|
84
|
+
</html>
|
85
|
+
HTML
|
86
|
+
end
|
74
87
|
end
|
75
88
|
|
76
89
|
And here is an example rack config, foo_app.ru:
|
77
90
|
|
78
91
|
require '/path/to/foo_app.rb'
|
79
|
-
|
92
|
+
use Rack::CommonLogger, logger = Logger.new('/tmp/synfeld.log')
|
93
|
+
foo_app = FooApp.new( :logger => logger, :root_dir => '/path/to/root/dir' )
|
94
|
+
run foo_app.as_rack_app
|
80
95
|
|
81
96
|
Run FooApp w/ rackup or shotgun:
|
82
97
|
|
83
|
-
rackup
|
98
|
+
rackup foo_app.ru -p 3000
|
84
99
|
|
85
100
|
or
|
86
101
|
|
87
|
-
shotgun
|
102
|
+
shotgun foo_app.ru -p 3000
|
103
|
+
|
104
|
+
== Features
|
105
|
+
|
106
|
+
==== The Router
|
107
|
+
|
108
|
+
When a Synfeld application starts up, it will call your app's 'add_routes' method, where you have to create your routes using the #add_route method. Example calls to add_route:
|
109
|
+
|
110
|
+
1. add_route %r{/some/path/(?:<somevar>.*)}, :action => "haml_test"
|
111
|
+
2. add_route "/some/otherpath/:somevar", :action => "haml_test"
|
112
|
+
3. add_route "/yet/anotherpath/:var", :action => "haml_test", :method => 'post', :furthermore => 'art is dead'
|
88
113
|
|
89
|
-
|
114
|
+
* At minimum, you have to provide the route and the :action to #add_route.
|
115
|
+
* When a route is passed as a regex (the 1st add_route line above), it is passed straight through to rackmount as is, so rackmount's rules apply.
|
116
|
+
* When using the convenience notation of the second add_route line above, the '/some/path/:somevar' is converted to a rackmount regex route under the covers, and :somevar will be passed to your app as a param (this is shown in the example code's #yap and #my_special_route methods).
|
117
|
+
* The 3rd add_route example shows how you can set any additional parameters on the route by adding associations onto the end of the route (this is also shown in #my_special_route in the example application above).
|
118
|
+
* If you happen to have a parameter called ':method', it will determine the request method required for the route (eg. 'get', 'put', 'post'). If the :method is not passed in, 'get' is assumed.
|
119
|
+
|
120
|
+
Note that rack-mount is an evolving project, so the examples above may have to be tweaked a bit in the future.
|
121
|
+
|
122
|
+
==== The Response
|
90
123
|
|
91
124
|
When a Synfeld application handles a rack request, it
|
92
125
|
|
93
|
-
1. Duplicates
|
94
|
-
2. Sets @response, @params, @env (the rack env)
|
95
|
-
3. Calls the action that
|
126
|
+
1. Duplicates itself (so it's thread safe)
|
127
|
+
2. Sets @response, @params, @env (@env is just the rack env)
|
128
|
+
3. Calls the action that the route that matched.
|
96
129
|
|
97
130
|
The @response is a hash used to return the rack status code, headers hash, and body. Actions may do what they please with the response. Default response:
|
98
131
|
|
@@ -103,47 +136,52 @@ The @response is a hash used to return the rack status code, headers hash, and b
|
|
103
136
|
}
|
104
137
|
|
105
138
|
|
106
|
-
Actions are expected to side-effect the :status_code, :headers, and :body if the defaults are not appropriate. As a convenience, if an action returns a string, it is assumed that that string is the :body. An exception is thrown if the :body is not set to something.
|
107
|
-
|
108
|
-
As the example app above shows, you can "serve" templated content in the form of 'haml' or 'erb' files.
|
139
|
+
Actions are expected to side-effect the :status_code, :headers, and :body if the defaults are not appropriate. As a convenience, if an action returns a string, it is assumed that that string is to be used as the response[:body]. An exception is thrown if the :body is not set to something. The 'Content-Length' header will be derived from the body's size.
|
109
140
|
|
110
|
-
|
141
|
+
As the example app above shows, you can serve templated content in the form of 'haml' or 'erb' files (the #erb_test and #haml_test methods in the code above).
|
111
142
|
|
112
|
-
|
143
|
+
Synfeld can currenty serve up the following types of static files:
|
113
144
|
|
114
145
|
js, css, png, gif, jpg, jpeg, html
|
115
146
|
|
116
|
-
|
147
|
+
Synfeld can currently render the following dynamic content:
|
148
|
+
|
149
|
+
erb, haml, json
|
150
|
+
|
151
|
+
Additional file types can be added upon request. Or you can just look at the synfeld code, which is tiny, then roll your own render method.
|
117
152
|
|
118
|
-
|
153
|
+
You can pass local variables to erb and haml.
|
119
154
|
|
120
|
-
|
155
|
+
Rendering 'partials' is trivial and is demonstrated in the included sample application file examples/public/erb_files/erb_test.erb.
|
121
156
|
|
122
|
-
That's
|
157
|
+
==== That's It
|
123
158
|
|
124
|
-
|
159
|
+
Synfeld just gives you a thread-safe rack-based web framework that consists of just a little more than a router. There's really not much to see. If you want caching, security, session access, etc, it is assumed you will add those as Rack middleware.
|
160
|
+
|
161
|
+
== Problems
|
125
162
|
|
126
163
|
None known.
|
127
164
|
|
128
|
-
==
|
165
|
+
== Requirements
|
129
166
|
|
167
|
+
* ruby (either 1.8.X or 1.9.X)
|
130
168
|
* ruby, rubygems, rack, rack-router
|
131
169
|
* For rack-router, see http://github.com/carllerche/rack-router
|
132
170
|
|
133
|
-
==
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
to you will have to clone it and build it yourself.
|
139
|
-
|
140
|
-
Then:
|
171
|
+
== Install
|
172
|
+
|
173
|
+
1. [install rack if necessary]
|
174
|
+
2. gem install josh-rack-mount --source=http://gems.github.com
|
175
|
+
3. gem install swerling-synfeld --source http://gems.github.com
|
141
176
|
|
142
|
-
|
177
|
+
(note: I noticed sometimes josh-rack-mount will complain about rack version
|
178
|
+
not being high enough, even if you are already on version 1.0.0. If that happens,
|
179
|
+
you have to clone the rack-mount repo locally and just build the rack-mount gem
|
180
|
+
yourself)
|
143
181
|
|
144
|
-
==
|
182
|
+
== License
|
145
183
|
|
146
|
-
(
|
184
|
+
(the MIT License)
|
147
185
|
|
148
186
|
Copyright (c) 2009 Steven Swerling
|
149
187
|
|
@@ -165,3 +203,4 @@ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
165
203
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
166
204
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
167
205
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
206
|
+
|
data/Rakefile
CHANGED
@@ -48,13 +48,21 @@ task :myclobber => [:clobber] do
|
|
48
48
|
sh "rm -rf #{File.join(mydir, 'ext/*.so')}"
|
49
49
|
sh "rm -rf #{File.join(mydir, 'ext/Makefile')}"
|
50
50
|
sh "rm -rf #{File.join(mydir, 'ext/Makefile')}"
|
51
|
+
sh "cp #{File.join(mydir, 'README.rdoc')} #{File.join(mydir, 'README.txt')}" # concession to bones
|
51
52
|
end
|
52
53
|
task :mypackage => [:myclobber] do
|
53
54
|
Rake::Task['gem:package'].invoke
|
54
55
|
end
|
55
56
|
task :mydoc => [:myclobber] do
|
56
57
|
FileUtils.rm_f doc_dir()
|
57
|
-
sh "cd #{this_dir()} && rdoc -o rdoc --inline-source --format=html -T hanna README.rdoc lib/**/*.rb"
|
58
|
+
#sh "cd #{this_dir()} && rdoc -o rdoc --inline-source --format=html -T hanna README.rdoc lib/**/*.rb"
|
59
|
+
this_dir = File.dirname(__FILE__) + '/'
|
60
|
+
files = []
|
61
|
+
files += Dir[File.join(this_dir, 'lib/**/*.rb')].map{|fn| fn.gsub(this_dir,'')}
|
62
|
+
files += Dir[File.join(this_dir, 'example/**/*.*')].map{|fn| fn.gsub(this_dir,'')}
|
63
|
+
files += ['README.rdoc']
|
64
|
+
files = files.reject{|fn| fn =~ /jpg/ }.sort
|
65
|
+
sh "cd #{this_dir()} && rdoc -o rdoc --inline-source #{files.flatten.join(" ")}"
|
58
66
|
end
|
59
67
|
task :taba => [:mydoc] do
|
60
68
|
this_dir = File.join(File.dirname(__FILE__))
|
data/TODO
CHANGED
@@ -1,2 +1 @@
|
|
1
|
-
|
2
|
-
http://github.com/joshbuddy/usher/tree/master
|
1
|
+
Create a sourceforge gem and move all the docs over there from slot-z.com.
|
@@ -3,8 +3,14 @@
|
|
3
3
|
<div>
|
4
4
|
<h3> Here is an erb test</h3>
|
5
5
|
Here is the time: <%= time %>
|
6
|
-
<br/>ran100: <%= ran100 %>
|
6
|
+
<br/>ran100: <%= ran100 %> (local variable passed in)
|
7
7
|
<br/><a href="/">home</a>
|
8
|
+
<br/>
|
9
|
+
<br/>
|
10
|
+
Here is the home page rendered as a partial:
|
11
|
+
<div style="margin-left: 50px">
|
12
|
+
<%= render_haml('haml_files/home.haml') %>
|
13
|
+
</div>
|
8
14
|
</div>
|
9
15
|
</body>
|
10
16
|
</html>
|
@@ -11,5 +11,9 @@
|
|
11
11
|
%li
|
12
12
|
%a{:href => '/html_test'} test an html file
|
13
13
|
%li
|
14
|
-
%a{:href => '/my/special/route'} test of non-static action
|
14
|
+
%a{:href => '/my/special/route'} test of non-static action
|
15
|
+
%li
|
16
|
+
%a{:href => '/alphabet.json'} alphabet as json
|
17
|
+
%li
|
18
|
+
%a{:href => '/alphabet.html'} alphabet as html
|
15
19
|
|
@@ -6,6 +6,7 @@
|
|
6
6
|
<h3>Not much to see here</h3>
|
7
7
|
Just testing render of a html file.
|
8
8
|
<a href='http://www.github.com/swerling/synfeld'>synfeld on github</a>
|
9
|
+
<br/>Serve up a static: <a href='http://www.achewood.com/'> <img src='images/beef_interstellar_thm.jpg'/> </a>
|
9
10
|
</p>
|
10
11
|
|
11
12
|
</body>
|
Binary file
|
Binary file
|
data/example/try_me.rb
CHANGED
@@ -1,39 +1,24 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), '../lib/synfeld.rb'))
|
2
|
+
require 'json'
|
2
3
|
|
4
|
+
# This is the sample Synfeld::App described in the README.rdoc
|
3
5
|
class TryMe < Synfeld::App
|
4
6
|
|
5
|
-
def
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
r.map "/haml_test", :get, :to => self, :with => { :action => "haml_test" }
|
16
|
-
r.map "/erb_test", :get, :to => self, :with => { :action => "erb_test" }
|
17
|
-
|
18
|
-
# These next 2 have to come last
|
19
|
-
r.map "/:anything_else", :get, :to => self, :with => { :action => "handle_static" }
|
20
|
-
r.map "/", :get, :to => self, :with => { :action => "home" }
|
21
|
-
end
|
7
|
+
def add_routes
|
8
|
+
add_route "/yap/:yap_variable", :action => "yap"
|
9
|
+
add_route "/html_test", :action => "html_test"
|
10
|
+
add_route "/haml_test", :action => "haml_test"
|
11
|
+
add_route "/erb_test", :action => "erb_test"
|
12
|
+
add_route '/alphabet.:format', :action => "alphabet"
|
13
|
+
add_route "/my/special/route", :action => "my_special_route",
|
14
|
+
:extra_parm1 => 'really',
|
15
|
+
:extra_parm2 => 'truly'
|
16
|
+
add_route '/', :action => "home"
|
22
17
|
end
|
23
18
|
|
24
19
|
# files are looked up relative to the root directory specified in initialize
|
25
20
|
def home
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
def my_special_route
|
30
|
-
self.response[:status_code] = 200
|
31
|
-
self.response[:headers]['Content-Type'] = 'text/html'
|
32
|
-
self.response[:body] = <<-HTML
|
33
|
-
<html>
|
34
|
-
<body>I'm <i>special</i>.</body>
|
35
|
-
</html>
|
36
|
-
HTML
|
21
|
+
render_haml('haml_files/home.haml')
|
37
22
|
end
|
38
23
|
|
39
24
|
def yap
|
@@ -41,17 +26,40 @@ class TryMe < Synfeld::App
|
|
41
26
|
end
|
42
27
|
|
43
28
|
def html_test
|
44
|
-
|
29
|
+
render_html('html_files/html_test.html')
|
45
30
|
end
|
46
31
|
|
47
32
|
def haml_test
|
48
|
-
|
33
|
+
render_haml('haml_files/haml_test.haml', :ran100 => Kernel.rand(100) + 1, :time => Time.now)
|
49
34
|
end
|
50
35
|
|
51
36
|
def erb_test
|
52
|
-
|
37
|
+
render_erb('erb_files/erb_test.erb', :ran100 => Kernel.rand(100) + 1, :time => Time.now)
|
38
|
+
end
|
39
|
+
|
40
|
+
def alphabet
|
41
|
+
alphabet = ('a'..'z').collect{|ch|ch}
|
42
|
+
case params[:format]
|
43
|
+
when 'html'
|
44
|
+
return "<html><body>#{alphabet.join("<br/>")}</body></html>"
|
45
|
+
when 'json'
|
46
|
+
hash = {:desc => 'here is the alphabet', :alphabet => alphabet}
|
47
|
+
render_json hash.to_json
|
48
|
+
else
|
49
|
+
raise "Format not recognized: #{params[:format]}"
|
50
|
+
end
|
53
51
|
end
|
54
52
|
|
53
|
+
def my_special_route
|
54
|
+
self.response[:status_code] = 200
|
55
|
+
self.response[:headers]['Content-Type'] = 'text/html'
|
56
|
+
self.response[:body] = <<-HTML
|
57
|
+
<html>
|
58
|
+
<body>I'm <i>special</i>,
|
59
|
+
#{self.params[:extra_parm1]} and #{self.params[:extra_parm2]}</body>
|
60
|
+
</html>
|
61
|
+
HTML
|
62
|
+
end
|
55
63
|
|
56
64
|
end
|
57
65
|
|
data/example/try_me.ru
CHANGED
@@ -1,2 +1,5 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__),'try_me.rb')
|
2
|
-
|
1
|
+
require ::File.join(::File.dirname(__FILE__),'try_me.rb')
|
2
|
+
use Rack::CommonLogger, logger = Logger.new('/tmp/synfeld.log')
|
3
|
+
try_me = TryMe.new( :logger => logger,
|
4
|
+
:root_dir => ::File.expand_path(::File.join(::File.dirname(__FILE__), 'public')))
|
5
|
+
run try_me.as_rack_app
|
data/lib/synfeld.rb
CHANGED
@@ -1,13 +1,17 @@
|
|
1
|
+
F = ::File
|
2
|
+
|
1
3
|
# base ruby requires
|
4
|
+
require 'rubygems'
|
2
5
|
require 'logger'
|
3
6
|
|
4
7
|
# gems dependencies
|
5
8
|
require 'rubygems'
|
6
9
|
|
7
10
|
require 'rack'
|
8
|
-
require 'rack/
|
11
|
+
require 'rack/mount'
|
12
|
+
require 'rack/mime'
|
9
13
|
|
10
14
|
# my files (require_all_libs_relative_to is a bones util method in synfeld_info.rb)
|
11
|
-
require
|
15
|
+
require F.join(File.dirname(__FILE__), 'synfeld_info')
|
12
16
|
Synfeld.require_all_libs_relative_to(__FILE__)
|
13
17
|
|
data/lib/synfeld/base.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
-
module Synfeld
|
1
|
+
module Synfeld # :nodoc:
|
2
2
|
|
3
3
|
#
|
4
|
-
# See the synopsis section of README.
|
4
|
+
# See the synopsis section of README.rdoc for usage.
|
5
5
|
#
|
6
|
-
# See the
|
6
|
+
# See the README.rdoc for an overview of an Synfeld::App, and see the Rack::Mount project for
|
7
|
+
# more information on Rack::Mount style routing.
|
7
8
|
#
|
8
9
|
# Variables of note:
|
9
10
|
#
|
@@ -16,7 +17,13 @@ module Synfeld
|
|
16
17
|
# The rack env passed into this apps #call method
|
17
18
|
#
|
18
19
|
# @params
|
19
|
-
# The params
|
20
|
+
# The params as determined by the matching Rack::Mount route.
|
21
|
+
#
|
22
|
+
# @root_dir
|
23
|
+
# This dir is prepended to relative paths to locate files.
|
24
|
+
#
|
25
|
+
# @logger
|
26
|
+
# Either you pass in the @logger that synfeld uses, or it sets one up on STDOUT.
|
20
27
|
#
|
21
28
|
class App
|
22
29
|
attr_accessor :response, :params, :env, :root_dir, :logger
|
@@ -26,22 +33,37 @@ module Synfeld
|
|
26
33
|
# Note this is not the same thing as the rack access log (although you
|
27
34
|
# can pass that logger in if you want). Default: Logger.new(STDOUT)
|
28
35
|
def initialize(opts = {})
|
29
|
-
|
36
|
+
|
37
|
+
@logger = opts[:logger]
|
38
|
+
if self.logger.nil?
|
39
|
+
@logger = Logger.new(STDOUT)
|
40
|
+
puts "WARNING: Synfeld not configured with a logger, using STDOUT. Won't have much to say if running as a daemon."
|
41
|
+
end
|
42
|
+
|
30
43
|
@root_dir = opts[:root_dir]
|
31
|
-
|
32
|
-
|
44
|
+
if self.root_dir.nil?
|
45
|
+
raise "You have to pass in the location of the 'root_dir', where all the files in your synfeld app are located"
|
46
|
+
end
|
47
|
+
|
48
|
+
Kernel.at_exit {self.whine("Alright, I'm outta here.")}
|
33
49
|
end
|
34
50
|
|
35
|
-
#
|
36
|
-
#
|
37
|
-
|
38
|
-
raise "#{self.class} must implement a 'router' method that returns a Rack::Router"
|
39
|
-
end
|
51
|
+
#
|
52
|
+
# RACK PLUMBING
|
53
|
+
#
|
40
54
|
|
41
|
-
#
|
55
|
+
# Return self as a rackup-able rack application.
|
42
56
|
def as_rack_app
|
43
|
-
|
44
|
-
|
57
|
+
routes = Rack::Mount::RouteSet.new_without_optimizations do |set|
|
58
|
+
@set = set
|
59
|
+
self.add_routes
|
60
|
+
add_route %r{^.*$}, :action => "render_static"
|
61
|
+
end
|
62
|
+
app = Rack::Builder.new {
|
63
|
+
#use Rack::CommonLogger, $stderr
|
64
|
+
#use Rack::Reloader, 0
|
65
|
+
run routes
|
66
|
+
}.to_app
|
45
67
|
end
|
46
68
|
|
47
69
|
# The rack #call method
|
@@ -50,48 +72,85 @@ module Synfeld
|
|
50
72
|
end
|
51
73
|
|
52
74
|
#
|
53
|
-
#
|
75
|
+
# ROUTING
|
54
76
|
#
|
55
77
|
|
56
|
-
|
57
|
-
|
58
|
-
|
78
|
+
@@__regex_colon = (RUBY_VERSION =~ /^1.8/)? ':' : '' # :nodoc:
|
79
|
+
|
80
|
+
# See the README for a full explanation of how to use this method.
|
81
|
+
def add_route(string_or_regex, opts = {})
|
82
|
+
raise "You have to provide an :action method to call" unless opts[:action]
|
83
|
+
method = (opts.delete(:method) || 'GET').to_s.upcase
|
84
|
+
# Adapt string_or_regex into a rack-mount regex route. If it is a string, convert it to a
|
85
|
+
# rack-mount compatable regex. In paths that look like /some/:var/in/path, convert the ':var'
|
86
|
+
# bits to rack-mount variables.
|
87
|
+
if string_or_regex.is_a?(String)
|
88
|
+
regex_string = "^" + string_or_regex.gsub(/:(([^\/]+))/){|s| "(?#{@@__regex_colon}<#{$1}>.*)" } + "$"
|
89
|
+
regex = %r{#{regex_string}}
|
90
|
+
#puts regex_string # dbg
|
91
|
+
else
|
92
|
+
regex = string_or_regex
|
93
|
+
end
|
94
|
+
|
95
|
+
# Add the route to rack-mount
|
96
|
+
@set.add_route(self,
|
97
|
+
{:path_info => regex, :request_method => method.upcase},
|
98
|
+
opts)
|
59
99
|
end
|
60
100
|
|
61
|
-
#
|
62
|
-
|
63
|
-
|
64
|
-
|
101
|
+
#
|
102
|
+
# ACCESSORS & SUGAR
|
103
|
+
#
|
104
|
+
|
105
|
+
# The name of the action method bound to the route that mathed the incoming request.
|
106
|
+
def action
|
107
|
+
self.params[:action]
|
65
108
|
end
|
66
109
|
|
67
110
|
protected
|
68
111
|
|
69
|
-
# :
|
70
|
-
|
71
|
-
|
72
|
-
|
112
|
+
def _call(env) # :nodoc:
|
113
|
+
begin
|
114
|
+
start_time = Time.now.to_f
|
115
|
+
@env = env
|
116
|
+
@params = env[ Rack::Mount::Const::RACK_ROUTING_ARGS ]
|
117
|
+
@response = {
|
118
|
+
:status_code => 200,
|
119
|
+
:headers => {'Content-Type' => 'text/html'},
|
120
|
+
:body => nil
|
121
|
+
}
|
122
|
+
|
123
|
+
action = self.action
|
124
|
+
if self.respond_to?(action)
|
125
|
+
result = self.send(self.action)
|
126
|
+
else
|
127
|
+
result = self.no_action
|
128
|
+
end
|
129
|
+
|
130
|
+
if result.is_a?(String)
|
131
|
+
response[:body] = result
|
132
|
+
else
|
133
|
+
raise "You have to set the response body" if response[:body].nil?
|
134
|
+
end
|
73
135
|
|
74
|
-
|
75
|
-
@params = env['rack_router.params']
|
76
|
-
@response = {
|
77
|
-
:status_code => 200,
|
78
|
-
:headers => {'Content-Type' => 'text/html'},
|
79
|
-
:body => nil
|
80
|
-
}
|
136
|
+
response[:headers]["Content-Length"] = response[:body].size.to_s
|
81
137
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
138
|
+
logger.debug("It took #{Time.now.to_f - start_time} sec for #{self.class} to handle request.")
|
139
|
+
[response[:status_code], response[:headers], Array(response[:body])]
|
140
|
+
rescue Exception => e
|
141
|
+
# It seems like we should get this next line for free from the CommonLogger, so I guess
|
142
|
+
# I'm doing something wrong, missing some piece of rack middleware or something. Until I
|
143
|
+
# figure it out, I'm explicitly logging the exception manually.
|
144
|
+
self.whine "#{e.class}, #{e}\n\t#{e.backtrace.join("\n\t")} "
|
145
|
+
raise e
|
87
146
|
end
|
147
|
+
end
|
148
|
+
# :startdoc:
|
88
149
|
|
89
|
-
response[:body] = body if body.is_a?(String)
|
90
|
-
raise "You have to set the response body" if response[:body].nil?
|
91
150
|
|
92
|
-
|
93
|
-
|
94
|
-
|
151
|
+
#
|
152
|
+
# EXCEPTIONS
|
153
|
+
#
|
95
154
|
|
96
155
|
# send an error message to the log prepended by "Synfeld: "
|
97
156
|
def whine msg
|
@@ -100,33 +159,37 @@ module Synfeld
|
|
100
159
|
end
|
101
160
|
|
102
161
|
|
103
|
-
#
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
if File.exist?(full_fn)
|
109
|
-
ext = fn.split('.').last.downcase
|
162
|
+
# Overrideable method that handles a missing action that was defined by a route
|
163
|
+
def no_action
|
164
|
+
self.response[:body] = "Action '#{self.action}' not found in '#{self.class}'"
|
165
|
+
self.response[:status_code] = 500
|
166
|
+
end
|
110
167
|
|
111
|
-
|
168
|
+
# Overrideable method that handles 404
|
169
|
+
def no_route
|
170
|
+
self.response[:body] = "route not found for: '#{self.env['REQUEST_URI']}'"
|
171
|
+
self.response[:status_code] = 404
|
172
|
+
end
|
112
173
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
when 'erb'; return serve_erb(full_fn, local)
|
117
|
-
else raise "Unrecognized file type: '#{ext}'";
|
118
|
-
end
|
119
|
-
else
|
120
|
-
raise "Could not find file '#{fn}' (full path '#{full_fn}')"
|
121
|
-
end
|
174
|
+
#
|
175
|
+
# RENDERING
|
176
|
+
#
|
122
177
|
|
178
|
+
# Render an html file. 'fn' is a full path, or a path relative to @root_dir.
|
179
|
+
def render_html(fn)
|
180
|
+
F.read(full_path(fn))
|
123
181
|
end
|
124
182
|
|
125
|
-
|
126
|
-
|
183
|
+
# Serve up a blob of json (just sets Content-Type to 'text/javascript' and
|
184
|
+
# sets the body to the json passed in to this method).
|
185
|
+
def render_json(json)
|
186
|
+
self.response[:headers]['Content-Type'] = 'text/javascript'
|
187
|
+
self.response[:body] = json
|
127
188
|
end
|
128
189
|
|
129
|
-
|
190
|
+
# Render a haml file. 'fn' is a full path, or a path relative to @root_dir.
|
191
|
+
# 'locals' is a hash definining variables to be passed to the template.
|
192
|
+
def render_haml(fn, locals = {})
|
130
193
|
|
131
194
|
if not defined? Haml
|
132
195
|
begin
|
@@ -136,10 +199,12 @@ module Synfeld
|
|
136
199
|
end
|
137
200
|
end
|
138
201
|
|
139
|
-
Haml::Engine.new(
|
202
|
+
Haml::Engine.new(F.read(full_path(fn)) ).render(Object.new, locals)
|
140
203
|
end
|
141
204
|
|
142
|
-
|
205
|
+
# Render an erb file. 'fn' is a full path, or a path relative to @root_dir.
|
206
|
+
# 'locals' is a hash definining variables to be passed to the template.
|
207
|
+
def render_erb(fn, locals = {})
|
143
208
|
|
144
209
|
if not defined? Erb
|
145
210
|
begin
|
@@ -149,7 +214,7 @@ module Synfeld
|
|
149
214
|
end
|
150
215
|
end
|
151
216
|
|
152
|
-
template = ERB.new
|
217
|
+
template = ERB.new F.read(full_path(fn))
|
153
218
|
|
154
219
|
bind = binding
|
155
220
|
locals.each do |n,v|
|
@@ -159,34 +224,56 @@ module Synfeld
|
|
159
224
|
template.result(bind)
|
160
225
|
end
|
161
226
|
|
162
|
-
def
|
163
|
-
fn =
|
227
|
+
def render_static
|
228
|
+
fn = F.expand_path(F.join(root_dir, self.env['REQUEST_URI']))
|
164
229
|
#puts fn # dbg
|
165
|
-
if
|
230
|
+
if F.exist?(fn) and not F.directory?(fn)
|
166
231
|
self.content_type!(fn.split('.').last)
|
167
|
-
|
232
|
+
F.read(fn)
|
168
233
|
else
|
169
234
|
return self.no_route
|
170
235
|
end
|
171
236
|
end
|
172
237
|
|
238
|
+
#
|
239
|
+
# UTIL
|
240
|
+
#
|
241
|
+
|
242
|
+
# Given a file extention, determine the 'Content-Type' and then set the
|
243
|
+
# @response[:headers]['Content-Type']. Unrecognized extentions are
|
244
|
+
# set to content type of 'text/plain'.
|
173
245
|
def content_type!(ext)
|
174
246
|
case ext.downcase
|
175
|
-
when 'html'; t = 'text/html'
|
176
247
|
when 'haml'; t = 'text/html'
|
177
|
-
when '
|
178
|
-
|
179
|
-
when '
|
180
|
-
when '
|
181
|
-
when '
|
182
|
-
when '
|
248
|
+
when 'erb'; t = 'text/html'
|
249
|
+
# I believe all the rest are determined accurately by the Rack::Mime.mime_type call in the else clause below.
|
250
|
+
# when 'html'; t = 'text/html'
|
251
|
+
# when 'js'; t = 'text/javascript'
|
252
|
+
# when 'css'; t = 'text/css'
|
253
|
+
# when 'png'; t = 'image/png'
|
254
|
+
# when 'gif'; t = 'image/gif'
|
255
|
+
# when 'jpg'; t = 'image/jpeg'
|
256
|
+
# when 'jpeg'; t = 'image/jpeg'
|
257
|
+
else t = Rack::Mime.mime_type('.' + ext, 'text/plain')
|
183
258
|
end
|
259
|
+
#puts("----#{ext}:" + t.inspect) # dbg
|
184
260
|
(self.response[:headers]['Content-Type'] = t) if t
|
185
261
|
end
|
186
262
|
|
187
|
-
|
188
|
-
|
189
|
-
|
263
|
+
# Return fn if a file by that name exists. If not, concatenate the @root_dir with the fn, and
|
264
|
+
# return that if it exists. Raise if the actual file cannot be determined.
|
265
|
+
#
|
266
|
+
# NOTE: no effort is made to protect access to files outside of your application's root
|
267
|
+
# dir. If you permit filepaths as request parameters, then it is up to you to make sure
|
268
|
+
# that they do not point to some sensitive part of your file-system.
|
269
|
+
def full_path(fn)
|
270
|
+
if F.exist?(fn)
|
271
|
+
return fn
|
272
|
+
elsif F.exist?(full_fn = F.join(self.root_dir, fn))
|
273
|
+
return full_fn
|
274
|
+
else
|
275
|
+
raise "Could not find file '#{fn}' (full path '#{full_fn}')"
|
276
|
+
end
|
190
277
|
end
|
191
278
|
|
192
279
|
end # class App
|
data/lib/synfeld_info.rb
CHANGED
data/synfeld.gemspec
CHANGED
@@ -2,27 +2,31 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{synfeld}
|
5
|
-
s.version = "0.0.
|
5
|
+
s.version = "0.0.4"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Steven Swerling"]
|
9
|
-
s.date = %q{2009-
|
9
|
+
s.date = %q{2009-09-26}
|
10
10
|
s.description = %q{Synfeld is a web application framework that does practically nothing.
|
11
11
|
|
12
|
-
|
12
|
+
Synfeld is little more than a small wrapper for Rack::Mount (see http://github.com/josh/rack-mount). If you want a web framework that is mostly just going to serve up json blobs, and occasionally serve up some simple content (eg. help files) and media, Synfeld makes that easy.
|
13
13
|
|
14
|
-
The sample app below shows pretty much everything
|
14
|
+
The sample app below shows pretty much everything there is to know about synfeld, in particular:
|
15
15
|
|
16
|
-
|
16
|
+
* How to define routes.
|
17
|
+
* Simple rendering of erb, haml, html, json, and static files.
|
18
|
+
* In the case of erb and haml, passing variables into the template is demonstrated.
|
19
|
+
* A dynamic action where the status code, headers, and body are created 'manually' (/my/special/route below)
|
20
|
+
* A simple way of creating format sensitive routes (/alphabet.html vs. /alphabet.json)
|
21
|
+
* The erb demo link also demos the rendering of a partial (not visible in the code below, you have to look at the template file examples/public/erb_files/erb_test.erb).}
|
17
22
|
s.email = %q{sswerling@yahoo.com}
|
18
23
|
s.extra_rdoc_files = ["History.txt", "README.rdoc", "README.txt"]
|
19
|
-
s.files = [".gitignore", "History.txt", "README.rdoc", "README.txt", "Rakefile", "TODO", "example/public/erb_files/erb_test.erb", "example/public/haml_files/haml_test.haml", "example/public/haml_files/home.haml", "example/public/html_files/html_test.html", "example/try_me.rb", "example/try_me.ru", "lib/synfeld.rb", "lib/synfeld/base.rb", "lib/synfeld_info.rb", "spec/spec_helper.rb", "spec/synfeld_spec.rb", "synfeld.gemspec", "test/test_synfeld.rb"]
|
20
|
-
s.has_rdoc = true
|
24
|
+
s.files = [".gitignore", "History.txt", "README.rdoc", "README.txt", "Rakefile", "TODO", "example/public/erb_files/erb_test.erb", "example/public/haml_files/haml_test.haml", "example/public/haml_files/home.haml", "example/public/html_files/html_test.html", "example/public/images/beef_interstellar_thm.jpg", "example/public/images/rails.png", "example/try_me.rb", "example/try_me.ru", "lib/synfeld.rb", "lib/synfeld/base.rb", "lib/synfeld_info.rb", "spec/spec_helper.rb", "spec/synfeld_spec.rb", "synfeld.gemspec", "test/test_synfeld.rb", "work/rackmount-test.ru"]
|
21
25
|
s.homepage = %q{http://tab-a.slot-z.net}
|
22
26
|
s.rdoc_options = ["--inline-source", "--main", "README.txt"]
|
23
27
|
s.require_paths = ["lib"]
|
24
28
|
s.rubyforge_project = %q{synfeld}
|
25
|
-
s.rubygems_version = %q{1.3.
|
29
|
+
s.rubygems_version = %q{1.3.5}
|
26
30
|
s.summary = %q{Synfeld is a web application framework that does practically nothing}
|
27
31
|
s.test_files = ["test/test_synfeld.rb"]
|
28
32
|
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'rack/mount'
|
2
|
+
|
3
|
+
#@usher ||= Usher.new(:generator => Usher::Util::Generators::URL.new)
|
4
|
+
|
5
|
+
@app = proc do |env|
|
6
|
+
|
7
|
+
body = "Hi there #{env[ Rack::Mount::Const::RACK_ROUTING_ARGS].inspect}"
|
8
|
+
[
|
9
|
+
200, # Status code
|
10
|
+
{ # Response headers
|
11
|
+
'Content-Type' => 'text/plain',
|
12
|
+
'Content-Length' => body.size.to_s,
|
13
|
+
},
|
14
|
+
[body] # Response body
|
15
|
+
]
|
16
|
+
end
|
17
|
+
|
18
|
+
@set = nil
|
19
|
+
|
20
|
+
def add_a_route(opts = {})
|
21
|
+
method = (opts.delete(:method) || 'GET').upcase
|
22
|
+
string_or_regex = opts.delete(:path) || raise("You have to provide a :path")
|
23
|
+
colon = (RUBY_VERSION =~ /^1.8/)? ':' : ''
|
24
|
+
if string_or_regex.is_a?(String)
|
25
|
+
regex_string = "^" + string_or_regex.gsub(/:(([^\/]+))/){|s| "(?#{colon}<#{$1}>.*)" } + "$"
|
26
|
+
puts regex_string
|
27
|
+
regex = %r{#{regex_string}}
|
28
|
+
else
|
29
|
+
regex = string_or_regex
|
30
|
+
end
|
31
|
+
@set.add_route(@app,
|
32
|
+
{:path_info => regex, :request_method => method.upcase},
|
33
|
+
opts)
|
34
|
+
end
|
35
|
+
|
36
|
+
basic_set = Rack::Mount::RouteSet.new_without_optimizations do |set|
|
37
|
+
@set = set
|
38
|
+
# set.add_route(@app, { :path_info => %r{^/hello/(?:<hi>.*)$}, :request_method => 'GET' },
|
39
|
+
# { :controller => 'spscontroller_a', :action => 'spsaction_a' })
|
40
|
+
# set.add_route(@app, { :path_info => %r{^/hi/(?<ho>.*)$}, :request_method => 'GET' },
|
41
|
+
# { :controller => 'spscontroller_a', :action => 'spsaction_a' })
|
42
|
+
# set.add_route(@app, { :path_info => '/ho/steve', :request_method => 'GET' },
|
43
|
+
# { :controller => 'spscontroller_a', :action => 'spsaction_a' })
|
44
|
+
# set.add_route(@app, { :path_info => Rack::Mount::Utils.normalize_path('/baz') },
|
45
|
+
# { :controller => 'baz', :action => 'index' })
|
46
|
+
add_a_route(:path => '/hillo/:name',
|
47
|
+
:method => 'get',
|
48
|
+
:controller => 'spscontroller_a',
|
49
|
+
:action => 'spsaction_a' )
|
50
|
+
add_a_route( :path => '/ho/:nime/blah',
|
51
|
+
:controller => 'spscontroller_b',
|
52
|
+
:action => 'spsaction_b' )
|
53
|
+
add_a_route(:path => %r{^/hey/(?:<hi>.*)$}, :cont => 'cont_c', :act => 'action_c' )
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
run basic_set
|
58
|
+
|
59
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: swerling-synfeld
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steven Swerling
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-09-26 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: 2.5.1
|
44
44
|
version:
|
45
|
-
description: Synfeld is a web application framework that does practically nothing.
|
45
|
+
description: "Synfeld is a web application framework that does practically nothing. Synfeld is little more than a small wrapper for Rack::Mount (see http://github.com/josh/rack-mount). If you want a web framework that is mostly just going to serve up json blobs, and occasionally serve up some simple content (eg. help files) and media, Synfeld makes that easy. The sample app below shows pretty much everything there is to know about synfeld, in particular: * How to define routes. * Simple rendering of erb, haml, html, json, and static files. * In the case of erb and haml, passing variables into the template is demonstrated. * A dynamic action where the status code, headers, and body are created 'manually' (/my/special/route below) * A simple way of creating format sensitive routes (/alphabet.html vs. /alphabet.json) * The erb demo link also demos the rendering of a partial (not visible in the code below, you have to look at the template file examples/public/erb_files/erb_test.erb)."
|
46
46
|
email: sswerling@yahoo.com
|
47
47
|
executables: []
|
48
48
|
|
@@ -63,6 +63,8 @@ files:
|
|
63
63
|
- example/public/haml_files/haml_test.haml
|
64
64
|
- example/public/haml_files/home.haml
|
65
65
|
- example/public/html_files/html_test.html
|
66
|
+
- example/public/images/beef_interstellar_thm.jpg
|
67
|
+
- example/public/images/rails.png
|
66
68
|
- example/try_me.rb
|
67
69
|
- example/try_me.ru
|
68
70
|
- lib/synfeld.rb
|
@@ -72,8 +74,10 @@ files:
|
|
72
74
|
- spec/synfeld_spec.rb
|
73
75
|
- synfeld.gemspec
|
74
76
|
- test/test_synfeld.rb
|
75
|
-
|
77
|
+
- work/rackmount-test.ru
|
78
|
+
has_rdoc: false
|
76
79
|
homepage: http://tab-a.slot-z.net
|
80
|
+
licenses:
|
77
81
|
post_install_message:
|
78
82
|
rdoc_options:
|
79
83
|
- --inline-source
|
@@ -96,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
100
|
requirements: []
|
97
101
|
|
98
102
|
rubyforge_project: synfeld
|
99
|
-
rubygems_version: 1.
|
103
|
+
rubygems_version: 1.3.5
|
100
104
|
signing_key:
|
101
105
|
specification_version: 3
|
102
106
|
summary: Synfeld is a web application framework that does practically nothing
|