Class: Mango::Application
- Inherits:
-
Sinatra::Base
- Object
- Sinatra::Base
- Mango::Application
- Defined in:
- lib/mango/application.rb
Overview
It's probably no surprise that Mango::Application
is a modular application controller
class, inheriting all of the magic and wonder of Sinatra::Base
. The primary responsibility
of the class is to receive an HTTP request and send an HTML response by instructing the
necessary models and/or views to perform actions based on that request.
For every HTTP request, the application will first attempt to match the request URI path to
a public file found within settings.public_dir
and send that file with a 200 response code.
In addition to serving static assets, the application has these dynamic route handlers:
- Content page templates with
GET /*
- JavaScript templates with
GET /javascripts/*.js
- Stylesheet templates with
GET /stylesheets/*.css
and one error handler:
- 404 Page Not Found with
NOT_FOUND
Serving public files found within settings.public_dir
Example requests routed to public files
|-- content
| `-- override.haml
`-- themes
`-- default
|-- public
| |-- images
| | |-- index.html
| | `-- ripe-mango.jpg
| |-- override
| `-- robots.txt
`-- security_hole.txt
GET /robots.txt => 200 themes/default/public/robots.txt
GET /images/index.html => 200 themes/default/public/images/index.html
GET /images/ripe-mango.jpg => 200 themes/default/public/images/ripe-mango.jpg
GET /override => 200 themes/default/public/override
GET /images/ => 200 themes/default/public/images/index.html
GET /../security_hole.txt => pass to NOT_FOUND error handler
Content page templates with GET /*
Example GET /*
requests routed to content page templates
|-- content
| |-- about
| | |-- index.erb
| | `-- us.haml
| |-- index.markdown
| |-- override.haml
| `-- turner+hooch.haml
`-- security_hole.haml
GET / => 200 content/index.markdown
GET /index => 200 content/index.markdown
GET /index?foo=bar => 200 content/index.markdown
GET /about/ => 200 content/about/index.erb
GET /about/index => 200 content/about/index.erb
GET /about/us => 200 content/about/us.haml
GET /turner%2Bhooch => 200 content/turner+hooch.haml
GET /page_not_found => pass to another matching route or to the NOT_FOUND error
handler if none exists
GET /../security_hole => pass to another matching route or to the NOT_FOUND error
handler if none exists
JavaScript templates with GET /javascripts/*.js
Example GET /javascripts/*.js
requests routed to JavaScript files and templates
`-- themes
`-- default
|-- javascripts
| |-- override.coffee
| |-- siblings.coffee
| `-- songs
| `-- happy.coffee
|-- public
| |-- root.js
| `-- stylesheets
| |-- econ.js
| |-- math
| | `-- opposite.js
| `-- override.js
`-- security_hole.js
GET /javascripts/siblings.js => 200 themes/default/stylesheets/siblings.coffee
GET /javascripts/songs/happy.js => 200 themes/default/stylesheets/songs/happy.coffee
GET /javascripts/econ.js => 200 themes/default/public/javascripts/econ.js
GET /javascripts/override.js => 200 themes/default/public/javascripts/override.js
GET /root.js => 200 themes/default/public/root.js
GET /javascripts/math/opposite.js => 200 themes/default/public/javascripts/math/opposite.js
GET /javascripts/not_found.js => pass to another matching route or to the NOT_FOUND
error handler if none exists
GET /siblings.js => pass to another matching route or to the NOT_FOUND
error handler if none exists
GET /javascripts/../security_hole.js => pass to another matching route or to the NOT_FOUND
error handler if none exists
Stylesheet templates with GET /stylesheets/*.css
Example GET /stylesheets/*.css
requests routed to stylesheets files and templates
`-- themes
`-- default
|-- public
| |-- default.css
| `-- stylesheets
| |-- override.css
| |-- reset.css
| `-- folder
| `-- print.css
|-- security_hole.sass
`-- stylesheets
|-- override.sass
|-- screen.scss
`-- folder
`-- mobile.sass
GET /stylesheets/screen.css => 200 themes/default/stylesheets/screen.scss
GET /stylesheets/folder/mobile.css => 200 themes/default/stylesheets/folder/mobile.sass
GET /stylesheets/reset.css => 200 themes/default/public/stylesheets/reset.css
GET /stylesheets/override.css => 200 themes/default/public/stylesheets/override.css
GET /default.css => 200 themes/default/public/default.css
GET /stylesheets/folder/print.css => 200 themes/default/public/stylesheets/folder/print.css
GET /stylesheets/not_found.css => pass to another matching route or to the NOT_FOUND
error handler if none exists
GET /screen.css => pass to another matching route or to the NOT_FOUND
error handler if none exists
GET /stylesheets/../security_hole.css => pass to another matching route or to the NOT_FOUND
error handler if none exists
404 Page Not Found with NOT_FOUND
When a requested URI path cannot be matched with a public file or template file, and cannot be matched to another route, the error handler attempts to send a 404 public file or a rendered a 404 template file with a 404 HTTP response.
Example GET /page_not_found
request routed to a 404 public file
`-- themes
`-- default
`-- public
`-- 404.html
GET /page_not_found => 404 themes/default/public/404.html
Example GET /page_not_found
request routed to a 404 Haml template
|-- content
| `-- index.haml
`-- themes
`-- default
`-- views
`-- 404.haml
GET /page_not_found => 404 themes/default/views/404.haml
If no 404 public file or template is found, the application sends a basic "Page Not Found" page with a 404 HTTP response.
Defined Under Namespace
Classes: ContentPageNotFound, RegisteredEngineNotFound, ViewTemplateNotFound
Constant Summary collapse
- JAVASCRIPT_TEMPLATE_ENGINES =
Supported JavaScript template engines
{ Tilt::CoffeeScriptTemplate => :coffee }
- STYLESHEET_TEMPLATE_ENGINES =
Supported stylesheet template engines
{ Tilt::ScssTemplate => :scss, Tilt::SassTemplate => :sass }
- VIEW_TEMPLATE_ENGINES =
Supported view template engines
{ Tilt::HamlTemplate => :haml, Tilt::ERBTemplate => :erb, Tilt::LiquidTemplate => :liquid }
Class Attribute Summary collapse
-
.mime_type("", "text/html") ⇒ String
Registers
text/html
as the mime type for static files ending with""
.
Instance Attribute Summary collapse
-
#set(: content, lambda{ File.join(root, "content") }) ⇒ String
Defines
settings.content
. -
#set(: javascripts, lambda{ File.join(root, "themes", theme, "javascripts") }) ⇒ String
Defines
settings.javascripts
. -
#set(: public_dir, lambda{ File.join(root, "themes", theme, "public") }) ⇒ String
Defines
settings.public_dir
. -
#set(: root, Dir.getwd) ⇒ String
Defines
settings.root
. -
#set(: stylesheets, lambda{ File.join(root, "themes", theme, "stylesheets") }) ⇒ String
Defines
settings.stylesheets
. -
#set(: theme, "default") ⇒ String
Defines
settings.theme
. -
#set(: views, lambda{ File.join(root, "themes", theme, "views") }) ⇒ String
Defines
settings.views
.
Class Method Summary collapse
-
.find_content_page(uri_path) ⇒ ContentPage
Given a URI path, creates a new
ContentPage
instance by searching for and reading a content file from disk. -
.get("/*") ⇒ Object
Attempts to render content page templates found within
settings.content
. -
.get("/stylesheets/*.css") ⇒ Object
Attempts to render stylesheet templates found within
settings.stylesheets
. -
.get("/javascripts/*.js") ⇒ Object
Attempts to render JavaScript templates found within
settings.javascripts
. -
.not_found ⇒ Object
Renders a 404 page with a 404 HTTP response code.
-
.render_content_page!(uri_path) ⇒ Object
Given a URI path, attempts to render a content page, if it exists, and halt.
-
.render_index_file!(uri_path) ⇒ Object
Given a URI path, attempts to send an index.html file, if it exists, and halt.
-
.render_javascript_template!(uri_path) ⇒ Object
Given a URI path, attempts to render a JavaScript template, if it exists, and halt.
-
.render_stylesheet_template!(uri_path) ⇒ Object
Given a URI path, attempts to render a stylesheet template, if it exists, and halt.
Class Attribute Details
.mime_type("", "text/html") ⇒ String
Registers text/html
as the mime type for static files ending with ""
197 |
# File 'lib/mango/application.rb', line 197 mime_type "", "text/html" |
Instance Attribute Details
#set(: content, lambda{ File.join(root, "content") }) ⇒ String
Defines settings.content
189 |
# File 'lib/mango/application.rb', line 189 set :content, lambda { File.join(root, "content") } |
#set(: javascripts, lambda{ File.join(root, "themes", theme, "javascripts") }) ⇒ String
Defines settings.javascripts
185 |
# File 'lib/mango/application.rb', line 185 set :javascripts, lambda { File.join(root, "themes", theme, "javascripts") } |
#set(: public_dir, lambda{ File.join(root, "themes", theme, "public") }) ⇒ String
Defines settings.public_dir
187 |
# File 'lib/mango/application.rb', line 187 set :public_dir, lambda { File.join(root, "themes", theme, "public") } |
#set(: root, Dir.getwd) ⇒ String
Defines settings.root
183 |
# File 'lib/mango/application.rb', line 183 set :root, Dir.getwd |
#set(: stylesheets, lambda{ File.join(root, "themes", theme, "stylesheets") }) ⇒ String
Defines settings.stylesheets
186 |
# File 'lib/mango/application.rb', line 186 set :stylesheets, lambda { File.join(root, "themes", theme, "stylesheets") } |
#set(: theme, "default") ⇒ String
Defines settings.theme
184 |
# File 'lib/mango/application.rb', line 184 set :theme, "default" |
Class Method Details
.find_content_page(uri_path) ⇒ ContentPage
Given a URI path, creates a new ContentPage
instance by searching for and reading a content
file from disk. Content files are searched consecutively until a page with a supported
content page template engine is found.
572 573 574 575 576 577 578 579 580 581 582 |
# File 'lib/mango/application.rb', line 572 def find_content_page(uri_path) ContentPage::TEMPLATE_ENGINES.each do |engine, extension| @preferred_extension = extension.to_s find_template(settings.content, uri_path, engine) do |file| next unless File.file?(file) return ContentPage.new(data: File.read(file), engine: engine) end end raise ContentPageNotFound, "Cannot find content page for path -- #{uri_path}" end |
.get("/*") ⇒ Object
Attempts to render content page templates found within settings.content
First, the application attempts to match the URI path with a public file stored in
settings.public_dir
. If a public file is found, the handler will:
- Send the public file with a 200 HTTP response code
- Halt execution
For example:
`-- themes
`-- default
`-- public
`-- hello_word.html
GET /hello_word.html => 200 themes/default/public/hello_word.html
If no match is found, the route handler attempts to match the URI path with a content page
template stored in settings.content
. If a content page template is found, the application
will:
- Read the content page from disk and render the data in memory
- Render the content page's view template file (see
Mango::ContentPages
)- An exception is raised if a registered engine for the view template file cannot be
found or if the view template file cannot be found within
settings.views
.
- An exception is raised if a registered engine for the view template file cannot be
found or if the view template file cannot be found within
- Send the rendered page with a 200 HTTP response code and halt execution
In addition, if a layout
template file exists within settings.views
and that layout
template file shares the same file extension as the view template, then the page's view
template is wrapped within this layout template when rendered.
For example, given the following mango application:
|-- content
| `-- index.markdown
`-- themes
`-- default
`-- views
|-- layout.haml
`-- page.haml
where the index.markdown
content page's view template file is page.haml
, then:
GET /index => 200 content/index.markdown +
themes/default/views/page.haml +
themes/default/views/layout.haml
Finally, if no matches are found, execution is passed to the next matching route handler if
one exists. Otherwise, execution is passed to the NOT_FOUND
error handler.
494 495 496 497 498 |
# File 'lib/mango/application.rb', line 494 get "/*" do |uri_path| render_index_file! uri_path render_content_page! uri_path pass end |
.get("/stylesheets/*.css") ⇒ Object
Attempts to render stylesheet templates found within settings.stylesheets
First, the application attempts to match the URI path with a public stylesheet file stored in
settings.public_dir
. If a public stylesheet file is found, the application will:
- Send the public stylesheet file with a 200 HTTP response code
- Halt execution
For example:
`-- themes
`-- default
`-- public
`-- stylesheets
`-- reset.css
GET /stylesheets/reset.css => 200 themes/default/public/stylesheets/reset.css
If no match is found, the route handler attempts to match the URI path with a stylesheet
template stored in settings.stylesheets
. If a stylesheet template is found, the
application will:
- Render the template as CSS
- Send the rendered template with a 200 HTTP response code
- Halt execution
For example:
`-- themes
`-- default
`-- stylesheets
`-- screen.scss
GET /stylesheets/screen.css => 200 themes/default/stylesheets/screen.scss
It's intended that requests to public stylesheet files and requests to stylesheet templates
share the /stylesheets/
prefix.
Finally, if no matches are found, execution is passed to the next matching route handler if
one exists. Otherwise, execution is passed to the NOT_FOUND
error handler.
415 416 417 418 |
# File 'lib/mango/application.rb', line 415 get "/stylesheets/*.css" do |uri_path| render_stylesheet_template! uri_path pass end |
.get("/javascripts/*.js") ⇒ Object
Attempts to render JavaScript templates found within settings.javascripts
First, the application attempts to match the URI path with a public JavaScript file stored in
settings.public_dir
. If a public JavaScript file is found, the application will:
- Send the public JavaScript file with a 200 HTTP response code
- Halt execution
For example:
`-- themes
`-- default
`-- public
`-- javascripts
`-- jquery.js
GET /javascripts/jquery.js => 200 themes/default/public/javascripts/jquery.js
If no match is found, the route handler attempts to match the URI path with a JavaScript
template stored in settings.javascripts
. If a JavaScript template is found, the
application will:
- Render the template as Javascript
- Send the rendered template with a 200 HTTP response code
- Halt execution
For example:
`-- themes
`-- default
`-- javascripts
`-- bundle.coffee
GET /javascripts/bundle.js => 200 themes/default/javascripts/bundle.coffee
It's intended that requests to public JavaScript files and requests to JavaScript templates
share the /javascripts/
prefix.
Finally, if no matches are found, execution is passed to the next matching route handler if
one exists. Otherwise, execution is passed to the NOT_FOUND
error handler.
345 346 347 348 |
# File 'lib/mango/application.rb', line 345 get "/javascripts/*.js" do |uri_path| render_javascript_template! uri_path pass end |
.not_found ⇒ Object
Renders a 404 page with a 404 HTTP response code.
First, the application attempts to render a public 404 file stored in settings.public_dir
. If
a public 404 file is found, the application will:
- Send the public 404 file with a 404 HTTP response code
- Halt execution
For example:
`-- themes
`-- default
`-- public
`-- 404.html
GET /page_not_found => 404 themes/default/public/404.html
If no match is found, the application attempts to render a 404 template stored in
settings.views
. If a 404 template is found, the application will not render it within a
layout template, even if an appropriately named layout template exists within
settings.views
. If a 404 template is found, the application will:
- Render the 404 template, without a layout template, as HTML
- Send the rendered 404 template with a 404 HTTP response code
- Halt execution
For example:
|-- content
| `-- index.haml
`-- themes
`-- default
`-- views
`-- 404.haml
GET /page_not_found => 404 themes/default/views/404.haml
Finally, if no matches are found, the application sends a basic "Page Not Found" page with a 404 HTTP response code.
264 265 266 267 268 269 |
# File 'lib/mango/application.rb', line 264 not_found do file_name = "404" render_404_public_file! file_name render_404_template! file_name "<!DOCTYPE html><title>404 Page Not Found</title><h1>404 Page Not Found</h1>" end |
.render_content_page!(uri_path) ⇒ Object
Given a URI path, attempts to render a content page, if it exists, and halt
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 |
# File 'lib/mango/application.rb', line 533 def render_content_page!(uri_path) uri_path += "index" if URI.directory?(uri_path) content_match = File.join(settings.content, "*") content_page_path = File.(uri_path, settings.content) return unless File.fnmatch(content_match, content_page_path) begin content_page = find_content_page(uri_path) rescue ContentPageNotFound return end view_template_path = File.(content_page.view, settings.views) begin engine = VIEW_TEMPLATE_ENGINES.fetch(Tilt[content_page.view]) rescue KeyError = "Cannot find registered engine for view template file -- #{view_template_path}" raise RegisteredEngineNotFound, end begin halt send(engine, content_page.view.to_s.templatize, locals: { page: content_page }) rescue Errno::ENOENT = "Cannot find view template file -- #{view_template_path}" raise ViewTemplateNotFound, end end |
.render_index_file!(uri_path) ⇒ Object
Given a URI path, attempts to send an index.html file, if it exists, and halt
504 505 506 507 508 509 510 511 512 513 514 |
# File 'lib/mango/application.rb', line 504 def render_index_file!(uri_path) return unless URI.directory?(uri_path) index_match = File.join(settings.public_dir, "*") index_file_path = File.(uri_path + "index.html", settings.public_dir) return unless File.fnmatch(index_match, index_file_path) return unless File.file?(index_file_path) send_file index_file_path end |
.render_javascript_template!(uri_path) ⇒ Object
Given a URI path, attempts to render a JavaScript template, if it exists, and halt
355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
# File 'lib/mango/application.rb', line 355 def render_javascript_template!(uri_path) javascript_match = File.join(settings.javascripts, "*") javascript_path = File.(uri_path, settings.javascripts) return unless File.fnmatch(javascript_match, javascript_path) JAVASCRIPT_TEMPLATE_ENGINES.each do |engine, extension| @preferred_extension = extension.to_s find_template(settings.javascripts, uri_path, engine) do |file| next unless File.file?(file) halt send(extension, uri_path.to_sym, views: settings.javascripts) end end end |
.render_stylesheet_template!(uri_path) ⇒ Object
Given a URI path, attempts to render a stylesheet template, if it exists, and halt
425 426 427 428 429 430 431 432 433 434 435 436 437 438 |
# File 'lib/mango/application.rb', line 425 def render_stylesheet_template!(uri_path) stylesheet_match = File.join(settings.stylesheets, "*") stylesheet_path = File.(uri_path, settings.stylesheets) return unless File.fnmatch(stylesheet_match, stylesheet_path) STYLESHEET_TEMPLATE_ENGINES.each do |engine, extension| @preferred_extension = extension.to_s find_template(settings.stylesheets, uri_path, engine) do |file| next unless File.file?(file) halt send(extension, uri_path.to_sym, views: settings.stylesheets) end end end |