class ActionView::Base
code}[github.com/jimweirich/builder].
For more information on Builder please consult the {source
end
end
end
end
xml.tag!(“dc:creator”, item.author_name) if item_has_creator?(item)
xml.link(@person.firm.account.url + @recent_items.url(item))
xml.guid(@person.firm.account.url + @recent_items.url(item))
xml.pubDate(item_pubDate(item))
xml.description(item_description(item)) if item_description(item)
xml.title(item_title(item))
xml.item do
@recent_items.each do |item|
xml.ttl “40”
xml.language “en-us”
xml.description “Basecamp: Recent items”
xml.link(@url)
xml.title(@feed_title)
xml.channel do
xml.rss(“version” => “2.0”, “xmlns:dc” => “purl.org/dc/elements/1.1/”) do
Here is a full-length RSS example actually used on Basecamp:
</div>
<p>A product of Danish Design during the Winter of ‘79…</p>
<h1>David Heinemeier Hansson</h1>
<div>
would produce something like:
end
xml.p(@person.bio)
xml.h1(@person.name)
xml.div do
Any method with a block will be treated as an XML markup tag with nested markup in the block. For example, the following:
# NOTE: order of attributes is not specified.
xml.target(“name” => “compile”, “option” => “fast”) # => <target option=“fast” name=“compile”>
xml.a(“A Link”, “href” => “onestepback.org”) # => <a href=“onestepback.org”>A Link</a>
xml.em { xml.b(“emph & bold”) } # => emph & bold
xml.em(“emphasized”) # => emphasized
Here are some basic examples:
named xml
is automatically made available to templates with a .builder
extension.
Builder templates are a more programmatic alternative to ERB. They are especially useful for generating XML content. An XmlMarkup object
== Builder
Rails will check the file’s modification time and recompile it in development mode.
By default, Rails will compile each template to a method in order to render it. When you alter a template,
=== Template cachingdefined? headline
to first check if the variable has been assigned before using it.
This is useful in cases where you aren’t sure if the local variable has been assigned. Alternatively, you could also use
Headline: <%= local_assigns %>
variables as:
The local variables passed to sub templates can be accessed as a hash using the local_assigns
hash. This lets you access the
First name: <%= person.first_name %>
Headline: <%= headline %>
These can now be accessed in application/header
with:
<%= render “application/header”, { headline: “Welcome”, person: person } %>
You can pass local variables to sub templates by using a hash with the variable names as keys and the objects as values:
=== Passing local variables to sub templates
<title><%= @page_title %></title>
Now the header can pick up on the @page_title
variable and use it for outputting a title tag:
<%= render “application/header” %>
<% @page_title = “A Wonderful Hello” %>
variables defined using the regular embedding tags. Like this:
But you don’t have to restrict yourself to static includes. Templates can share variables amongst themselves by using instance
result of the rendering. The output embedding writes it to the current template.
As you see, we use the output embeddings for the render methods. The render call itself will just return a string holding the
<%= render “application/footer” %>
Something really specific and terrific
<%= render “application/header” %>
classic example is the use of a header and footer (even though the Action Pack-way would be to use Layouts):
Using sub templates allows you to sidestep tedious replication and extract common display structures in shared templates. The
=== Using sub templates
Note however that <%= %>
and <%= -%>
are different: only the latter removes trailing whitespaces.
including the trailing newline. <% %>
and <%- -%>
are the same.
When on a line that only contains whitespaces except for the tag, <% %>
suppresses leading and trailing whitespace,
If you absolutely must write from within a function use concat
.
Hi, Mr. <% puts “Frodo” %>
<%# WRONG %>
is not just a usage suggestion. Regular output functions like print or puts won’t work with ERB templates. So this would be wrong:
The loop is set up in regular embedding tags <% %>
, and the name is written using the output embedding tag <%= %>
. Note that this
<% end %>
Name: <%= person.name %><br/>
<% @people.each do |person| %>
Names of all the people
following loop for names:
You trigger ERB by using embeddings such as <% %>
, <% -%>
, and <%= %>
. The <%= %>
tag set is used when you want output. Consider the
== ERB
If the template file has a .builder
extension, then Jim Weirich’s Builder::XmlMarkup library is used.
template system which can embed Ruby into an HTML document.
If the template file has a .erb
extension, then it uses the erubi[https://rubygems.org/gems/erubi]
Action View templates can be written in several ways.
= Action View Base
:nodoc:
def self.empty
def self.empty with_view_paths([]) end
def self.with_context(context, assigns = {}, controller = nil)
def self.with_context(context, assigns = {}, controller = nil) new context, assigns, controller end
def self.with_view_paths(view_paths, assigns = {}, controller = nil)
def self.with_view_paths(view_paths, assigns = {}, controller = nil) with_context ActionView::LookupContext.new(view_paths), assigns, controller end
def _run(method, template, locals, buffer, add_to_stack: true, has_strict_locals: false, &block)
def _run(method, template, locals, buffer, add_to_stack: true, has_strict_locals: false, &block) _old_output_buffer, _old_virtual_path, _old_template = @output_buffer, @virtual_path, @current_template @current_template = template if add_to_stack @output_buffer = buffer if has_strict_locals begin public_send(method, buffer, **locals, &block) rescue ArgumentError => argument_error raise( ArgumentError, argument_error. message. gsub("unknown keyword:", "unknown local:"). gsub("missing keyword:", "missing local:"). gsub("no keywords accepted", "no locals accepted") ) end else public_send(method, locals, buffer, &block) end ensure @output_buffer, @virtual_path, @current_template = _old_output_buffer, _old_virtual_path, _old_template end
def assign(new_assigns) # :nodoc:
def assign(new_assigns) # :nodoc: @_assigns = new_assigns new_assigns.each { |key, value| instance_variable_set("@#{key}", value) } end
def cache_template_loading
def cache_template_loading ActionView::Resolver.caching? end
def cache_template_loading=(value)
def cache_template_loading=(value) ActionView::Resolver.caching = value end
def changed?(other) # :nodoc:
def changed?(other) # :nodoc: compiled_method_container != other.compiled_method_container end
def compiled_method_container
def compiled_method_container raise NotImplementedError, <<~msg.squish Subclasses of ActionView::Base must implement `compiled_method_container` or use the class method `with_empty_template_cache` for constructing an ActionView::Base subclass that has an empty cache. msg end
def in_rendering_context(options)
def in_rendering_context(options) old_view_renderer = @view_renderer old_lookup_context = @lookup_context if !lookup_context.html_fallback_for_js && options[:formats] formats = Array(options[:formats]) if formats == [:js] formats << :html end @lookup_context = lookup_context.with_prepended_formats(formats) @view_renderer = ActionView::Renderer.new @lookup_context end yield @view_renderer ensure @view_renderer = old_view_renderer @lookup_context = old_lookup_context end
def initialize(lookup_context, assigns, controller) # :nodoc:
def initialize(lookup_context, assigns, controller) # :nodoc: @_config = ActiveSupport::InheritableOptions.new @lookup_context = lookup_context @view_renderer = ActionView::Renderer.new @lookup_context @current_template = nil assign_controller(controller) _prepare_context super() # Assigns must be called last to minimize the number of shapes assign(assigns) end
def inspect
def inspect "#<ActionView::Base:#{'%#016x' % (object_id << 1)}>" end
def with_empty_template_cache # :nodoc:
def with_empty_template_cache # :nodoc: subclass = Class.new(self) { # We can't implement these as self.class because subclasses will # share the same template cache as superclasses, so "changed?" won't work # correctly. define_method(:compiled_method_container) { subclass } define_singleton_method(:compiled_method_container) { subclass } def inspect "#<ActionView::Base:#{'%#016x' % (object_id << 1)}>" end } end
def xss_safe? # :nodoc:
def xss_safe? # :nodoc: true end