RailsCasts - Ruby on Rails Screencasts

RailsCasts Pro episodes are now free!

Learn more or hide this

Calendars (revised)

#213 Calendars (revised)

Aug 10, 2012 | 9 minutes | Views, Plugins, Forms
Learn how to add a calendar to your Rails app. Whether it be a date picker using jQuery UI or a full page calendar for browsing records, I will show you how to do it in this episode.
Click to Play Video ▶
Tweet
  • Download:
  • source code Project Files in Zip (60.1 KB)
  • mp4 Full Size H.264 Video (23.4 MB)
  • m4v Smaller H.264 Video (12.7 MB)
  • webm Full Size VP8 Video (14.8 MB)
  • ogv Full Size Theora Video (30.9 MB)
Browse_code Browse Source Code

Resources

Date Picker

Gemfile
group :assets do
 # ...
 gem 'jquery-ui-rails'
end
app/assets/javascripts/application.js
//= require jquery.ui.datepicker
app/assets/stylesheets/application.css
/*
 *= require jquery.ui.datepicker
 */
articles/_form.html.erb
<%= f.text_field :published_on %>
articles.js.coffee
jQuery ->
 $('#article_published_on').datepicker
 dateFormat: 'yy-mm-dd'

Calendar View

calendars_controller.rb
def index
 @articles = Article.all
 @articles_by_date = @articles.group_by(&:published_on)
 @date = params[:date] ? Date.parse(params[:date]) : Date.today
end
index.html.erb
<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>
helpers/calendar_helper.rb
module CalendarHelper
 def calendar(date = Date.today, &block)
 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
app/assets/stylesheets/articles.css.scss
#articles .calendar {
 border-collapse: collapse;
 width: 100%;
 td, th {
 font-family: "Lucida Grande", arial, helvetica, sans-serif;
 font-size: 10px;
 padding: 6px;
 border: 1px solid #999;
 }
 th {
 background: #DDD;
 color: #666;
 text-align: center;
 width: 14.2857142857143%;
 }
 td {
 background: #FFF;
 color: #777;
 height: 80px;
 vertical-align: top;
 font-size: 16px;
 }
 .notmonth, .notmonth a { color: #CCC; }
 .today { background-color: #D7F2FF; }
}
#articles #month {
 margin: 0;
 padding-bottom: 10px;
 text-align: center;
 font-size: 22px;
 a {
 text-decoration: none;
 padding: 0 10px;
 color: #999;
 }
}
#articles ul {
 font-size: 11px;
 padding-left: 20px;
}
loading

AltStyle によって変換されたページ (->オリジナル) /