calendar_helperの頭の悪い携帯対応
vendor/plugins/calendar_helper/lib/calendar_helper.rb の、calendar メソッドの #TODO〜 からメソッドの最後までをこのように書き換えてみた…。
# 自前テンプレートエンジンtmp。リクエストが携帯かどうかで切り替える。 tmp = request.mobile? ? lambda do |tn| # 携帯の場合 case tn when :table_start "<pre>" when :thtr "" when :pmt " %s " % options[:previous_month_text] when :month_name lambda do |colspan| " %4s " % Date::MONTHNAMES[options[:month]] end when :nmt " %s " % options[:next_month_text] when :h_to_dn "<br>" when :dn lambda do |d| " %s" % d[options[:abbrev]] end when :dn_to_b "<br>" when :td_om lambda do |d| " <font color='#999999'>%2d</font>" % d.day end when :td lambda do |cell_attrs, cell_text| " %2s" % cell_text end when :newline "<br>" when :table_end "</pre>" end end : lambda do |tn| # PCの場合 case tn when :table_start %(<table class="#{options[:table_class]}" border="0" cellspacing="0" cellpadding="0">) when :thtr %(<thead><tr>) when :pmt %(<th colspan="2">#{options[:previous_month_text]}</th>) when :month_name lambda do |colspan| %(<th colspan="#{colspan}" class="#{options[:month_name_class]}">#{Date::MONTHNAMES[options[:month]]}</th>) end when :nmt %(<th colspan="2">#{options[:next_month_text]}</th>) when :h_to_dn %(</tr><tr class="#{ options[:day_name_class]}">) when :dn lambda do |d| unless d[options[:abbrev]].eql? d "<th scope='col'><abbr title='#{d}'>#{d[options[:abbrev]]}</abbr></th>" else "<th scope='col'>#{d[options[:abbrev]]}</th>" end end when :dn_to_b "</tr></thead><tbody><tr>" when :td_om lambda do |d| cls = options[:other_month_class] + (weekend?(d) ? " weekendDay" : "") "<td class=\"#{cls}\">#{d.day}%s</td>" % (options[:accessible] ? "<span class=\"hidden\"> #{Date::MONTHNAMES[d.month]}</span>" : "") end when :td lambda do |cell_attrs, cell_text| "<td #{cell_attrs}>#{cell_text}</td>" end when :newline "</tr><tr>" when :table_end "</tr></tbody></table>" end end # カレンダー構築 cal = tmp.call(:table_start) cal << tmp.call(:thtr) if options[:previous_month_text] or options[:next_month_text] cal << tmp.call(:pmt) colspan=3 else colspan=7 end cal << tmp.call(:month_name).call(colspan) cal << tmp.call(:nmt) if options[:next_month_text] cal << tmp.call(:h_to_dn) day_names.each do |d| cal << tmp.call(:dn).call(d) end cal << tmp.call(:dn_to_b) beginning_of_week(first, first_weekday).upto(first - 1) do |d| cal << tmp.call(:td_om).call(d) end unless first.wday == first_weekday first.upto(last) do |cur| cell_text, cell_attrs = block.call(cur) cell_text ||= cur.mday cell_attrs ||= {:class => options[:day_class]} cell_attrs[:class] += " weekendDay" if [0, 6].include?(cur.wday) cell_attrs[:class] += " today" if (cur == Date.today) and options[:show_today] cell_attrs = cell_attrs.map {|k, v| %(#{k}="#{v}") }.join(" ") cal << tmp.call(:td).call(cell_attrs, cell_text) cal << tmp.call(:newline) if cur.wday == last_weekday end (last + 1).upto(beginning_of_week(last + 7, first_weekday) - 1) do |d| cal << tmp.call(:td_om).call(d) end unless last.wday == last_weekday cal << tmp.call(:table_end)
元のソースを切り貼りすることで携帯対応させることをテーマに、クロージャとしてのProcオブジェクトを最大限活用。コルーチンとか使ってみようとしたが、あくまで部分テンプレートを明示的に指定したかったので却下。RubyのLISP的なとこってこういうとこなのだろうか。