11

次のコードは、Ryan Bates のRailsCastsからのもので、ブログのフロント ページをカレンダーに変えて、記事が日にちのリンクとして表示されるようにします。次のヘルパー モジュールは、Calendar を作成します。このコードについて 2 つの質問があります

  1. day_cellメソッドでは、彼は と呼ばれるメソッドを使用しますcapture。いくつかのドキュメントを見つけましたが、このコンテキストでキャプチャがどのように機能しているかはまだわかりません。また、&callback引数としてキャプチャに渡されるのは何ですか? :callbackStruct.new に渡されるものと同じでしょうか? もしそうなら、それはどのようにして捕獲されますか?Struct に渡される :callback とは何ですか?

    def day_cell(day)
      content_tag :td, view.capture(day, &callback), class: day_classes(day)
    end
    

ソースコード

module CalendarHelper
  def calendar(date = Date.today, &block)
    binding.pry
    Calendar.new(self, date, block).table

  end

  class Calendar < Struct.new(:view, :date, :callback)
    HEADER = %w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday]
    START_DAY = :sunday

    delegate :content_tag, to: :view

    def table
      content_tag :table, class: "calendar" do
        header + week_rows
      end
    end

    def header
      content_tag :tr do
        HEADER.map { |day| content_tag :th, day }.join.html_safe
      end
    end

    def week_rows
      weeks.map do |week|
        content_tag :tr do
          week.map { |day| day_cell(day) }.join.html_safe
        end
      end.join.html_safe
    end

    def day_cell(day)
      content_tag :td, view.capture(day, &callback), class: day_classes(day)
    end

    def day_classes(day)
      classes = []
      classes << "today" if day == Date.today
      classes << "notmonth" if day.month != date.month
      classes.empty? ? nil : classes.join(" ")
    end

    def weeks
      first = date.beginning_of_month.beginning_of_week(START_DAY)
      last = date.end_of_month.end_of_week(START_DAY)
      (first..last).to_a.in_groups_of(7)
    end
  end
end
4

1 に答える 1

23

研究を重ね、ついにその謎を解き明かしました。

ですから、いくつかのことから始めましょう。いつものように、ドキュメントはあまり明確ではありません。capture(*args)メソッドは、テンプレートの一部を変数に取得することになっていますが、取得したテンプレートの一部に変数を渡すことができるという説明を深く掘り下げていません。それはもちろんブロックの形で来ます

Ryan Bate のCalendar Screen-castからのソース コード:

<div id="articles">
  <h2 id="month">
    <%= link_to "<", date: @date.prev_month %>
    <%= @date.strftime("%B %Y") %>
    <%= link_to ">", date: @date.next_month %>
  </h2>
  <%= calendar @date do |date| %>
    <%= date.day %>
    <% if @articles_by_date[date] %>
      <ul>
        <% @articles_by_date[date].each do |article| %>
          <li><%= link_to article.name, article %></li>
        <% end %>
      </ul>
    <% end %>
  <% end %>
</div>

上記のコードでは、ブロックはこの部分のみになります。

do |date| %>
  <%= date.day %>
  <% if @articles_by_date[date] %>
    <ul>
      <% @articles_by_date[date].each do |article| %>
        <li><%= link_to article.name, article %></li>
      <% end %>
    </ul>
  <% end %>
<% end %>

だから、彼がこの電話をかけるとき:

content_tag :td, view.capture(day, &callback), class: day_classes(day)

特に:

view.capture(day, &callback)

ここで起こっていることは、彼がの引数を上記のブロックに|date|として渡しているということです。パラメーター (ブロック内)。

ここで理解する必要があるのは、問題 (30 日間のカレンダーの作成) のコンテキストでのことです。Month の各日は、テンプレートの一部(&callback) と共にキャプチャ メソッドに渡されます。その結果、Given Month の各日に対して上記のブロックがレンダリングされます。もちろん、最後のステップは.. レンダリングされたコンテンツを (毎日) content_tag :tdのコンテンツとして配置することです。

最後のメモ; Ryan はビュー変数でキャプチャ メソッドを呼び出しています。ドキュメントにも記載されていませんが、ScreenCast の中で、ビューにアクセスするにはこのビューが「プロキシ」として必要であると述べています。もちろん、ビューはViewHelper メソッドにアクセスできるのは 1 つだけです。

要約すると、これは非常に美しいコードですが、それが何をするかを理解して初めて美しいコードになります。

これが役立つことを願っています。これは私が思いつくことができる最良の説明です。:)

于 2013-03-05T16:50:33.827 に答える