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/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 creates an instance method for this view which appends a tag.
-
.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.
- #otag(*a) ⇒ Object
-
#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.
96 97 98 99 |
# File 'lib/hoshi/view.rb', line 96 def initialize @tcache = {} 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.
194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/hoshi/view.rb', line 194 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.
40 41 42 43 44 45 46 47 |
# File 'lib/hoshi/view.rb', line 40 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.
81 82 83 84 85 |
# File 'lib/hoshi/view.rb', line 81 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.
89 90 91 |
# File 'lib/hoshi/view.rb', line 89 def self.content_type 'application/octet-stream' end |
.dtd!(dtd) ⇒ Object
Sets the doctype declaration for this class.
50 51 52 53 |
# File 'lib/hoshi/view.rb', line 50 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.
27 28 29 |
# File 'lib/hoshi/view.rb', line 27 def self. *names names.map { |n| tag n, :none } end |
.permissive! ⇒ Object
Free-form tags. Basically, dynamic tag creation by method_missing.
60 61 62 |
# File 'lib/hoshi/view.rb', line 60 def self.permissive! @permissive = true end |
.permissive? ⇒ Boolean
Returns true if we add tags to this class on the fly.
65 66 67 |
# File 'lib/hoshi/view.rb', line 65 def self.permissive? @permissive end |
.self_closing_tags(*names) ⇒ Object
31 32 33 |
# File 'lib/hoshi/view.rb', line 31 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.
71 72 73 |
# File 'lib/hoshi/view.rb', line 71 def self.strict! @permissive = false end |
.strict? ⇒ Boolean
Returns true if we do not add tags to the class on the fly.
76 77 78 |
# File 'lib/hoshi/view.rb', line 76 def self.strict? !permissive? end |
.tag(name, close_type = nil) ⇒ Object
This creates an instance method for this view which appends a tag. Most of these are handled for you. The arguments to this method match those to Tag.new. See also View#permissive!. tag(‘h1’) def show_an_h1 h1 “I have been shown” end
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.
22 23 24 |
# File 'lib/hoshi/view.rb', line 22 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 => ‘/’.”
145 146 147 148 |
# File 'lib/hoshi/view.rb', line 145 def _tag(tname, close_type = nil, inside = '', opts = {}) t = otag(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.
152 153 154 155 |
# File 'lib/hoshi/view.rb', line 152 def append! x current << x x end |
#clear! ⇒ Object
Clears the current state of this view.
102 103 104 105 |
# File 'lib/hoshi/view.rb', line 102 def clear! self.tree = [] self.current = tree end |
#comment(*a) ⇒ Object
Adds a comment.
112 113 114 115 116 117 118 |
# File 'lib/hoshi/view.rb', line 112 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.
158 159 160 161 |
# File 'lib/hoshi/view.rb', line 158 def doc &b doctype html &b end |
#doctype ⇒ Object
54 55 56 57 |
# File 'lib/hoshi/view.rb', line 54 def doctype comment "No doctype defined; are you sub-classing View directly " \ "and not calling dtd!()?" end |
#entity(e) ⇒ Object
120 121 122 |
# File 'lib/hoshi/view.rb', line 120 def entity e raw "&#{e};" end |
#otag(*a) ⇒ Object
107 108 109 |
# File 'lib/hoshi/view.rb', line 107 def otag(*a) @tcache[a] ||= Tag.new(*a) end |
#raw(*things) ⇒ Object
Appends one or more non-escaped strings to the document.
170 171 172 |
# File 'lib/hoshi/view.rb', line 170 def raw *things append! things.join end |
#render ⇒ Object
Returns the string representation of the document. This is what you want to eventually call.
176 177 178 |
# File 'lib/hoshi/view.rb', line 176 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.
184 185 186 187 188 189 190 191 |
# File 'lib/hoshi/view.rb', line 184 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.
165 166 167 |
# File 'lib/hoshi/view.rb', line 165 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.
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/hoshi/view.rb', line 126 def tag(tname, close_type = nil, *opts, &b) t = otag(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 |