railscast PRO #213+
老實說因為block我還不熟,有些東西實在不是很懂怎樣跑的囧
總之先看到哪就先筆記到哪
code: https://github.com/telsaiori/ckeditor_test/blob/calendar/app/helpers/calendar_helper.rb
view:
<%= calendar current_date do |date| %>
<% date_key = date.strftime %>
<% if posts_by_date[date_key] %>
<%= link_to date.day, posts_path(posts_by_date: date_key) %>
<% else %>
<%= date.day%>
<% end %>
<% end %>
code:def calendar(date = Date.today, &block)
Calendar.new(self, date, block).table
end
class Calendar < Struct.new(:view, :date, :callback)
Calendar.new(self, date, block).table
end
這裡使用Struct.new(:view, :date, :callback)和設定attr_accessor :view, :date, :callback效果是一樣的然後把self: 本來網頁的view
date: 當日日期
block:本來view裡面的block丟給Calendar然後由table method建出月曆
delegate主要是用來讓A class也可以使用別的class的method,這邊的話就是讓Calandar裡面也可以使用content_tag這個helper
不然會出現
undefined method `content_tag’ for CalendarHelper::Calendar:0x007fb442119330
class Calendar < Struct.new(:view, :date, :callback)
HEADER = %w[ 日 一 二 三 四 五 六]
START_DAY = :sunday
delegate :content_tag, to: :view
def table
content_tag :table, class: "calendar" do
year_header + header + week_rows
end
end
下面生成table的過程就比較單純 生成星期幾的部分,因為前面已經定義好HEADER,這邊只是把它變成[“日“, “一“, “二“, “三“, “四“, “五“, “六“]然後再靠join轉成字串在用html_safe讓他可以正常輸出到view
def header
content_tag :tr do
HEADER.map { |day| content_tag :th, day}.join.html_safe
end
end
生成一個星期的row,先用一開始代進來的date算出這星期的第一天和最後一天,然後和上面一樣轉成htmldef 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 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
中間會先把日期丟給day_cell處理 capture可以把模板保留成string方便之後在需要的地方處理
以這邊的view.capture(day, &callback)就是會把目前正在處理的日期回傳給view裡面的block
比方如果目前處理到“Wed, 11 Jan 2017”
如果沒有文章,capture的結果會是”\n 11\n”
有文章的話會得到
“\n <a href=\"/posts?posts_by_date=2017-01-11\">11</a>\n”
<%= calendar current_date do |date| %>
<% date_key = date.strftime %>
<% if posts_by_date[date_key] %>
<%= link_to date.day, posts_path(posts_by_date: date_key) %>
<% else %>
<%= date.day%>
<% end %>
<% 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
Written with StackEdit.
沒有留言:
張貼留言