Class: Hoshi::View
- Inherits:
-
Object
- Object
- Hoshi::View
- Defined in:
- lib/hoshi/view.rb,
lib/hoshi/view/svg.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 :html5
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, SVG, 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.
112 113 114 115 |
# File 'lib/hoshi/view.rb', line 112 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.
210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/hoshi/view.rb', line 210 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.
56 57 58 59 60 61 62 63 |
# File 'lib/hoshi/view.rb', line 56 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.
97 98 99 100 101 |
# File 'lib/hoshi/view.rb', line 97 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.
105 106 107 |
# File 'lib/hoshi/view.rb', line 105 def self.content_type 'application/octet-stream' end |
.dtd!(dtd) ⇒ Object
Sets the doctype declaration for this class.
66 67 68 69 |
# File 'lib/hoshi/view.rb', line 66 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.
43 44 45 |
# File 'lib/hoshi/view.rb', line 43 def self. *names names.map { |n| tag n, :none } end |
.permissive! ⇒ Object
Free-form tags. Basically, dynamic tag creation by method_missing.
76 77 78 |
# File 'lib/hoshi/view.rb', line 76 def self.permissive! @permissive = true end |
.permissive? ⇒ Boolean
Returns true if we add tags to this class on the fly.
81 82 83 |
# File 'lib/hoshi/view.rb', line 81 def self.permissive? @permissive end |
.self_closing_tags(*names) ⇒ Object
47 48 49 |
# File 'lib/hoshi/view.rb', line 47 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.
87 88 89 |
# File 'lib/hoshi/view.rb', line 87 def self.strict! @permissive = false end |
.strict? ⇒ Boolean
Returns true if we do not add tags to the class on the fly.
92 93 94 |
# File 'lib/hoshi/view.rb', line 92 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
24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/hoshi/view.rb', line 24 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.
38 39 40 |
# File 'lib/hoshi/view.rb', line 38 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 => ‘/’.”
161 162 163 164 |
# File 'lib/hoshi/view.rb', line 161 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.
168 169 170 171 |
# File 'lib/hoshi/view.rb', line 168 def append! x current << x x end |
#clear! ⇒ Object
Clears the current state of this view.
118 119 120 121 |
# File 'lib/hoshi/view.rb', line 118 def clear! self.tree = [] self.current = tree end |
#comment(*a) ⇒ Object
Adds a comment.
128 129 130 131 132 133 134 |
# File 'lib/hoshi/view.rb', line 128 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.
174 175 176 177 |
# File 'lib/hoshi/view.rb', line 174 def doc &b doctype html &b end |
#doctype ⇒ Object
70 71 72 73 |
# File 'lib/hoshi/view.rb', line 70 def doctype comment "No doctype defined; are you sub-classing View directly " \ "and not calling dtd!()?" end |
#entity(e) ⇒ Object
136 137 138 |
# File 'lib/hoshi/view.rb', line 136 def entity e raw "&#{e};" end |
#otag(*a) ⇒ Object
123 124 125 |
# File 'lib/hoshi/view.rb', line 123 def otag(*a) @tcache[a] ||= Tag.new(*a) end |
#raw(*things) ⇒ Object
Appends one or more non-escaped strings to the document.
186 187 188 |
# File 'lib/hoshi/view.rb', line 186 def raw *things append! things.join end |
#render ⇒ Object
Returns the string representation of the document. This is what you want to eventually call.
192 193 194 |
# File 'lib/hoshi/view.rb', line 192 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.
200 201 202 203 204 205 206 207 |
# File 'lib/hoshi/view.rb', line 200 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.
181 182 183 |
# File 'lib/hoshi/view.rb', line 181 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.
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/hoshi/view.rb', line 142 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 |