3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Rails】今月を常に表示させるカレンダーの作り方

Last updated at Posted at 2021-01-27

背景

  • Railsで個人アプリケーションを作成していましたが、今月の予定表を作る必要がありました。そこで、コントローラー側でRubyを用いてプログラムを書けば、ビューで表示できるかと思ってので実装してみました。変数との関連性と計算に時間が掛かりましたが、そこまで難しいレベルではありませんので参考になればと思い、記事を書かせていただきました。外国人なので変な日本語が混じってるかもしれませんが、ご指摘いただければ幸いです。

目次

  • Dateクラスについて
  • timesメソッドについて
  • コントローラーの実装
  • ビューの実装
  • 参考サイト

Dateクラスについて

DateクラスはRubyの組み込みクラスであり、今回使用したのは以下のメソッドです。

  • Date.today
    今日の日付を取得します。今年の場合、戻り値は2021-01-28で年月日の形式になります。
now = Date.today
  • Date.today.year
    今年の値を取得します。戻り値は2021になります。
this_year = Date.today.year
  • Date.today.month
    今月の値を取得します。戻り値は1になります。
this_year = Date.today.month
  • Date.today.wday
    今日の日付を取得します。戻り値は0から6までの値です。
戻り値 意味
0 日曜日
1 月曜日
2 火曜日
3 水曜日
4 木曜日
5 金曜日
6 土曜日
weekday = Date.today.wday
  • Date.today.beginning_of_month
    今月の初日を取得します。戻り値は2021-01-01になります。
first_day = Date.today.beginning_of_month  

timesメソッドについて

  • timesは同じ処理を回数分だけ繰り返す時に使うメソッドです。
  • 使い方
    回数.times do |変数|
10.times do |i|
  (処理)
end

コントローラーの実装

以上のメソッドを踏まえて、コントローラーの実装を行いました。全体のコードは以下の通りです。

class SdatesController < ApplicationController
  def index
    date_today
  end

  private

  def date_today
    @now = Date.today
    @wday_jan = ["月","火","水","木","金","土","日"]
    @this_year = @now.year
    @this_month = @now.month
    
    
    @first_day = @now.beginning_of_month
    @last_day = (@first_day + (7-@first_day.wday))
    @week_period = (@first_day..@last_day)

    @last_day2 = (@last_day + (7-@last_day.wday))
    @week_period2 = ((@last_day+1)..@last_day2)

    @last_day3 = (@last_day2 + (7-@last_day2.wday))
    @week_period3 = ((@last_day2+1)..@last_day3)

    @last_day4 = (@last_day3 + (7-@last_day3.wday))
    @week_period4 = ((@last_day3+1)..@last_day4)

    @last_day5 = (@last_day4 + (7-@last_day4.wday))
    @week_period5 = ((@last_day4+1)..@last_day5)

    @last_day6 = (@last_day5 + (7-@last_day5.wday))
    @week_period6 = ((@last_day5+1)..@last_day6)

  end
end

今回のカレンダー機能と関係あるところはprivate以下のコードです。
長いように見えますが、@last_day2以下は同じような処理の繰り返しです。

  • まずは今日の日付を変数@nowに代入します。
@now = Date.today
  • wdayメソッドは戻り値が数字であるため、曜日として表示するための配列@wday_janを用意します。
@wday_jan = ["月","火","水","木","金","土","日"]

例えば、@wday_jan[1]だった場合、"月"が出力されるようにします。

@this_year = @now.year
 @this_month = @now.month
  • 今月の初日を取得するために.beginning_of_monthメソッドを使います。値は@first_dayに代入します。
 @this_month = @now.month
  • 初日から最初の週(first weekend)の末日(日曜日)を計算し、
    値を@last_dayに代入します。@last_dayは「初日の日付 + 日曜日までの日数」であり、
    ここでポイントになるのはが「日曜日までの日数」の計算です。
    @wday_janには["月","火","水","木","金","土","日"]が格納されて"1"が"月"、"2"が"火"・・・"0”が"日"などのようにマッチングしています。例えば、初日が水曜日だった場合、@wday_janには"水"="3"です。水曜日から最初の週の末日(日曜日)までの日数は"7-3"となります。この関係を数式で表現すると「@wday_janの配列の数-初日の曜日数(3)」になります。代入した変数で式を表すと以下になります。
@last_day = (@first_day + (7-@first_day.wday))
  • 次は初日から最初の週の末日までの日付らをRangeオブジェクト@week_periodに代入します。
