跳至內容 跳至搜尋

Action View 模板

命名空間
方法
E
I
L
M
N
R
S
T

常數

NONE = Object.new
 
STRICT_LOCALS_REGEX = /\#\s+locals:\s+\((.*)\)/
 

屬性

[R] format
[RW] frozen_string_literal
[R] handler
[R] identifier
[R] variable
[R] variant
[R] virtual_path

類別公開方法

mime_types_implementation=(implementation)

# File actionview/lib/action_view/template.rb, line 184
def mime_types_implementation=(implementation)
  # This method isn't thread-safe, but it's not supposed
  # to be called after initialization
  if self::Types != implementation
    remove_const(:Types)
    const_set(:Types, implementation)
  end
end

new(source, identifier, handler, locals:, format: nil, variant: nil, virtual_path: nil)

# File actionview/lib/action_view/template.rb, line 199
def initialize(source, identifier, handler, locals:, format: nil, variant: nil, virtual_path: nil)
  @source            = source.dup
  @identifier        = identifier
  @handler           = handler
  @compiled          = false
  @locals            = locals
  @virtual_path      = virtual_path

  @variable = if @virtual_path
    base = @virtual_path.end_with?("/") ? "" : ::File.basename(@virtual_path)
    base =~ /\A_?(.*?)(?:\.\w+)*\z/
    $1.to_sym
  end

  @format            = format
  @variant           = variant
  @compile_mutex     = Mutex.new
  @strict_locals     = NONE
  @strict_local_keys = nil
  @type              = nil
end

實例公開方法

encode!()

此方法負責正確設定來源的編碼。在此之前,我們假設來源是二進位制資料。如果沒有提供額外資訊,我們假設編碼與 `Encoding.default_external` 相同。

使用者也可以透過在模板第一行加入註釋(`# encoding: 編碼名稱`)來指定編碼。這適用於任何模板引擎,因為我們會在將來源傳遞給模板引擎之前處理掉編碼註釋,並在其位置留下一行空白行。

# File actionview/lib/action_view/template.rb, line 321
def encode!
  source = self.source

  return source unless source.encoding == Encoding::BINARY

  # Look for # encoding: *. If we find one, we'll encode the
  # String in that encoding, otherwise, we'll use the
  # default external encoding.
  if source.sub!(LEADING_ENCODING_REGEXP, "")
    encoding = magic_encoding = $1
  else
    encoding = Encoding.default_external
  end

  # Tag the source with the default external encoding
  # or the encoding specified in the file
  source.force_encoding(encoding)

  # If the user didn't specify an encoding, and the handler
  # handles encodings, we simply pass the String as is to
  # the handler (with the default_external tag)
  if !magic_encoding && @handler.respond_to?(:handles_encoding?) && @handler.handles_encoding?
    source
  # Otherwise, if the String is valid in the encoding,
  # encode immediately to default_internal. This means
  # that if a handler doesn't handle encodings, it will
  # always get Strings in the default_internal
  elsif source.valid_encoding?
    source.encode!
  # Otherwise, since the String is invalid in the encoding
  # specified, raise an exception
  else
    raise WrongEncodingError.new(source, encoding)
  end
end

inspect()

# File actionview/lib/action_view/template.rb, line 300
def inspect
  "#<#{self.class.name} #{short_identifier} locals=#{locals.inspect}>"
end

local_assigns

返回一個包含已定義局部變數的雜湊。

給定此子模板渲染

<%= render "application/header", { headline: "Welcome", person: person } %>

您可以在子模板中使用 `local_assigns` 來存取局部變數

local_assigns[:headline] # => "Welcome"

`local_assigns` 中的每個鍵都可用作局部變數

local_assigns[:headline] # => "Welcome"
headline                 # => "Welcome"

由於 `local_assigns` 是一個 `Hash`,它與 Ruby 3.1 的模式匹配賦值運算符相容

local_assigns => { headline:, **options }
headline                 # => "Welcome"
options                  # => {}

模式匹配賦值也支援變數重新命名

local_assigns => { headline: title }
title                    # => "Welcome"

如果模板引用了未作為 `locals: { ... }` `Hash` 的一部分傳遞到視圖中的變數,模板將引發 `ActionView::Template::Error`

<%# => raises ActionView::Template::Error %>
<% alerts.each do |alert| %>
  <p><%= alert %></p>
<% end %>

由於 `local_assigns` 返回一個 `Hash` 實例,您可以有條件地讀取變數,然後在鍵不是 `locals: { ... }` 選項的一部分時回退到預設值

<% local_assigns.fetch(:alerts, []).each do |alert| %>
  <p><%= alert %></p>
<% end %>

