tobias-sinatra-respond_to 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .bundle
2
+ .DS_Store
3
+ pkg/
4
+ coverage/
5
+ coverage.info
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --profile
data/Changelog.rdoc ADDED
@@ -0,0 +1,81 @@
1
+ === 0.5.0 / 2010-08-22
2
+
3
+ * Requires Sinatra 1.x
4
+ * Allow specifying format through a format param to the url
5
+
6
+ === 0.4.0 / 2010-01-30
7
+
8
+ * Specify that when running into unknown template languages the error message defaults to a generic template example
9
+ * Update code example
10
+ * Update supported sinatra versions in README
11
+ * Remove issues section because I believe it has been corrected
12
+ * Update development error message for new builder syntax
13
+ * Remove redundant hoe dependency and update rcov opts
14
+ * Fix the media_type -> mime_type conversion on Sinatra 0.9
15
+ * Fix rendering with extensions, e.g. resource.html.haml
16
+ * Add spec and passing code for content_type usage
17
+ * Changed how development error images are shown
18
+ * Update media_type to mime_type for Sinatra 1.0 while maintaining backward compat
19
+
20
+ === 0.3.8 / 2010-01-30
21
+
22
+ * Need to bump because of wrong gem name
23
+ * Fix some issues in the README
24
+
25
+ === 0.3.7 / 2010-01-30
26
+
27
+ * Update builder template for how sinatra handles this now
28
+ * Update spec tests for 1.9
29
+ * Update XMLHttpResponse test for new rack-test
30
+ * Regenerated gemspec for version 0.3.6
31
+
32
+ === 0.3.6 / 2009-07-31
33
+
34
+ * Version bump to 0.3.6
35
+ * solving incompatibility between 1.9 to fully qualify TEXT_MIME_TYPES check
36
+
37
+ === 0.3.5 / 2009-05-14
38
+
39
+ * Regenerated gemspec for version 0.3.5
40
+ * Version bump to 0.3.5
41
+ * better testing of environment expectations, workarounds for sinatra environment switching
42
+ * problem in spec, wasn't checking for right thing
43
+ * spec for reaching the /__sinatra__/*.png images
44
+ * couple more tests for charset and format helpers
45
+ * reduce regex use and simplify others
46
+ * some more code cleaning
47
+ * simplification and readability
48
+ * add some more specification for respond_to
49
+
50
+ === 0.3.4 / 2009-05-13
51
+
52
+ * updated gemspec
53
+ * Version bump to 0.3.4
54
+ * updated readme
55
+ * passing code for tests
56
+ * tests and tests
57
+ * typo in readme
58
+ * allow for content_type setting automatically when not using respond_to
59
+ * make it a bit clearer in readme that outside of respond_to content_type is not set
60
+ * bumped gem version in gemspec
61
+ * noted the change in classic applications, the gem now works around this but not following extension writing guidelines
62
+
63
+ === 0.3.3 / 2009-05-12
64
+
65
+ * Version bump to 0.3.3
66
+ * Version bump to 0.3.2
67
+ * spec referenced file not in repository
68
+
69
+ === 0.3.1 / 2009-05-11
70
+
71
+ * Version bump to 0.3.1
72
+ * add sinatra as a dependency
73
+ * allow overriding default charset in respond_to
74
+ * install instructions
75
+ * first gem
76
+ * Version bump to 0.0.0
77
+ * missing end in example
78
+ * add caveats about existing routes
79
+ * fix a little error in example
80
+ * updated readme and license
81
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,43 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ sinatra-respond_to (0.5.0)
5
+ sinatra (~> 1.1)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ builder (2.1.2)
11
+ diff-lcs (1.1.2)
12
+ haml (3.0.22)
13
+ rack (1.2.1)
14
+ rack-test (0.5.6)
15
+ rack (>= 1.0)
16
+ rcov (0.9.9)
17
+ rspec (2.0.1)
18
+ rspec-core (~> 2.0.1)
19
+ rspec-expectations (~> 2.0.1)
20
+ rspec-mocks (~> 2.0.1)
21
+ rspec-core (2.0.1)
22
+ rspec-expectations (2.0.1)
23
+ diff-lcs (>= 1.1.2)
24
+ rspec-mocks (2.0.1)
25
+ rspec-core (~> 2.0.1)
26
+ rspec-expectations (~> 2.0.1)
27
+ sinatra (1.1.0)
28
+ rack (~> 1.1)
29
+ tilt (~> 1.1)
30
+ tilt (1.1)
31
+
32
+ PLATFORMS
33
+ ruby
34
+
35
+ DEPENDENCIES
36
+ builder (>= 2.0)
37
+ bundler (~> 1.0.0)
38
+ haml (>= 2.0)
39
+ rack-test (~> 0.5.6)
40
+ rcov (~> 0.9.8)
41
+ rspec (~> 2.0.1)
42
+ sinatra (~> 1.1)
43
+ sinatra-respond_to!
data/README.md ADDED
@@ -0,0 +1,145 @@
1
+ # sinatra-respond\_to
2
+
3
+ * http://www.github.com/cehoffman/sinatra-respond\_to
4
+
5
+ ## DESCRIPTION:
6
+
7
+ A respond\_to style Rails block for baked-in web service support in Sinatra
8
+
9
+ ## FEATURES/PROBLEMS:
10
+
11
+ * Handles setting the content type depending on what is being served
12
+ * Automatically can adjust XMLHttpRequests to return Javascript
13
+
14
+ ## SYNOPSIS:
15
+
16
+ Allows urls of the form **/posts**, **/posts.rss**, and **/posts?format=atom** to route to the same Sinatra block and format specific respond\_to block.
17
+
18
+ require 'sinatra'
19
+ require 'sinatra/respond_to'
20
+
21
+ Sinatra::Application.register Sinatra::RespondTo
22
+
23
+ get '/posts' do
24
+ @posts = Post.recent
25
+
26
+ respond_to do |wants|
27
+ wants.html { haml :posts } # => views/posts.html.haml, also sets content_type to text/html
28
+ wants.rss { haml :posts } # => views/posts.rss.haml, also sets content_type to application/rss+xml
29
+ wants.atom { haml :posts } # => views/posts.atom.haml, also sets content_type to appliation/atom+xml
30
+ end
31
+ end
32
+
33
+ get '/post/:id' do
34
+ @post = Post.find(params[:id])
35
+
36
+ respond_to do |wants|
37
+ wants.html { haml :post } # => views/post.html.haml, also sets content_type to text/html
38
+ wants.xhtml { haml :post } # => views/post.xhtml.haml, also sets content_type to application/xhtml+xml
39
+ wants.xml { @post.to_xml } # => sets content_type to application/xml
40
+ wants.js { erb :post } # => views/post.js.erb, also sets content_type to application/javascript
41
+ end
42
+ end
43
+
44
+ get '/comments/:id' do
45
+ @comment = Comment.find(params[:id])
46
+
47
+ respond_to do |wants|
48
+ wants.html { haml :comment } # => views/comment.html.haml, also sets content_type to text/html
49
+ wants.json { @comment.to_json } # => sets content_type to application/json
50
+ wants.js { erb :comment } # => views/comment.js.erb, also sets content_type to application/javascript
51
+ end
52
+ end
53
+
54
+ To change the character set of the response, there is a `charset` helper. For example
55
+
56
+ get '/iso-8859-1' do
57
+ charset 'iso-8859-1'
58
+ "This is now sent using iso-8859-1 character set"
59
+ end
60
+
61
+ get '/respond_to-mixed' do
62
+ respond_to do |wants|
63
+ wants.html { charset 'iso-8859-1'; "Some html in iso-8859-1" }
64
+ wants.xml { builder :utf-8-xml } # => this is returned in the default character set
65
+ end
66
+ end
67
+
68
+ ## CONFIGURATION:
69
+
70
+ There a few options available for configuring the default behavior of respond\_to using Sinatra's `set` utility.
71
+
72
+ * **default\_content - :html**
73
+ When a user vists a url without an extension, for example /post this will be
74
+ the assumed content to serve first. Expects a symbol as used in setting content_type.
75
+ * **assume\_xhr\_is\_js - true**
76
+ To avoid headaches with accept headers, and appending .js to urls, this will
77
+ cause the default format for all XmlHttpRequests to be classified as wanting Javascript
78
+ in the response.
79
+
80
+ ## REQUIREMENTS:
81
+
82
+ * sinatra 1.1
83
+
84
+ If you would like to use Sinatra 1.0, use version `0.5.0`.
85
+
86
+ ## INSTALL:
87
+
88
+ $ gem install sinatra-respond_to
89
+
90
+ ## CAVEATS:
91
+ Due to the way respond\_to works, all incoming requests have the extension striped from the request.path\_info. This causes routes like the following to fail.
92
+
93
+ get '/style.css' do
94
+ sass :style # => renders views/style.sass
95
+ end
96
+
97
+ They need to be changed to the following.
98
+
99
+ get '/style' do
100
+ sass :style # => renders views/style.css.sass
101
+ end
102
+
103
+ If you want to ensure the route only gets called for css requests try this. This will use sinatra's built in accept header matching.
104
+
105
+ get '/style', :provides => :css do
106
+ sass :style
107
+ end
108
+
109
+ ## DEVELOPERS:
110
+
111
+ After checking out the source, run:
112
+
113
+ $ bundle install
114
+ $ rake spec
115
+
116
+ This task will install any missing dependencies, run the tests/specs, and generate the RDoc.
117
+
118
+ ## Contributors
119
+
120
+ * [Ryan Schenk](http://github.com/rschenk/)
121
+
122
+ ## LICENSE:
123
+
124
+ (The MIT License)
125
+
126
+ Copyright (c) 2009-2010 Chris Hoffman
127
+
128
+ Permission is hereby granted, free of charge, to any person obtaining
129
+ a copy of this software and associated documentation files (the
130
+ 'Software'), to deal in the Software without restriction, including
131
+ without limitation the rights to use, copy, modify, merge, publish,
132
+ distribute, sublicense, and/or sell copies of the Software, and to
133
+ permit persons to whom the Software is furnished to do so, subject to
134
+ the following conditions:
135
+
136
+ The above copyright notice and this permission notice shall be
137
+ included in all copies or substantial portions of the Software.
138
+
139
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
140
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
141
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
142
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
143
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
144
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
145
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ begin
5
+ require 'rspec/core/rake_task'
6
+ desc 'Run specs'
7
+ RSpec::Core::RakeTask.new do |t|
8
+ t.rcov = true
9
+ t.rcov_opts = ['--sort coverage --text-summary --sort-reverse']
10
+ t.rcov_opts << "--comments --exclude spec,pkg,#{ENV['GEM_HOME']}"
11
+ end
12
+ rescue LoadError
13
+ puts 'RSpec not available, try a bundle install'
14
+ end
@@ -0,0 +1,219 @@
1
+ require 'sinatra/base'
2
+
3
+ # Accept header parsing was looked at but deemed
4
+ # too much of an irregularity to deal with. Problems with the header
5
+ # differences from IE, Firefox, Safari, and every other UA causes
6
+ # problems with the expected output. The general expected behavior
7
+ # would be serve html when no extension provided, but most UAs say
8
+ # they will accept application/xml with out a quality indicator, meaning
9
+ # you'd get the xml block served insead. Just plain retarded, use the
10
+ # extension and you'll never be suprised.
11
+
12
+ module Sinatra
13
+ module RespondTo
14
+ class UnhandledFormat < Sinatra::NotFound; end
15
+ class MissingTemplate < Sinatra::NotFound
16
+ def code; 500 end
17
+ end
18
+
19
+ def self.registered(app)
20
+ app.helpers RespondTo::Helpers
21
+
22
+ app.set :default_content, :html
23
+ app.set :assume_xhr_is_js, true
24
+
25
+ # We remove the trailing extension so routes
26
+ # don't have to be of the style
27
+ #
28
+ # get '/resouce.:format'
29
+ #
30
+ # They can instead be of the style
31
+ #
32
+ # get '/resource'
33
+ #
34
+ # and the format will automatically be available in <tt>format</tt>
35
+ app.before do
36
+ # Let through sinatra image urls in development
37
+ next if self.class.development? && request.path_info =~ %r{/__sinatra__/.*?.png}
38
+
39
+ unless options.static? && options.public? && (request.get? || request.head?) && static_file?(request.path_info)
40
+ if request.params.has_key? 'format'
41
+ format params['format']
42
+ else
43
+ # Sinatra relies on a side-effect from path_info= to
44
+ # determine its routes. A direct string change (e.g., sub!)
45
+ # would bypass that -- and fail to have the effect we're looking
46
+ # for.
47
+ request.path_info = request.path_info.sub %r{\.([^\./]+)$}, ''
48
+
49
+ # Thanks to Sinatra, users can call:
50
+ #
51
+ # set :default_content, :foo
52
+ # set :default_content, proc { :foo }
53
+ # set :default_content, proc { |bar| :foo }
54
+ #
55
+ # And get the same result from options.default_content(request).
56
+ _format = options.assume_xhr_is_js? ? :js : $1 if request.xhr?
57
+ _format ||= options.default_content(request)
58
+
59
+ format _format
60
+ end
61
+ end
62
+ end
63
+
64
+ app.configure :development do |dev|
65
+ dev.error UnhandledFormat do
66
+ content_type :html, :charset => 'utf-8'
67
+
68
+ (<<-HTML).gsub(/^ {10}/, '')
69
+ <!DOCTYPE html>
70
+ <html>
71
+ <head>
72
+ <style type="text/css">
73
+ body { text-align:center;font-family:helvetica,arial;font-size:22px;
74
+ color:#888;margin:20px}
75
+ #c {margin:0 auto;width:500px;text-align:left}
76
+ </style>
77
+ </head>
78
+ <body>
79
+ <h2>Sinatra doesn't know this ditty.</h2>
80
+ <img src='/__sinatra__/404.png'>
81
+ <div id="c">
82
+ Try this:
83
+ <pre>#{request.request_method.downcase} '#{request.path_info}' do\n respond_to do |wants|\n wants.#{format} { "Hello World" }\n end\nend</pre>
84
+ </div>
85
+ </body>
86
+ </html>
87
+ HTML
88
+ end
89
+
90
+ dev.error MissingTemplate do
91
+ content_type :html, :charset => 'utf-8'
92
+ response.status = request.env['sinatra.error'].code
93
+
94
+ engine = request.env['sinatra.error'].message.split('.').last
95
+ engine = 'haml' unless ['haml', 'builder', 'erb'].include? engine
96
+
97
+ path = File.basename(request.path_info)
98
+ path = "root" if path.nil? || path.empty?
99
+
100
+ format = engine == 'builder' ? 'xml' : 'html'
101
+
102
+ layout = case engine
103
+ when 'haml' then "!!!\n%html\n %body= yield"
104
+ when 'erb' then "<html>\n <body>\n <%= yield %>\n </body>\n</html>"
105
+ when 'builder' then "xml << yield"
106
+ end
107
+
108
+ layout = "<small>app.#{format}.#{engine}</small>\n<pre>#{escape_html(layout)}</pre>"
109
+
110
+ (<<-HTML).gsub(/^ {10}/, '')
111
+ <!DOCTYPE html>
112
+ <html>
113
+ <head>
114
+ <style type="text/css">
115
+ body { text-align:center;font-family:helvetica,arial;font-size:22px;
116
+ color:#888;margin:20px}
117
+ #c {margin:0 auto;width:500px;text-align:left;}
118
+ small {float:right;clear:both;}
119
+ pre {clear:both;}
120
+ </style>
121
+ </head>
122
+ <body>
123
+ <h2>Sinatra can't find #{request.env['sinatra.error'].message}</h2>
124
+ <img src='/__sinatra__/500.png'>
125
+ <div id="c">
126
+ Try this:<br />
127
+ #{layout}
128
+ <small>#{path}.#{format}.#{engine}</small>
129
+ <pre>Hello World!</pre>
130
+ <small>application.rb</small>
131
+ <pre>#{request.request_method.downcase} '#{request.path_info}' do\n respond_to do |wants|\n wants.#{engine == 'builder' ? 'xml' : 'html'} { #{engine} :#{path}#{",\n#{' '*32}layout => :app" if layout} }\n end\nend</pre>
132
+ </div>
133
+ </body>
134
+ </html>
135
+ HTML
136
+ end
137
+
138
+ end
139
+
140
+ app.class_eval do
141
+ # Changes in 1.0 Sinatra reuse render for layout so we store the
142
+ # original value to tell us if this is an automatic attempt to do a
143
+ # layout call. If it is, it might fail with Errno::ENOENT and we want
144
+ # to pass that back to sinatra since it isn't a MissingTemplate error
145
+ alias :render_without_format :render
146
+ def render(*args, &block)
147
+ assumed_layout = args[1] == :layout
148
+ args[1] = "#{args[1]}.#{format}".to_sym if args[1].is_a?(::Symbol)
149
+ render_without_format *args, &block
150
+ rescue Errno::ENOENT => e
151
+ raise MissingTemplate, "#{args[1]}.#{args[0]}" unless assumed_layout
152
+ raise e
153
+ end
154
+ private :render
155
+ end
156
+ end
157
+
158
+ module Helpers
159
+ # Patch the content_type function to remember the set type
160
+ # This helps cut down on time in the format helper so it
161
+ # doesn't have to do a reverse lookup on the header
162
+ def self.included(klass)
163
+ klass.class_eval do
164
+ alias :content_type_without_save :content_type
165
+ def content_type(*args)
166
+ @_format = args.first.to_sym
167
+ content_type_without_save *args
168
+ end
169
+ end
170
+ end
171
+
172
+ def format(val=nil)
173
+ unless val.nil?
174
+ mime_type = ::Sinatra::Base.mime_type(val)
175
+ fail "Unknown media type #{val}\nTry registering the extension with a mime type" if mime_type.nil?
176
+
177
+ @_format = val.to_sym
178
+ response['Content-Type'] ? response['Content-Type'].sub!(/^[^;]+/, mime_type) : content_type(@_format)
179
+ end
180
+
181
+ @_format
182
+ end
183
+
184
+ # This is mostly just a helper so request.path_info isn't changed when
185
+ # serving files from the public directory
186
+ def static_file?(path)
187
+ public_dir = File.expand_path(options.public)
188
+ path = File.expand_path(File.join(public_dir, unescape(path)))
189
+
190
+ path[0, public_dir.length] == public_dir && File.file?(path)
191
+ end
192
+
193
+ def charset(val=nil)
194
+ fail "Content-Type must be set in order to specify a charset" if response['Content-Type'].nil?
195
+
196
+ if response['Content-Type'] =~ /charset=[^;]+/
197
+ response['Content-Type'].sub!(/charset=[^;]+/, (val == '' && '') || "charset=#{val}")
198
+ else
199
+ response['Content-Type'] += ";charset=#{val}"
200
+ end unless val.nil?
201
+
202
+ response['Content-Type'][/charset=([^;]+)/, 1]
203
+ end
204
+
205
+ def respond_to(&block)
206
+ wants = {}
207
+ def wants.method_missing(type, *args, &handler)
208
+ ::Sinatra::Base.send(:fail, "Unknown media type for respond_to: #{type}\nTry registering the extension with a mime type") if ::Sinatra::Base.mime_type(type).nil?
209
+ self[type] = handler
210
+ end
211
+
212
+ yield wants
213
+
214
+ raise UnhandledFormat if wants[format].nil?
215
+ wants[format].call
216
+ end
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,5 @@
1
+ module Sinatra
2
+ module RespondTo
3
+ Version = '0.6.0'
4
+ end
5
+ end
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/sinatra/respond_to/version', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'tobias-sinatra-respond_to'
6
+ s.version = Sinatra::RespondTo::Version
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ['Chris Hoffman']
9
+ s.email = ['cehoffman@gmail.com']
10
+ s.homepage = 'http://github.com/cehoffman/sinatra-respond_to'
11
+ s.summary = 'A respond_to style Rails block for baked-in web service support in Sinatra'
12
+
13
+ s.required_rubygems_version = '>= 1.3.6'
14
+
15
+ s.add_runtime_dependency 'sinatra', '~> 1.1'
16
+
17
+ s.add_development_dependency 'rspec', '~> 2.0.1'
18
+ s.add_development_dependency 'rack-test', '~> 0.5.6'
19
+ s.add_development_dependency 'rcov', '~> 0.9.8'
20
+ s.add_development_dependency 'builder', '>= 2.0'
21
+ s.add_development_dependency 'haml', '>= 2.0'
22
+ s.add_development_dependency 'bundler', '~> 1.0.0'
23
+
24
+ s.files = `git ls-files`.split("\n")
25
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
26
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
27
+ s.require_path = 'lib'
28
+ end
@@ -0,0 +1,9 @@
1
+ class ProductionErrorApp < Sinatra::Base
2
+ set :environment, :production
3
+ register Sinatra::RespondTo
4
+ get '/missing-template' do
5
+ respond_to do |wants|
6
+ wants.html { haml :missing }
7
+ end
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ A static file
@@ -0,0 +1,55 @@
1
+ require 'sinatra/base'
2
+ require 'erb'
3
+ require 'haml'
4
+ require 'sass'
5
+ require 'builder'
6
+
7
+ class TestApp < Sinatra::Base
8
+ register Sinatra::RespondTo
9
+
10
+ set :views, File.join(File.dirname(__FILE__), 'views')
11
+ set :public, File.join(File.dirname(__FILE__), 'public')
12
+
13
+ get '/resource' do
14
+ respond_to do |wants|
15
+ wants.html { haml :resource }
16
+ wants.json { "We got some json" }
17
+ wants.xml { builder :resource }
18
+ wants.js { erb :resource }
19
+ wants.png { }
20
+ end
21
+ end
22
+
23
+ get '/default_charset' do
24
+ respond_to do |wants|
25
+ wants.html { "Should set charcter set to default_charset" }
26
+ end
27
+ end
28
+
29
+ get '/iso-8859-1' do
30
+ respond_to do |wants|
31
+ wants.html { charset 'iso-8859-1'; "Should have character set of iso-8859-1" }
32
+ end
33
+ end
34
+
35
+ get '/normal-no-respond_to' do
36
+ "Just some plain old text"
37
+ end
38
+
39
+ get '/style.css' do
40
+ "This route should fail"
41
+ end
42
+
43
+ get '/style-no-extension', :provides => :css do
44
+ "Should succeed only when browser accepts text/css"
45
+ end
46
+
47
+ get '/missing-template' do
48
+ respond_to do |wants|
49
+ wants.html { haml :missing }
50
+ wants.xml { builder :missing }
51
+ wants.js { erb :missing }
52
+ wants.css { sass :missing }
53
+ end
54
+ end
55
+ end
@@ -0,0 +1 @@
1
+ Unreachable static file
@@ -0,0 +1,2 @@
1
+ %html
2
+ %body= yield
@@ -0,0 +1 @@
1
+ Hello from HTML
@@ -0,0 +1,3 @@
1
+ $(function () {
2
+ return '<%= "Hiya from javascript" %>'
3
+ });
@@ -0,0 +1 @@
1
+ xml.root "Some XML"
@@ -0,0 +1,382 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe Sinatra::RespondTo do
4
+ def mime_type(sym)
5
+ ::Sinatra::Base.mime_type(sym)
6
+ end
7
+
8
+ describe "options" do
9
+ it "should initialize with :default_content set to :html" do
10
+ TestApp.default_content.should == :html
11
+ end
12
+
13
+ it "should initialize with :assume_xhr_is_js set to true" do
14
+ TestApp.assume_xhr_is_js == true
15
+ end
16
+ end
17
+
18
+ describe "assume_xhr_is_js" do
19
+ it "should set the content type to application/javascript for an XMLHttpRequest" do
20
+ header 'X_REQUESTED_WITH', 'XMLHttpRequest'
21
+
22
+ get '/resource'
23
+
24
+ last_response['Content-Type'].should =~ %r{#{mime_type(:js)}}
25
+ end
26
+
27
+ it "should not set the content type to application/javascript for an XMLHttpRequest when assume_xhr_is_js is false" do
28
+ TestApp.disable :assume_xhr_is_js
29
+ header 'X_REQUESTED_WITH', 'XMLHttpRequest'
30
+ get '/resource'
31
+
32
+ last_response['Content-Type'].should_not =~ %r{#{mime_type(:js)}}
33
+
34
+ # Put back the option, no side effects here
35
+ TestApp.enable :assume_xhr_is_js
36
+ end
37
+ end
38
+
39
+ describe "extension routing" do
40
+ it "should use a format parameter before sniffing out the extension" do
41
+ get "/resource?format=xml"
42
+ last_response.body.should =~ %r{\s*<root>Some XML</root>\s*}
43
+ end
44
+
45
+ it "breaks routes expecting an extension" do
46
+ # In test_app.rb the route is defined as get '/style.css' instead of get '/style'
47
+ get "/style.css"
48
+
49
+ last_response.should_not be_ok
50
+ end
51
+
52
+ it "should pick the default content option for routes with out an extension, and render haml templates" do
53
+ get "/resource"
54
+
55
+ last_response.body.should =~ %r{\s*<html>\s*<body>Hello from HTML</body>\s*</html>\s*}
56
+ end
57
+
58
+ it "should render for a template using builder" do
59
+ get "/resource.xml"
60
+
61
+ last_response.body.should =~ %r{\s*<root>Some XML</root>\s*}
62
+ end
63
+
64
+ it "should render for a template using erb" do
65
+ get "/resource.js"
66
+
67
+ last_response.body.should =~ %r{'Hiya from javascript'}
68
+ end
69
+
70
+ it "should return string literals in block" do
71
+ get "/resource.json"
72
+
73
+ last_response.body.should =~ %r{We got some json}
74
+ end
75
+
76
+ # This will fail if the above is failing
77
+ it "should set the appropriate content-type for route with an extension" do
78
+ get "/resource.xml"
79
+
80
+ last_response['Content-Type'].should =~ %r{#{mime_type(:xml)}}
81
+ end
82
+
83
+ it "should honor a change in character set in block" do
84
+ get "/iso-8859-1"
85
+
86
+ last_response['Content-Type'].should =~ %r{charset=iso-8859-1}
87
+ end
88
+
89
+ it "should return not found when path does not exist" do
90
+ get "/nonexistant-path.txt"
91
+
92
+ last_response.status.should == 404
93
+ end
94
+
95
+ describe "for static files" do
96
+ before(:all) do
97
+ TestApp.enable :static
98
+ end
99
+
100
+ after(:all) do
101
+ TestApp.disable :static
102
+ end
103
+
104
+ it "should allow serving static files from public directory" do
105
+ get '/static.txt'
106
+
107
+ last_response.body.should == "A static file"
108
+ end
109
+
110
+ it "should only serve files when static routing is enabled" do
111
+ TestApp.disable :static
112
+ get '/static.txt'
113
+
114
+ last_response.should_not be_ok
115
+ last_response.body.should_not == "A static file"
116
+
117
+ TestApp.enable :static
118
+ end
119
+
120
+ it "should not allow serving static files from outside the public directory" do
121
+ get '/../unreachable_static.txt'
122
+
123
+ last_response.should_not be_ok
124
+ last_response.body.should_not == "Unreachable static file"
125
+ end
126
+ end
127
+ end
128
+
129
+ describe "routes not using respond_to" do
130
+ it "should set the default content type when no extension" do
131
+ get "/normal-no-respond_to"
132
+
133
+ last_response['Content-Type'].should =~ %r{#{mime_type(TestApp.default_content)}}
134
+ end
135
+
136
+ it "should set the appropriate content type when given an extension" do
137
+ get "/normal-no-respond_to.css"
138
+
139
+ last_response['Content-Type'].should =~ %r{#{mime_type(:css)}}
140
+ end
141
+ end
142
+
143
+ describe "error pages in production" do
144
+ before(:each) do
145
+ @app = Rack::Builder.new { run ::ProductionErrorApp }
146
+ end
147
+
148
+ describe Sinatra::RespondTo::MissingTemplate do
149
+ it "should return 404 status when looking for a missing template in production" do
150
+ get '/missing-template'
151
+
152
+ last_response.status.should == 404
153
+ last_response.body.should_not =~ /Sinatra can't find/
154
+ end
155
+ end
156
+
157
+ describe Sinatra::RespondTo::UnhandledFormat do
158
+ it "should return with a 404 when an extension is not supported in production" do
159
+ get '/missing-template.txt'
160
+
161
+ last_response.status.should == 404
162
+ last_response.body.should_not =~ /respond_to/
163
+ end
164
+ end
165
+ end
166
+
167
+ describe "error pages in development:" do
168
+
169
+ it "should allow access to the /__sinatra__/*.png images" do
170
+ get '/__sinatra__/404.png'
171
+
172
+ last_response.should be_ok
173
+ end
174
+
175
+ describe Sinatra::RespondTo::MissingTemplate do
176
+ it "should return 500 status when looking for a missing template" do
177
+ get '/missing-template'
178
+
179
+ last_response.status.should == 500
180
+ end
181
+
182
+ it "should provide a helpful generic error message for a missing template when in development" do
183
+ get '/missing-template.css'
184
+
185
+ last_response.body.should =~ /missing-template\.html\.haml/
186
+ last_response.body.should =~ %r{get '/missing-template' do respond_to do |wants| wants.html \{ haml :missing-template, layout => :app \} end end}
187
+ end
188
+
189
+ it "should show the /__sinatra__/500.png" do
190
+ get '/missing-template'
191
+
192
+ last_response.body.should =~ %r{src='/__sinatra__/500.png'}
193
+ end
194
+
195
+ it "should provide a contextual code example for the template engine" do
196
+ # Haml
197
+ get '/missing-template'
198
+
199
+ last_response.body.should =~ %r{app.html.haml}
200
+ last_response.body.should =~ %r{missing-template.html.haml}
201
+ last_response.body.should =~ %r{get '/missing-template' do respond_to do |wants| wants.html \{ haml :missing-template, layout => :app \} end end}
202
+
203
+ # ERB
204
+ get '/missing-template.js'
205
+
206
+ last_response.body.should =~ %r{app.html.erb}
207
+ last_response.body.should =~ %r{missing-template.html.erb}
208
+ last_response.body.should =~ %r{get '/missing-template' do respond_to do |wants| wants.html \{ erb :missing-template, layout => :app \} end end}
209
+
210
+ # Builder
211
+ get '/missing-template.xml'
212
+
213
+ last_response.body.should =~ %r{app.xml.builder}
214
+ last_response.body.should =~ %r{missing-template.xml.builder}
215
+ last_response.body.should =~ %r{get '/missing-template' do respond_to do |wants| wants.xml \{ builder :missing-template, layout => :app \} end end}
216
+ end
217
+ end
218
+
219
+ describe Sinatra::RespondTo::UnhandledFormat do
220
+ it "should return with a 404 when an extension is not supported" do
221
+ get '/missing-template.txt'
222
+
223
+ last_response.status.should == 404
224
+ end
225
+
226
+ it "should provide a helpful error message for an unhandled format" do
227
+ get '/missing-template.txt'
228
+
229
+ last_response.body.should =~ %r{get '/missing-template' do respond_to do |wants| wants.txt \{ "Hello World" \} end end}
230
+ end
231
+
232
+ it "should show the /__sinatra__/404.png" do
233
+ get '/missing-template.txt'
234
+
235
+ last_response.body.should =~ %r{src='/__sinatra__/404.png'}
236
+ end
237
+ end
238
+ end
239
+
240
+ describe "helpers:" do
241
+ include Sinatra::Helpers
242
+ include Sinatra::RespondTo::Helpers
243
+
244
+ before(:each) do
245
+ stub!(:response).and_return({'Content-Type' => 'text/html'})
246
+ end
247
+
248
+ describe "charset" do
249
+ it "should set the working charset when called with a non blank string" do
250
+ response['Content-Type'].should_not =~ /charset/
251
+
252
+ charset 'utf-8'
253
+
254
+ response['Content-Type'].split(';').should include("charset=utf-8")
255
+ end
256
+
257
+ it "should remove the charset when called with a blank string" do
258
+ charset 'utf-8'
259
+ charset ''
260
+
261
+ response['Content-Type'].should_not =~ /charset/
262
+ end
263
+
264
+ it "should return the current charset when called with nothing" do
265
+ charset 'utf-8'
266
+
267
+ charset.should == 'utf-8'
268
+ end
269
+
270
+ it "should fail when the response does not have a Content-Type" do
271
+ response.delete('Content-Type')
272
+
273
+ lambda { charset }.should raise_error
274
+ end
275
+
276
+ it "should not modify the Content-Type when given no argument" do
277
+ response['Content-Type'] = "text/html;charset=iso-8859-1"
278
+
279
+ charset
280
+
281
+ response['Content-Type'].should == "text/html;charset=iso-8859-1"
282
+ end
283
+ end
284
+
285
+ describe "format" do
286
+ before(:each) do
287
+ stub!(:request).and_return(Sinatra::Request.new({}))
288
+ end
289
+
290
+ it "should set the correct mime type when given an extension" do
291
+ format :xml
292
+
293
+ response['Content-Type'].split(';').should include(mime_type(:xml))
294
+ end
295
+
296
+ it "should fail when set to an unknown extension type" do
297
+ lambda { format :bogus }.should raise_error
298
+ end
299
+
300
+ it "should return the current mime type extension" do
301
+ format :js
302
+
303
+ format.should == :js
304
+ end
305
+
306
+ it "should not modify the Content-Type when given no argument" do
307
+ response['Content-Type'] = "application/xml;charset=utf-8"
308
+
309
+ format
310
+
311
+ response['Content-Type'].should == "application/xml;charset=utf-8"
312
+ end
313
+
314
+ it "should not return nil when only content_type sets headers" do
315
+ settings = mock('settings')
316
+ settings.should_receive(:default_encoding).and_return('utf-8')
317
+ stub!(:settings).and_return(settings)
318
+
319
+ content_type :xhtml
320
+
321
+ format.should == :xhtml
322
+ end
323
+ end
324
+
325
+ describe "static_file?" do
326
+ before(:all) do
327
+ TestApp.enable :static
328
+ @static_folder = "/static folder/"
329
+ @reachable_static_file = "/static.txt"
330
+ @unreachable_static_file = "/../unreachable_static.txt"
331
+ end
332
+
333
+ after(:all) do
334
+ TestApp.disable :static
335
+ end
336
+
337
+ def options
338
+ TestApp
339
+ end
340
+
341
+ def unescape(path)
342
+ Rack::Utils.unescape(path)
343
+ end
344
+
345
+ it "should return true if the request path points to a file in the public directory" do
346
+ static_file?(@reachable_static_file).should be_true
347
+ end
348
+
349
+ it "should return false when pointing to files outside of the public directory" do
350
+ static_file?(@unreachable_static_file).should be_false
351
+ end
352
+
353
+ it "should return false when the path is for a folder" do
354
+ static_file?(@static_folder).should be_false
355
+ end
356
+ end
357
+
358
+ describe "respond_to" do
359
+ before(:each) do
360
+ stub!(:request).and_return(Sinatra::Request.new({}))
361
+ end
362
+
363
+ it "should fail for an unknown extension" do
364
+ lambda do
365
+ respond_to do |wants|
366
+ wants.bogus
367
+ end
368
+ end.should raise_error
369
+ end
370
+
371
+ it "should call the block corresponding to the current format" do
372
+ format :html
373
+
374
+ respond_to do |wants|
375
+ wants.js { "Some JS" }
376
+ wants.html { "Some HTML" }
377
+ wants.xml { "Some XML" }
378
+ end.should == "Some HTML"
379
+ end
380
+ end
381
+ end
382
+ end
@@ -0,0 +1,20 @@
1
+ #$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+ require 'rspec'
6
+ require 'rack/test'
7
+
8
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'sinatra', 'respond_to')
9
+ require File.join(File.dirname(__FILE__), 'app', 'test_app')
10
+ require File.join(File.dirname(__FILE__), 'app', 'production_error_app')
11
+
12
+ RSpec.configure do |config|
13
+ def app
14
+ @app ||= ::Rack::Builder.new do
15
+ run ::TestApp
16
+ end
17
+ end
18
+
19
+ config.include ::Rack::Test::Methods
20
+ end
metadata ADDED
@@ -0,0 +1,208 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tobias-sinatra-respond_to
3
+ version: !ruby/object:Gem::Version
4
+ hash: 7
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 6
9
+ - 0
10
+ version: 0.6.0
11
+ platform: ruby
12
+ authors:
13
+ - Chris Hoffman
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-10 00:00:00 -05:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: sinatra
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 13
30
+ segments:
31
+ - 1
32
+ - 1
33
+ version: "1.1"
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 13
45
+ segments:
46
+ - 2
47
+ - 0
48
+ - 1
49
+ version: 2.0.1
50
+ type: :development
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: rack-test
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ hash: 7
61
+ segments:
62
+ - 0
63
+ - 5
64
+ - 6
65
+ version: 0.5.6
66
+ type: :development
67
+ version_requirements: *id003
68
+ - !ruby/object:Gem::Dependency
69
+ name: rcov
70
+ prerelease: false
71
+ requirement: &id004 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ hash: 43
77
+ segments:
78
+ - 0
79
+ - 9
80
+ - 8
81
+ version: 0.9.8
82
+ type: :development
83
+ version_requirements: *id004
84
+ - !ruby/object:Gem::Dependency
85
+ name: builder
86
+ prerelease: false
87
+ requirement: &id005 !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ hash: 3
93
+ segments:
94
+ - 2
95
+ - 0
96
+ version: "2.0"
97
+ type: :development
98
+ version_requirements: *id005
99
+ - !ruby/object:Gem::Dependency
100
+ name: haml
101
+ prerelease: false
102
+ requirement: &id006 !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ hash: 3
108
+ segments:
109
+ - 2
110
+ - 0
111
+ version: "2.0"
112
+ type: :development
113
+ version_requirements: *id006
114
+ - !ruby/object:Gem::Dependency
115
+ name: bundler
116
+ prerelease: false
117
+ requirement: &id007 !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ~>
121
+ - !ruby/object:Gem::Version
122
+ hash: 23
123
+ segments:
124
+ - 1
125
+ - 0
126
+ - 0
127
+ version: 1.0.0
128
+ type: :development
129
+ version_requirements: *id007
130
+ description:
131
+ email:
132
+ - cehoffman@gmail.com
133
+ executables: []
134
+
135
+ extensions: []
136
+
137
+ extra_rdoc_files: []
138
+
139
+ files:
140
+ - .gitignore
141
+ - .rspec
142
+ - Changelog.rdoc
143
+ - Gemfile
144
+ - Gemfile.lock
145
+ - README.md
146
+ - Rakefile
147
+ - lib/sinatra/respond_to.rb
148
+ - lib/sinatra/respond_to/version.rb
149
+ - sinatra-respond_to.gemspec
150
+ - spec/app/production_error_app.rb
151
+ - spec/app/public/static folder/.keep
152
+ - spec/app/public/static.txt
153
+ - spec/app/test_app.rb
154
+ - spec/app/unreachable_static.txt
155
+ - spec/app/views/layout.html.haml
156
+ - spec/app/views/resource.html.haml
157
+ - spec/app/views/resource.js.erb
158
+ - spec/app/views/resource.xml.builder
159
+ - spec/extension_spec.rb
160
+ - spec/spec_helper.rb
161
+ has_rdoc: true
162
+ homepage: http://github.com/cehoffman/sinatra-respond_to
163
+ licenses: []
164
+
165
+ post_install_message:
166
+ rdoc_options: []
167
+
168
+ require_paths:
169
+ - lib
170
+ required_ruby_version: !ruby/object:Gem::Requirement
171
+ none: false
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ hash: 3
176
+ segments:
177
+ - 0
178
+ version: "0"
179
+ required_rubygems_version: !ruby/object:Gem::Requirement
180
+ none: false
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ hash: 23
185
+ segments:
186
+ - 1
187
+ - 3
188
+ - 6
189
+ version: 1.3.6
190
+ requirements: []
191
+
192
+ rubyforge_project:
193
+ rubygems_version: 1.3.7
194
+ signing_key:
195
+ specification_version: 3
196
+ summary: A respond_to style Rails block for baked-in web service support in Sinatra
197
+ test_files:
198
+ - spec/app/production_error_app.rb
199
+ - spec/app/public/static folder/.keep
200
+ - spec/app/public/static.txt
201
+ - spec/app/test_app.rb
202
+ - spec/app/unreachable_static.txt
203
+ - spec/app/views/layout.html.haml
204
+ - spec/app/views/resource.html.haml
205
+ - spec/app/views/resource.js.erb
206
+ - spec/app/views/resource.xml.builder
207
+ - spec/extension_spec.rb
208
+ - spec/spec_helper.rb