11

以下代码来自 Ryan Bates 的RailsCasts,他在其中将博客的首页变成了日历,以便文章在几天内显示为链接。以下帮助模块创建日历。我对此代码有两个问题

  1. day_cell方法中,他使用了一种叫做 的方法capture。我在上面找到了一些文档,但我仍然无法弄清楚捕获在这种情况下是如何工作的。另外,&callback作为参数传递给捕获的是什么?是否与:callback传递给 Struct.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)

这里发生的事情是他将day参数作为|date|传递给上面的 Block 。参数(在块中)。

这里需要理解的是,在问题的背景下(制作 30 天日历);每月的每一天都与模板(&回调)一起传递给捕获方法,这样做..结果为给定月份的每一天呈现上面的块。最后一步,当然是.. 将呈现的内容(每天)作为content_tag 的内容:td

最后一点;Ryan 在视图变量上调用 capture 方法,文档中也没有说明,但他在 ScreenCast 中确实提到他需要这个视图作为“代理”来访问视图,当然视图是只有一个可以访问 ViewHelper 方法。

所以,总而言之,它是非常漂亮的代码,但只有当你理解它的作用时它才会变得漂亮,所以,我同意乍一看非常令人困惑。

希望这会有所帮助,这是我能想到的最好的解释。:)

于 2013-03-05T16:50:33.827 回答