Class: Hoshi::View
- Inherits:
-
Object
- Object
- Hoshi::View
- Defined in:
- lib/hoshi/view.rb,
lib/hoshi/view-tag.rb,
lib/hoshi/view/html.rb,
lib/hoshi/view/rss2.rb,
lib/hoshi/view/html3.rb,
lib/hoshi/view/html4.rb,
lib/hoshi/view/html5.rb,
lib/hoshi/view/xhtml.rb,
lib/hoshi/view/xhtml1.rb,
lib/hoshi/view/xhtml2.rb,
lib/hoshi/view-tag-fallback.rb,
lib/hoshi/view/xhtml1_strict.rb,
lib/hoshi/view/html4_frameset.rb,
lib/hoshi/view/xhtml1_frameset.rb,
lib/hoshi/view/html4_transitional.rb,
lib/hoshi/view/xhtml1_transitional.rb
Overview
The View class is the super-class for views you create with Hoshi. More likely, though, you’ll be using one of View’s many sub-classes as the super-class for your view, like this:
class MyView < Hoshi::View :html4
or
class MyView < Hoshi::View::XHTML1Frameset
Of course, using View[] is the preferred method for the sake of brevity. When you create a view class, you’ll want to define one or more methods that eventually call View#render, which turns your view into HTML. (Private methods and methods that build up state do not need to do so.)
Defined Under Namespace
Classes: HTML, HTML3, HTML4, HTML4Frameset, HTML4Transitional, HTML5, RSS2, ValidationError, XHTML, XHTML1, XHTML1Frameset, XHTML1Transitional, XHTML2
Class Method Summary collapse
-
.[](doctype) ⇒ Object
This method choses, based on the provided doctype, the proper sub-class of View.
-
.build(*args, &block) ⇒ Object
Create and render a view via a block.
-
.content_type ⇒ Object
This is overridden in HTML/XHTML, and you’ll definitely want to override it if you subclass View directly.
-
.dtd!(dtd) ⇒ Object
Sets the doctype declaration for this class.
-
.open_tags(*names) ⇒ Object
A short-hand for creating multiple tags that are left open.
-
.permissive! ⇒ Object
Free-form tags.
-
.permissive? ⇒ Boolean
Returns true if we add tags to this class on the fly.
- .self_closing_tags(*names) ⇒ Object
-
.strict! ⇒ Object
Only the tags already specified are allowed.
-
.strict? ⇒ Boolean
Returns true if we do not add tags to the class on the fly.
-
.tag(name, close_type = nil) ⇒ Object
This method is a fallback for pre-1.8.7 Ruby; if a syntax error is encountered when hoshi/view.rb tries to load hoshi/view-tag.rb, this file is loaded.
-
.tags(*names) ⇒ Object
A short-hand for creating multiple tags via View.tag.
Instance Method Summary collapse
-
#_tag(tname, close_type = nil, inside = '', opts = {}) ⇒ Object
An inline tag; it just returns a string rather than updating the view object in place.
-
#append!(x) ⇒ Object
Appends something to the document.
-
#clear! ⇒ Object
Clears the current state of this view.
-
#comment(*a) ⇒ Object
Adds a comment.
-
#doc(&b) ⇒ Object
If you’re tired of typing “doctypenhtml” every single time.
- #doctype ⇒ Object
- #entity(e) ⇒ Object
-
#initialize ⇒ View
constructor
A new instance of View.
-
#method_missing(mname, *args, &b) ⇒ Object
Dynamically add tags if the view class for this object is permissive.
-
#raw(*things) ⇒ Object
Appends one or more non-escaped strings to the document.
-
#render ⇒ Object
Returns the string representation of the document.
-
#render_cgi(extra_headers = {}) ⇒ Object
Prints the string representation of the docutment, with HTTP headers.
-
#safe(*things) ⇒ Object
Turns things in to strings, properly escapes them, and appends them to the document.
-
#tag(tname, close_type = nil, *opts, &b) ⇒ Object
Appends a tag to the current document, for when a tag is only needed once or has a name that is not a valid method name.
Constructor Details
#initialize ⇒ View
Returns a new instance of View.
100 101 102 |
# File 'lib/hoshi/view.rb', line 100 def initialize clear! end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(mname, *args, &b) ⇒ Object
Dynamically add tags if the view class for this object is permissive.
193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/hoshi/view.rb', line 193 def method_missing(mname, *args, &b) if self.class.permissive? self.class.tag mname if b send mname, *args, &b else send mname, *args end else super end end |
Class Method Details
.[](doctype) ⇒ Object
This method choses, based on the provided doctype, the proper sub-class of View. Generally, you’ll be using this rather than sub-classing View directly. The doctype argument is case- and underscore-insensitive, and valid arguments are names of View subclasses that are inside the View namespace.
44 45 46 47 48 49 50 51 |
# File 'lib/hoshi/view.rb', line 44 def self.[] doctype doctype = doctype.to_s.downcase.gsub('_', '') const_get(constants.find { |c| cl = const_get c (cl.ancestors.include?(self) && c.to_s.downcase == doctype) rescue false }) rescue nil end |
.build(*args, &block) ⇒ Object
Create and render a view via a block.
85 86 87 88 89 |
# File 'lib/hoshi/view.rb', line 85 def self.build(*args, &block) c = new(*args) c.instance_eval(&block) c.render end |
.content_type ⇒ Object
This is overridden in HTML/XHTML, and you’ll definitely want to override it if you subclass View directly.
93 94 95 |
# File 'lib/hoshi/view.rb', line 93 def self.content_type 'application/octet-stream' end |
.dtd!(dtd) ⇒ Object
Sets the doctype declaration for this class.
54 55 56 57 |
# File 'lib/hoshi/view.rb', line 54 def self.dtd! dtd dtd += "\n" define_method(:doctype) { append! dtd } end |
.open_tags(*names) ⇒ Object
A short-hand for creating multiple tags that are left open.
31 32 33 |
# File 'lib/hoshi/view.rb', line 31 def self. *names names.map { |n| tag n, :none } end |
.permissive! ⇒ Object
Free-form tags. Basically, dynamic tag creation by method_missing.
64 65 66 |
# File 'lib/hoshi/view.rb', line 64 def self.permissive! @permissive = true end |
.permissive? ⇒ Boolean
Returns true if we add tags to this class on the fly.
69 70 71 |
# File 'lib/hoshi/view.rb', line 69 def self.permissive? @permissive end |
.self_closing_tags(*names) ⇒ Object
35 36 37 |
# File 'lib/hoshi/view.rb', line 35 def self. *names names.map { |n| tag n, :self } end |
.strict! ⇒ Object
Only the tags already specified are allowed. No dynamic tag creation. This is the default.
75 76 77 |
# File 'lib/hoshi/view.rb', line 75 def self.strict! @permissive = false end |
.strict? ⇒ Boolean
Returns true if we do not add tags to the class on the fly.
80 81 82 |
# File 'lib/hoshi/view.rb', line 80 def self.strict? !permissive? end |
.tag(name, close_type = nil) ⇒ Object
This method is a fallback for pre-1.8.7 Ruby; if a syntax error is encountered when hoshi/view.rb tries to load hoshi/view-tag.rb, this file is loaded. I have really been trying to avoid eval()ing strings (for religious reasons), but have to make this concession.
10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/hoshi/view-tag.rb', line 10 def self.tag(name, close_type = nil) define_method(name) { |*opts,&b| if b tag name, close_type, *opts, &b else tag name, close_type, *opts end } # Inline tags. define_method("_#{name}") { |*opts| _tag name, close_type, *opts } end |
.tags(*names) ⇒ Object
A short-hand for creating multiple tags via View.tag. For tags that do not require closing, see View.open_tags.
26 27 28 |
# File 'lib/hoshi/view.rb', line 26 def self. *names names.map &method(:tag) end |
Instance Method Details
#_tag(tname, close_type = nil, inside = '', opts = {}) ⇒ Object
An inline tag; it just returns a string rather than updating the view object in place. Useful for things like p “Here is a paragraph and a #‘link’, :href => ‘/’.”
144 145 146 147 |
# File 'lib/hoshi/view.rb', line 144 def _tag(tname, close_type = nil, inside = '', opts = {}) t = Tag.new(tname, close_type) t.render(inside, opts) end |
#append!(x) ⇒ Object
Appends something to the document. The comment, decl, and various tag methods call this.
151 152 153 154 |
# File 'lib/hoshi/view.rb', line 151 def append! x current << x x end |
#clear! ⇒ Object
Clears the current state of this view.
105 106 107 108 |
# File 'lib/hoshi/view.rb', line 105 def clear! self.tree = [] self.current = tree end |
#comment(*a) ⇒ Object
Adds a comment.
111 112 113 114 115 116 117 |
# File 'lib/hoshi/view.rb', line 111 def comment(*a) if a.include?('--') raise ValidationError, "Comments can't include '--'." else append! "<!-- #{a} -->" end end |
#doc(&b) ⇒ Object
If you’re tired of typing “doctypenhtml” every single time.
157 158 159 160 |
# File 'lib/hoshi/view.rb', line 157 def doc &b doctype html &b end |
#doctype ⇒ Object
58 59 60 61 |
# File 'lib/hoshi/view.rb', line 58 def doctype comment "No doctype defined; are you sub-classing View directly " \ "and not calling dtd!()?" end |
#entity(e) ⇒ Object
119 120 121 |
# File 'lib/hoshi/view.rb', line 119 def entity e raw "&#{e};" end |
#raw(*things) ⇒ Object
Appends one or more non-escaped strings to the document.
169 170 171 |
# File 'lib/hoshi/view.rb', line 169 def raw *things append! things.join end |
#render ⇒ Object
Returns the string representation of the document. This is what you want to eventually call.
175 176 177 |
# File 'lib/hoshi/view.rb', line 175 def render tree.flatten.map(&:to_s).join end |
#render_cgi(extra_headers = {}) ⇒ Object
Prints the string representation of the docutment, with HTTP headers. Useful for one-off CGI scripts. Takes an optional hash argument for headers (Content-Type and Status are set by default). See CGI#header for information on how the header hash should look.
183 184 185 186 187 188 189 190 |
# File 'lib/hoshi/view.rb', line 183 def render_cgi(extra_headers = {}) h = { 'type' => self.class.content_type, 'status' => 'OK', }.merge(extra_headers) CGI.new.out(h) { render } end |
#safe(*things) ⇒ Object
Turns things in to strings, properly escapes them, and appends them to the document.
164 165 166 |
# File 'lib/hoshi/view.rb', line 164 def safe *things append! CGI.escapeHTML(things.map(&:to_s).join("\n")) end |
#tag(tname, close_type = nil, *opts, &b) ⇒ Object
Appends a tag to the current document, for when a tag is only needed once or has a name that is not a valid method name.
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/hoshi/view.rb', line 125 def tag(tname, close_type = nil, *opts, &b) t = Tag.new(tname, close_type) if b old, self.current = current, [] # These two lines let you do 'asdf { "jkl" }' like Markaby. r = b.call current << r.to_s if current.empty? inside, self.current = current.map(&:to_s).join, old elsif opts.first.kind_of? String inside = CGI.escapeHTML(opts.shift) end append! t.render(inside, opts.first || {}) end |