將 Ruby 3.1 的模式匹配賦值與 +Hash#with_defaults+ 的調用相結合,可以實現緊湊的局部變數賦值

<% local_assigns.with_defaults(alerts: []) => { headline:, alerts: } %>

<h1><%= headline %></h1>

<% alerts.each do |alert| %>
  <p><%= alert %></p>
<% end %>

預設情況下,模板將接受任何 `locals` 作為關鍵字參數,並將它們提供給 `local_assigns`。要限制模板將接受的 `local_assigns`,請添加 `locals:` 魔術註釋

<%# locals: (headline:, alerts: []) %>

<h1><%= headline %></h1>

<% alerts.each do |alert| %>
  <p><%= alert %></p>
<% end %>

在指南的Action View 概覽中閱讀有關嚴格局部變數的更多資訊。

# File actionview/lib/action_view/template.rb, line 165
eager_autoload do
  autoload :Error
  autoload :RawFile
  autoload :Renderable
  autoload :Handlers
  autoload :HTML
  autoload :Inline
  autoload :Types
  autoload :Sources
  autoload :Text
  autoload :Types
end

locals()

此模板已編譯或將要編譯的局部變數,如果這是嚴格局部變數模板,則為 nil。

# File actionview/lib/action_view/template.rb, line 223
def locals
  if strict_locals?
    nil
  else
    @locals
  end
end

render(view, locals, buffer = nil, implicit_locals: [], add_to_stack: true, &block)

渲染模板。如果模板尚未編譯,則在渲染之前完成編譯。

此方法被檢測為 “!render_template.action_view”。請注意,我們在此檢測中使用感叹號,因為您不想在生產環境中使用它。只有在監聽時才會變慢。

# File actionview/lib/action_view/template.rb, line 271
def render(view, locals, buffer = nil, implicit_locals: [], add_to_stack: true, &block)
  instrument_render_template do
    compile!(view)

    if strict_locals? && @strict_local_keys && !implicit_locals.empty?
      locals_to_ignore = implicit_locals - @strict_local_keys
      locals.except!(*locals_to_ignore)
    end

    if buffer
      view._run(method_name, self, locals, buffer, add_to_stack: add_to_stack, has_strict_locals: strict_locals?, &block)
      nil
    else
      result = view._run(method_name, self, locals, OutputBuffer.new, add_to_stack: add_to_stack, has_strict_locals: strict_locals?, &block)
      result.is_a?(OutputBuffer) ? result.to_s : result
    end
  end
rescue => e
  handle_render_error(view, e)
end

short_identifier()

# File actionview/lib/action_view/template.rb, line 296
def short_identifier
  @short_identifier ||= defined?(Rails.root) ? identifier.delete_prefix("#{Rails.root}/") : identifier
end

source()

# File actionview/lib/action_view/template.rb, line 304
def source
  @source.to_s
end

strict_locals!()

此方法負責將模板標記為具有嚴格的局部變數,這表示模板只能接受魔術註釋中定義的局部變數。例如,如果您的模板接受局部變數 `title` 和 `comment_count`,請將以下內容添加到您的模板檔案中

<%# locals: (title: "Default title", comment_count: 0) %>

嚴格的局部變數對於驗證模板參數和指定預設值很有用。

# File actionview/lib/action_view/template.rb, line 366
def strict_locals!
  if @strict_locals == NONE
    self.source.sub!(STRICT_LOCALS_REGEX, "")
    @strict_locals = $1

    return if @strict_locals.nil? # Magic comment not found

    @strict_locals = "**nil" if @strict_locals.blank?
  end

  @strict_locals
end

strict_locals?()

返回模板是否使用嚴格的局部變數。

# File actionview/lib/action_view/template.rb, line 380
def strict_locals?
  strict_locals!
end

supports_streaming?()

返回底層處理程序是否支援串流。如果是,則在開始渲染時**可以**傳遞串流緩衝區。

# File actionview/lib/action_view/template.rb, line 261
def supports_streaming?
  handler.respond_to?(:supports_streaming?) && handler.supports_streaming?
end

translate_location(backtrace_location, spot)

將 ErrorHighlight 返回的錯誤位置轉換為模板內正確的來源位置。

# File actionview/lib/action_view/template.rb, line 251
def translate_location(backtrace_location, spot)
  if handler.respond_to?(:translate_location)
    handler.translate_location(spot, backtrace_location, encode!) || spot
  else
    spot
  end
end

type()

# File actionview/lib/action_view/template.rb, line 292
def type
  @type ||= Types[format]
end

實例私有方法

instrument(action, &block)

# File actionview/lib/action_view/template.rb, line 578
def instrument(action, &block) # :doc:
  ActiveSupport::Notifications.instrument("#{action}.action_view", instrument_payload, &block)
end