Rails:捕获方法

时间:2012-10-11 21:58:18

标签: ruby-on-rails

以下代码来自Ryan Bates'RailsCasts,他将博客的首页转换为日历,以便文章在日期显示为链接。以下辅助模块创建日历。我对此代码有两个问题

  1. day_cell方法中,他使用名为capture的方法。我在其上找到了一些文档,但我仍然无法弄清楚捕获在这种情况下是如何工作的。另外,作为捕获参数传递的&callback是什么?是否与传递给Struct.new的:callback相同?如果是这样,它如何进入捕获?什么是:传递给Struct的回调?

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

    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
    

1 个答案:

答案 0 :(得分:16)

我做了我的研究,最后我揭开了神秘面纱。

所以,开始时要做几件事;像往常一样documentation不是很清楚, 捕获(* args)方法应该将一块模板抓取到一个变量中,但它并没有深入解释你可以将变量传递给抓取的模板< / strong>,当然以

的形式出现

源代码 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)

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

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

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

所以,总而言之,这是非常漂亮的代码,但是一旦你明白它的作用就会很美好,所以,我同意一见钟情。

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