Ticket #7921: actionview_base_docs.diff
| File actionview_base_docs.diff, 25.4 kB (added by jeremymcanally, 2 years ago) |
|---|
-
actionpack/lib/action_view/base.rb
old new 4 4 class ActionViewError < StandardError #:nodoc: 5 5 end 6 6 7 # Action View templates can be written in three ways. If the template file has a +.erb+ (or +.rhtml+) extension then it uses a mixture of ERb 8 # (included in Ruby) and HTML. If the template file has a +.builder+ (or +.rxml+) extension then Jim Weirich's Builder::XmlMarkup library is used. 9 # If the template file has a +.rjs+ extension then it will use ActionView::Helpers::PrototypeHelper::JavaScriptGenerator. 7 # ActionView is the view portion of Rails' model-view-controller architecture; along with ActionController, it handles the response to 8 # the client, whether it's XML, HTML, JavaScript, or otherwise. ActionView's primary job is to render templates for actions. 9 # By default, these templates can be one of three types: ERb for HTML output, Builder for XML output, and RJS for JavaScript. 10 # ERb template files have a <tt>.erb</tt> (or <tt>.rhtml</tt>) extension and use a mixture of ERb (Embedded Ruby, which is included in the Ruby 11 # distribution) and HTML. Builder template files have a <tt>.builder</tt> (or <tt>.rxml</tt>) extension, and are handled by Jim Weirich's 12 # Builder::XmlMarkup library. RJS template files have an <tt>.rjs</tt> extension and use ActionView::Helpers::PrototypeHelper::JavaScriptGenerator 13 # to render their output. 10 14 # 11 # = ERb 15 # == Template Types 16 # Each template type has its own syntax and way of doing things, so we'll look at each one separately. 17 # 18 # === ERb 19 # ERb templates are the most common templates for Rails applications since they generate HTML. ERb templates are essentially HTML templates 20 # with Ruby sprinkled around inside of special tags. These tags allow you to interpolate Ruby code values and flow control into your template. 21 # The first set of these tags are <% %> and <% -%>; these tags, typically used for control structures or "non-output" code, allow you to execute 22 # Ruby code without displaying any output. For example, an if statement is typically a construct where the output (true or false) is not desired. 12 23 # 13 # You trigger ERb by using embeddings such as <% %>, <% -%>, and <%= %>. The <%= %> tag set is used when you want output. Consider the 14 # following loop for names: 15 # 16 # <b>Names of all the people</b> 17 # <% for person in @people %> 18 # Name: <%= person.name %><br/> 24 # <% if person.name != "Frodo" %> 25 # You are not Mr. Frodo! 19 26 # <% end %> 20 27 # 21 # The loop is setup in regular embedding tags <% %> and the name is written using the output embedding tag <%= %>. Note that this 22 # is not just a usage suggestion. Regular output functions like print or puts won't work with ERb templates. So this would be wrong: 28 # The Ruby code itself will not yield any output, but if the person.name variable isn't "Frodo," then "You are not Mr. Frodo!" is displayed. 29 # Just like in normal Ruby code, control structures will execute or output whatever is in the executed branch. For example, if you wanted to 30 # display an "X" for each person logged into your website, you could do something like the following. 23 31 # 24 # Hi, Mr. <% puts "Frodo" %> 32 # <% for user in all_logged_in_users %> 33 # X 34 # <% end %> 25 35 # 26 # If you absolutely must write from within a function, you can use the TextHelper#concat 36 # So if you have 5 logged in users, the page should display "XXXXX". %- and -%> suppress leading and trailing whitespace, 37 # including the trailing newline, and can be used interchangeably with <% and %>. 27 38 # 28 # <%- and -%> suppress leading and trailing whitespace, including the trailing newline, and can be used interchangeably with <% and %>. 39 # If you do want to display output, then you need to use the <%= %> tag. This will display the return value of the code inside of the 40 # tag. Consider the following loop for names: 29 41 # 30 # == Using sub templates 42 # <b>Names of all the people</b> 43 # <% for person in @people %> 44 # Name: <%= person.name %><br/> 45 # <% end %> 31 46 # 32 # Using sub templates allows you to sidestep tedious replication and extract common display structures in shared templates. The 33 # classic example is the use of a header and footer (even though the Action Pack-way would be to use Layouts): 47 # The loop is setup in regular embedding tags <% %>, but the name is written using the output tag: <%= %>. For each iteration, the page 48 # should now display a person's name. Note that this is not just a usage suggestion. Regular output functions like print or puts won't 49 # work with ERb templates. So this would be wrong: 34 50 # 35 # <%= render "shared/header" %> 36 # Something really specific and terrific 37 # <%= render "shared/footer" %> 51 # Hi, Mr. <% puts "Frodo" %> 38 52 # 39 # As you see, we use the output embeddings for the render methods. The render call itself will just return a string holding the 40 # result of the rendering. The output embedding writes it to the current template. 53 # If you absolutely must write from within a method, you can use the TextHelper#concat. Otherwise, output will come from the last used value of the block 54 # of code inside the tag or the return value of the block or method that you call. For example, the image_tag is a helper method that lets you easily link to 55 # images in your public/images folder. 41 56 # 42 # But you don't have to restrict yourself to static includes. Templates can share variables amongst themselves by using instance 43 # variables defined using the regular embedding tags. Like this: 44 # 45 # <% @page_title = "A Wonderful Hello" %> 46 # <%= render "shared/header" %> 47 # 48 # Now the header can pick up on the @page_title variable and use it for outputting a title tag: 49 # 50 # <title><%= @page_title %></title> 51 # 52 # == Passing local variables to sub templates 57 # <%= image_tag 'avatar.jpg' %> 53 58 # 54 # You can pass local variables to sub templates by using a hash with the variable names as keys and the objects as values: 59 # Now you should have an HTML <img> tag that links to avatar.jpg in your public/images folder. 60 # 61 # === Builder 55 62 # 56 # <%= render "shared/header", { :headline => "Welcome", :person => person } %> 57 # 58 # These can now be accessed in shared/header with: 59 # 60 # Headline: <%= headline %> 61 # First name: <%= person.first_name %> 62 # 63 # If you need to find out whether a certain local variable has been assigned a value in a particular render call, 64 # you need to use the following pattern: 65 # 66 # <% if local_assigns.has_key? :headline %> 67 # Headline: <%= headline %> 68 # <% end %> 69 # 70 # Testing using <tt>defined? headline</tt> will not work. This is an implementation restriction. 71 # 72 # == Template caching 73 # 74 # By default, Rails will compile each template to a method in order to render it. When you alter a template, Rails will 75 # check the file's modification time and recompile it. 76 # 77 # == Builder 78 # 79 # Builder templates are a more programmatic alternative to ERb. They are especially useful for generating XML content. An +XmlMarkup+ object 80 # named +xml+ is automatically made available to templates with a +.builder+ extension. 81 # 63 # Builder templates are a more programmatic alternative to ERb. They can generate HTML, but they are especially useful for generating XML 64 # content. An <tt>XmlMarkup</tt> object named <tt>xml</tt> is automatically made available to templates with a <tt>.builder</tt> or <tt>.rxml</tt> extension, which 65 # you can call methods on that are named for tags, providing parameters for their content and attributes and blocks for their child nodes. 82 66 # Here are some basic examples: 83 67 # 84 68 # xml.em("emphasized") # => <em>emphasized</em> … … 86 70 # xml.a("A Link", "href"=>"http://onestepback.org") # => <a href="http://onestepback.org">A Link</a> 87 71 # xml.target("name"=>"compile", "option"=>"fast") # => <target option="fast" name="compile"\> 88 72 # # NOTE: order of attributes is not specified. 73 # xml.tag!("dc:creator", "My Name") # => <dc:creator>My Name</dc:creator> 89 74 # 90 # Any method with a block will be treated as an XML markup tag with nested markup in the block. For example, the following: 75 # Note the em method generated an em tag, the a method an a tag, and so on. This uses method_missing, so there isn't a single "set" of 76 # tags you can generate: you could have a rubyonrails tag or whatever (this is XML you know!). You can also use the tag method to generate 77 # tags that would be invalid method names for Ruby (e.g., dc:creator). Any method called with a block will be treated as an XML markup 78 # tag with nested markup in the block. For example, the following: 91 79 # 92 80 # xml.div { 93 81 # xml.h1(@person.name) … … 101 89 # <p>A product of Danish Design during the Winter of '79...</p> 102 90 # </div> 103 91 # 104 # A full-length RSS example actually used on Basecamp: 92 # As was mentioned before, Builder works to generate HTML, but it's excellent for generating XML content. For example, 93 # below is a full-length RSS generator actually used in Basecamp: 105 94 # 106 95 # xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/") do 107 96 # xml.channel do … … 125 114 # end 126 115 # end 127 116 # 128 # More builder documentation can be found at http://builder.rubyforge.org.117 # This script generates something like the following: 129 118 # 130 # == JavaScriptGenerator 119 # <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"> 120 # <channel> 121 # <title>My Feed</title> 122 # <link>feed://yourproject.projectpath.com/feed/recent_items_rss</link> 123 # <description>Basecamp: Recent items</description> 124 # <language>en-us</language> 125 # <ttl>40</ttl> 126 # <item> 127 # <title>My Item</title> 128 # <description>This is my item. Back in it glory.</description> 129 # <pubDate>Fri, 26 Jan 2007 00:17:58 +0000</pubDate> 130 # <guid>basecamp.0e0ar1a.TodoItem.a01fd35</guid> 131 # <link>http://yourproject.projectpath.com/I938292</link> 132 # <dc:creator>The Author</dc:creator> 133 # </item> 134 # </channel> 135 # </rss> 131 136 # 132 # JavaScriptGenerator templates end in +.rjs+. Unlike conventional templates which are used to 133 # render the results of an action, these templates generate instructions on how to modify an already rendered page. This makes it easy to 134 # modify multiple elements on your page in one declarative Ajax response. Actions with these templates are called in the background with Ajax 135 # and make updates to the page where the request originated from. 137 # Builder doesn't just generate RSS, though. It can generate ATOM, XML configuration files, or any other XML file. More 138 # Builder documentation can be found at http://builder.rubyforge.org. 139 # 140 # === RJS (JavaScriptGenerator) 141 # 142 # JavaScriptGenerator templates end in <tt>.rjs</tt>. Unlike conventional templates which are used to 143 # render the results of an action, these templates generate JavaScript instructions for modifying an already rendered page. 144 # Actions with these templates are called in the background with Ajax and make updates to the page where the request originated from. 145 # This makes it easy to modify multiple elements on your page in one declarative Ajax response. This is accomplished through methods 146 # such as replace_html and visual_effect on the JavaScriptGenerator class. 136 147 # 137 # An instance of the JavaScriptGenerator object named +page+ is automatically made available to your template, which is implicitly wrapped in an ActionView::Helpers::PrototypeHelper#update_page block. 148 # An instance of the JavaScriptGenerator object named <tt>page</tt> is automatically made available to your template, which is 149 # implicitly wrapped in an ActionView::Helpers::PrototypeHelper#update_page block. When an .rjs action is called with 150 # <tt>link_to_remote</tt>, the generated JavaScript is automatically evaluated. Example: 138 151 # 139 # When an .rjs action is called with +link_to_remote+, the generated JavaScript is automatically evaluated. Example:140 #141 152 # link_to_remote :url => {:action => 'delete'} 142 153 # 143 # The subsequently rendered +delete.rjs+might look like:154 # The subsequently rendered <tt>delete.rjs</tt> might look like: 144 155 # 145 156 # page.replace_html 'sidebar', :partial => 'sidebar' 146 157 # page.remove "person-#{@person.id}" 147 158 # page.visual_effect :highlight, 'user-list' 148 159 # 149 # This refreshes the sidebar, removes a person element and highlights the user list. 160 # This refreshes the sidebar, removes a person element and highlights the user list. For more information and detailed usage, 161 # see the ActionView::Helpers::PrototypeHelper::JavaScriptGenerator documentation. 162 # 163 # == Layouts, partials, and template sharing 164 # In the interest of keeping your views DRY, Rails offers a few constructs to help you reuse view code: layouts, partials, and shared 165 # templates. Layouts # provide a consistent look for actions by providing a header and/or footer that can be shared. Partials 166 # allow you to sidestep tedious replication and extract common display structures into shared components. Rails also allows you to 167 # share templates and use them inside of other templates. 168 # 169 # === Layouts 170 # If you wanted to create a consistent header and footer, you might think that including two separate templates would be the best 171 # course of action (like the following). 172 # 173 # <%= render "shared/header" %> 174 # Something really specific and terrific 175 # <%= render "shared/footer" %> 176 # 177 # As you see, we use the output embeddings for the render methods. The render call itself will just return a string holding the 178 # result of the template's rendering that is then written to the current template's output. But Rails offers a better way to 179 # accomplish this called a layout. Layouts live in the app/views/layouts/ folder. They can be specified on a controller's actions 180 # by using the layout method. 150 181 # 151 # See the ActionView::Helpers::PrototypeHelper::JavaScriptGenerator documentation for more details. 182 # class MyController < ApplicationController 183 # layout "my_layout" 184 # end 185 # 186 # The above example looks for app/views/layouts/my_layout.rhtml (or .erb, .builder, or .rxml) for use as a layout. Inside that file 187 # you should put something like the following. 188 # 189 # <html> 190 # <head> 191 # <title>My Own Application</title> 192 # </head> 193 # 194 # <body> 195 # <h1>Welcome</h1> 196 # <%= yield %> 197 # </body> 198 # </html> 199 # 200 # Now every action on MyController will have the page title "My Own Application" and show "Welcome" at the top of the page in large 201 # letters. 202 # 203 # If a layout is named for a controller (e.g., UsersController and app/views/layouts/users.erb), then every 204 # action on that controller will use that layout without any specification needed in the controller. For more detailed information, see the 205 # ActionController::Layout::ClassMethods documentation. 206 # 207 # === Partials 208 # Partials allow you to extract commonly pieces of a template into a sharable component. This is useful for elements such login forms, 209 # comment forms, ads, and so on. So, for example, let's say you wanted to include your login form on every page, you would do something 210 # like the following in file called _login.erb in your controller's view directory. 211 # 212 # <% form_tag do -%> 213 # Login: <%= text_field_tag 'login' %><br /> 214 # Password: <%= password_field_tag 'password' %><br /> 215 # <%= submit_tag 'Log in' %> 216 # <% end -%> 217 # 218 # This partial uses a few helper methods covered below to generate a form; including this in a page like so... 219 # 220 # <%= render :partial => 'login' %> 221 # 222 # will render it on that page. You can now use this line on a number of pages; if you update _login.erb, then each page that renders that 223 # partial will also be updated. See the ActionView::Partials documentation for more details and information on passing variables into 224 # partials. 225 # 226 # === Sharing templates (subtemplates) 227 # Rails lets you share template among controllers; this mechanism is very similar to a partial, with the only different being variable scope (covered 228 # below). You can share a template by simply calling render with a template path in your view, like this: 229 # 230 # <%= render :file => "my_shared/login" %> 231 # 232 # This will render the template app/views/my_shared/login.erb in the current template as if it were added to the original template instance, which 233 # means it has access to all instance variables of the parent template (but not the local variables). 234 # 235 # ==== Using variables in subtemplates 236 # Templates can share variables amongst themselves by using instance variables defined using the regular embedding tags. Like this: 237 # 238 # <% @page_title = "A Wonderful Hello" %> 239 # <%= render "shared/header" %> 240 # 241 # Now the header can pick up on the @page_title variable and use it for outputting a title tag: 242 # 243 # <title><%= @page_title %></title> 244 # 245 # You can also pass local variables to sub templates by using a hash with the variable names as keys and the objects as values. For example, 246 # maybe you'd like to pass in the current logged in user. 247 # 248 # <%= render "shared/header", { :person => current_user } %> 249 # 250 # These can now be accessed in shared/header with: 251 # 252 # Hello, <%= person.first_name %>! We're glad you're logged in as <%= person.login %>. 253 # 254 # If you need to find out whether a certain local variable has been assigned a value in a particular render call, 255 # you need to use the following pattern: 256 # 257 # <% if local_assigns.has_key? :person %> 258 # Hello, <%= person.first_name %>! We're glad you're logged in as <%= person.login %>. 259 # <% end %> 260 # 261 # Testing using <tt>defined? headline</tt> will not work, due to an implementation restriction. 262 # 263 # == Helpers 264 # Views (and especially template-based views) are meant to have as little application logic in them as possible, but sometimes 265 # there's a little bit of logic that you need. Maybe you need to pull something from the database or render something takes a lot 266 # of lines of code that don't really belong in the view. This is where helpers are, well, helpful. They allow you to "cheat" a little 267 # bit on the separation of MVC and expose some application logic to your views. Think of helpers as standing over the gap between 268 # controller and view. 269 # 270 # Every controller, when generated, gives you a helper to go along with it in the app/helpers/ directory. So for a controller 271 # StoreController you would have store_helper.rb. Inside, you can put any sort of logic the views may need to get to. For example, 272 # let's say you're building a store and maybe you need to calculate a total and get the right formatting for prices. You could do 273 # that everywhere in the view that you need it (e.g., the item page, the cart sidebar, the total page, and so on), or you could create 274 # a method <tt>format_price</tt> in a helper. 275 # 276 # === Built-in helpers 277 # Rails offers a large range of built-in helpers also. Below is a full list with a short description; check out their documentation for 278 # for information. 279 # 280 # - ActionView::Helpers::ActiveRecordHelper - Makes it easier to create forms for ActiveRecord objects 281 # - ActionView::Helpers::AssetTagHelper - Helps with linking to assets (i.e., images and javascripts) in Rails applications 282 # - ActionView::Helpers::BenchmarkHelper - Aids in benchmarking Rails actions 283 # - ActionView::Helpers::CacheHelper - Makes caching of fragments simple 284 # - ActionView::Helpers::CaptureHelper - Captures markup and code results for later use 285 # - ActionView::Helpers::DateHelper - Create select and option tags for date selection in forms 286 # - ActionView::Helpers::DebugHelper - Provides a set of methods for making it easier to locate problems in your Rails application. 287 # - ActionView::Helpers::FormHelper - Makes creating forms based on objects in your views much easier 288 # - ActionView::Helpers::FormOptionsHelper - Provides a number of methods for turning different kinds of containers into a set of option tags 289 # - ActionView::Helpers::FormTagHelper - Create free-form forms in your views 290 # - ActionView::Helpers::JavaScriptHelper - Provides functionality for working with JavaScript in your views 291 # - ActionView::Helpers::JavaScriptMacrosHelper - Provides a set of helpers for creating JavaScript macros that rely on and often bundle methods from JavaScriptHelper into larger units 292 # - ActionView::Helpers::NumberHelper - Provides methods for converting a numbers into formatted strings 293 # - ActionView::Helpers::PaginationHelper - Provides methods for linking to ActionController::Pagination objects 294 # - ActionView::Helpers::PrototypeHelper - Provides a set of helpers for calling Prototype[http://www.prototypejs.org/] JavaScript functions 295 # - ActionView::Helpers::ScriptaculousHelper - Provides a set of helpers for calling Scriptaculous[http://scrip.taculo.us/] visual effects 296 # - ActionView::Helpers::TagHelper - Helps generate HTML tags programmatically when you canât use a Builder 297 # - ActionView::Helpers::TextHelper - Provides a set of methods for filtering, formatting and transforming strings that can reduce the amount of inline Ruby code in your view 298 # - ActionView::Helpers::UrlHelper - Easy linking and getting of URLs that depend on the controller and action 299 # 300 # == Caching 301 # By default, Rails will compile each template to a method in order to render it. When you alter a template, Rails will 302 # check the file's modification time and recompile it. If, after compilation, Rails determines nothing has changed by using an 303 # ETag[http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19] header, it will send a "304 Not Modified" response to the 304 # user so you don't waste bandwidth and resources sending the page to them again. 305 # 152 306 class Base 153 307 include ERB::Util 154 308 … … 228 382 # takes the contents of the template to render as well as the Hash of 229 383 # local assigns available to the template. The #render method ought to 230 384 # return the rendered template as a string. 385 # 386 # ==== Example 387 # 388 # Adding the <tt>PDF::Writer</tt> library by Austin Ziegler as a template 389 # handler is as simple as requiring the library, calling <tt>register_template_handler</tt>,... 390 # 391 # require 'pdf_render' 392 # ActionView::Base.register_template_handler 'rpdf', ActionView::PDFRender 393 # 394 # ...and then creating a handler as shown here[http://wiki.rubyonrails.org/rails/pages/HowtoGeneratePDFs]. 231 395 def self.register_template_handler(extension, klass) 232 396 @@template_handlers[extension] = klass 233 397 end … … 241 405 end 242 406 243 407 # Renders the template present at <tt>template_path</tt>. If <tt>use_full_path</tt> is set to true, 244 # it's relative to the view_pathsarray, otherwise it's absolute. The hash in <tt>local_assigns</tt>408 # it's relative to the <tt>view_paths</tt> array, otherwise it's absolute. The hash in <tt>local_assigns</tt> 245 409 # is made available as local variables. 410 # 411 # ==== Examples 412 # # Renders the view header.erb in the shared directory of app/views 413 # render_file "shared/header" 414 # 415 # # The false says the path to the template is absolute 416 # render_file "/var/www/rails_app/app/views/shared/header", false 417 # 418 # # Renders a template, passing in two local variables: user and date 419 # render_file "application/top", true, { 'user' => 'dhh@rubyonrails.com', 'date' => 'March 28th, 2007'} 246 420 def render_file(template_path, use_full_path = true, local_assigns = {}) #:nodoc: 247 421 @first_render ||= template_path 248 422 template_path_without_extension, template_extension = path_and_extension(template_path) … … 272 446 end 273 447 274 448 # Renders the template present at <tt>template_path</tt> (relative to the view_paths array). 275 # The hash in <tt>local_assigns</tt> is made available as local variables. 276 def render(options = {}, old_local_assigns = {}, &block) #:nodoc: 449 # The hash in <tt>local_assigns</tt> is made available as local variables. This method is used 450 # to render subtemplates. 451 # 452 # ==== Examples 453 # # Renders the view header.erb in the shared directory of app/views 454 # render "shared/header" 455 # 456 # # Renders a template, passing in two local variables: user and date 457 # render_file "application/top", { 'user' => 'dhh@rubyonrails.com', 'date' => 'March 28th, 2007'} 458 def render(options = {}, old_local_assigns = {}, &block) 277 459 if options.is_a?(String) 278 460 render_file(options, true, old_local_assigns) 279 461 elsif options == :update … … 307 489 # Render the provided template with the given local assigns. If the template has not been rendered with the provided 308 490 # local assigns yet, or if the template has been updated on disk, then the template will be compiled to a method. 309 491 # 310 311 492 # Either, but not both, of template and file_path may be nil. If file_path is given, the template 312 493 # will only be read if it has to be compiled. 313 494 #