簡素なカレンダーのライブラリが欲しくて、clndr-railsを試したがひと月毎にデータ取得するにはjsonでやり取りしないといけなかったり、Eventの種類わけてCSS当てたい等いろいろ弄くって拡張難しそうだったのでベースのCSSだけ残して後は自作した方が良い気がしたのでそのメモ
Clndr
gem 'clndr-rails'
application.css
*= require clndr-rails
Model
calendar.rb
class Calendar
attr_accessor :current_month_days, :prev_month_days, :next_month_days, :start_day
def initialize(date, start_day: :sunday)
self.current_month_days = date.all_month
self.prev_month_days = date.prev_month.all_month
self.next_month_days = date.next_month.all_month
self.start_day = start_day
end
def to_partial_path
'calendar/calendar'
end
def headers
%w(Sun Mon Tue Wed Thu Fri Sat)
end
def title
"#{current_month_days.first.month} #{current_month_days.first.year}"
end
def days
days = current_month_days.to_a
days.concat(prev_month_days_in_first_week)
days.concat(next_month_days_in_last_week)
days.sort.map{|date| add_singleton_methods(date) }
end
def prev_month_path
switch_month_path(:prev)
end
def next_month_path
switch_month_path(:next)
end
private
def prev_month_days_in_first_week
(current_month_days.first.beginning_of_week(start_day)...current_month_days.first).reject{|date|
date.in?(current_month_days)
}
end
def next_month_days_in_last_week
(current_month_days.last..current_month_days.last.end_of_week(start_day)).reject {|date|
date.in?(current_month_days)
}
end
def add_singleton_methods(date)
is_prev_month, is_next_month = prev_month_days.include?(date), next_month_days.include?(date)
date.define_singleton_method(:prev_month?){ is_prev_month }
date.define_singleton_method(:next_month?){ is_next_month }
date
end
def switch_month_path(type)
target_date =
case type
when :prev then prev_month_days.first
when :next then next_month_days.first
end
Rails.application.routes.url_helpers.calendar_path(
month: target_date.month,
year: target_date.year
)
end
end
to_partial_path
を定義することでrendar @calendar
で描画できる
Controller
calendar_controller.rb
def index
@calendar = Calendar.new(current_date)
end
View
calndar/index.html.erb
<%= render @calendar %>
clandar/_calendar.html.erb
<div id="my-clndr" class="clearfix full-clndr-template">
<div class="clndr">
<div class="clndr-controls">
<%= link_to calendar.prev_month_path do %>
<div class="clndr-previous-button"><</div>
<% end %>
<%= link_to calendar.next_month_path do %>
<div class="clndr-next-button">></div>
<% end %>
<div class="current-month"><%= calendar.title %></div>
</div>
</div>
<div class="clndr-grid full">
<div class="days-of-the-week clearfix">
<% calendar.headers.each do |day_of_week| %>
<div class="header-day"><%= day_of_week %></div>
<% end %>
</div>
<div class="days">
<% calendar.days.each do |date| %>
<%= content_tag :div,
class: "day #{'past' if date.past?} \
#{'prev-month adjacent-month' if date.prev_month?} \
#{'next-month adjacent-month' if date.next_month?} \
calendar-dow-#{date.wday}".squish! do %>
<span class="day-number"><%= date.day %></span>
<% end %>
<% end %>
</div>
</div>
</div>
あとはここから見た目弄くったりeventsをつっこんだり。