@week_period = (@first_day..@last_day)
  • 同じように第2週目、第3週目....の月曜~日曜までのRangeを求めます。繰り返しになるので説明は割愛します。
@last_day2 = (@last_day + (7-@last_day.wday))
@week_period2 = ((@last_day+1)..@last_day2)
...以下、繰り返し部分を省略
  • index.html.erbテンプレートで表示させるために、privateで定義した関数date_todayを記述します。
   (上記、コードは省略)
def index
   date_today
end

ビューの実装

コントローラーで定義したメソッドをindex.html.erbテンプレートに表示するための記述をします。

<div class="schedule_title">
    <h1>Schedule Board</h1>
</div>

<div id="todays_date">
    <%= @this_year %>年<%= @this_month %>
</div>

<table border="1" id="sdate_table">
    <thead>
        <tr>
            <th class="sdate_name">月</th>
            <th class="sdate_name"></th>
            <th class="sdate_name">水</th>
            <th class="sdate_name"></th>
            <th class="sdate_name">金</th>
            <th class="sdate_name"></th>
            <th class="sdate_name">日</th>
        </tr>
    </thead>
    <tbody>
        <tr>
        <% 7.times do |x| %>
            <td>
            <% @week_period.each do |period| %> 
            <% if x == (period -1).wday %>
            <%= period %> 
            <% end %>
            <% end %>
            </td>
        <% end %>
        </tr>

        <tr>
        <% 7.times do |x| %>
            <td>
            <% @week_period2.each do |period| %> 
            <% if x == (period -1).wday %>
            <%= period %> 
            <% end %>
            <% end %>
            </td>
        <% end %>
        </tr>

        <tr>
        <% 7.times do |x| %>
            <td>
            <% @week_period3.each do |period| %> 
            <% if x == (period -1).wday %>
            <%= period %> 
            <% end %>
            <% end %>
            </td>
        <% end %>
        </tr>

        <tr>
        <% 7.times do |x| %>
            <td>
            <% @week_period4.each do |period| %> 
            <% if x == (period -1).wday %>
            <%= period %> 
            <% end %>
            <% end %>
            </td>
        <% end %>
        </tr>

        <tr>
        <% 7.times do |x| %>
            <td>
            <% @week_period5.each do |period| %> 
            <% if x == (period -1).wday %>
            <%= period %> 
            <% end %>
            <% end %>
            </td>
        <% end %>
        </tr>

    
        <% if Random.rand(@week_period6).month == @this_month %>
        <% 7.times do |x| %>
            <td>
            <% @week_period6.each do |period| %> 
            <% if x == (period -1).wday %>
            <%= period %> 
            <% end %>
            <% end %>
            </td>
        <% end %>
        </tr>
        <% end %>
</tbody>
</table>
  • timesメソッドを使い、テーブルの1行ごとに日付を表示させます。の間を7回繰り返すことによって1週間の日付を出力します。
 <% 7.times do |x| %>
            <td>
            <% @week_period.each do |period| %> 
            <% if x == (period -1).wday %>
            <%= period %> 
            <% end %>
            <% end %>
            </td>
        <% end %>
  • if文を使い、繰り返しの変数xと@week_periodに格納されている日付らを変数periodに代入。日付から1を引いた後に、その日付の曜日(0~6の値)とxが一致した場合にのみ表示するようにします。つまり、変数xには1週間分を繰り返す機能と同時に月曜日〜日曜日まで(1,2,3,〜0)までindexの機能を持たせます。こうすることによってこのindexと一致した日付の値のみが表示されます。

  • 最後の週には次月の日付が入ってしまったりする場合があるため、if文を使って分岐させます。

<% if Random.rand(@week_period6).month == @this_month %>

Random.rand(変数)メソッドを使い、変数内の中からランダムで一つの値を取得します。
@week_period6には最後の週の日付らが入ってます。その日付らのどれかになります。(1月25日〜31日までのどれか)その値に.monthメソッドを使い、月を取得します(1月)。それと@this_month(実際の今月。例えば、今日が2月2日の場合は2月)が一致した場合にのみ、表示するようにします。

  • index.html.erbの画像
    スクリーンショット 2021-01-28 2.09.41.png

参考サイト

https://www.javadrive.jp/ruby/for/index6.html
https://qiita.com/geshi/items/685a0814d77688fb1a55
https://qiita.com/youcune/items/f5371d449d2486c67357

3
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?