Techioz Blog

収量分野は何をするのですか?魔法はどのように作用するのでしょうか?

概要

<!DOCTYPE html>
<% provide(:title, "Home") %>
<html>
  <head>
    <title><%= full_title(yield(:title)) %></title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= debug(params) if Rails.env.development? %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>

解決策

yield はメソッドに渡されたブロックを呼び出すだけです。 ERB テンプレートはプレーンな Ruby コードにコンパイルされます。プロセス全体を説明するのは難しいですが、例を示します。

# render_example.rb

# you could see this method name in your layouts or templates:
#  
#   <%= __method__ %>
#
# it looks like this: _app_views_layouts_application_html_erb__1249814135074865580_182580
def application_layout
  "<html>"+
    "<title>"+
      yield(:title) +
    "</title>"+
    "<body>"+
      yield +
    "</body>"+
  "</html>"
end

# your template
def index_template
  content_for :title do
    "my title"
  end
  "content"
end

# to show how yield(:title) works
def content_for name
  @content_for ||= {}
  @content_for[name] = yield
end

def render
  template = index_template

  # this block is called when yield or yield(:title) is called 
  application_layout do |content|
    if content
      @content_for[content]
    else
      template
    end
  end
end

p render
$ ruby render_example.rb
"<html><title>my title</title><body>content</body></html>"

実際の application_layout でコンパイルされた erb コードがどのように見えるか知りたい場合は、次のようにします。

def _app_views_layouts_application_html_erb__2833155640507924630_37360(local_assigns, output_buffer)
  @virtual_path = "layouts/application";; @output_buffer.safe_append='<!DOCTYPE html>
  <html>
    <head>
      <title>Stackoverflow</title>
      <meta name="viewport" content="width=device-width,initial-scale=1">
      <link rel="icon" type="image/ico" href="favicon.ico">
      '.freeze; @output_buffer.append=( csrf_meta_tags ); @output_buffer.safe_append='
      '.freeze; @output_buffer.append=( csp_meta_tag ); @output_buffer.safe_append='
      '.freeze; @output_buffer.append=( stylesheet_link_tag "tailwind", "actiontext", "inter-font", "data-turbo-track": "reload" ); @output_buffer.safe_append='
      '.freeze; @output_buffer.append=( javascript_importmap_tags ); @output_buffer.safe_append='
  '.freeze;
  @output_buffer.safe_append='  </head>
    <body>
      <main class="container grid px-5 mx-auto mt-28">
        <div>
          '.freeze; @output_buffer.append=( yield ); @output_buffer.safe_append='
        </div>
      </main>
    </body>
  </html>
  '.freeze;
  @output_buffer
end