jsとかややこしいの使わずRailsでカスタム自由度の高いカレンダー実装

カレンダー実装をするために色々探してたんですが、jqueryプラグインとかgem使ったらいじりにくいし、これってのがなく、しょうがなく色々参考にしながら１から作りました。

誰かのお役に立てば幸いです。

見た目はこんな感じです。

<img src="https://i.gyazo.com/447844539f7ba2f3a34df66d9a09f8f8.png">

さっそくコード

## 先ずはカレンダーの箱

ちょっと一工夫いるのは条件によって<tr>を出したり消したりしてるとこですね。
そこだけです。
基本的に見れば分かるコードだと思うので解説は割愛します。
ちなみに
http://qiita.com/100010/items/9f13dac0a76c04e36bbd
を参考にしてます。

html.erb

```html+erb

<div class="event-calendar">
    <table>
        <caption>2016年9月</caption>
        <tbody>
            <tr>
                <th>日</th>
                <th>月</th>
                <th>火</th>
                <th>水</th>
                <th>木</th>
                <th>金</th>
                <th>土</th>
            </tr>
            <% @calendar_days.each_with_index do |day, i| %>
                <% if i == 0 || i % 7 == 0 %>
                    <tr>
                <% end %>
                <td>
                    <p>
                        <%= day %>
                    </p>
                    <div>
                        <!-- ここにカレンダー１日単位で情報埋める -->
                    </div>
                </td>
                <% if i !=  0 && (i + 1) % 7 == 0 %>
                    </tr>
                <% end %>
            <% end %>
        </tbody>
    </table>
</div>

```

で、次に@calendar_daysに突っ込む値です

## ちょっとめんどくさいアルゴリズム

けっこう苦肉りながら書いたので、もっといい方法あるだろって感じですが一旦こんな感じです。

全体としては、月の最初の日より前の部分と、月の最後の日より後の、よくカレンダーでグレーになってる過不足部分（なんて呼ぶんでしょうあれ）を、integerのarrayにして、最終的に当月の1~30日の配列と足してます。

```ruby

    def get_calendar_dates(date)
      get_pre_shortage_days(date) + (1..date.end_of_month.day).to_a + get_post_shortage_days(date)
    end

    # その月の、"29 30" 1 のようなカレンダー不足分
    def get_pre_shortage_days(date)
      beginning_day = date.beginning_of_month
       return 0 if beginning_day.wday == 0
       pre_shortage_day = beginning_day - beginning_day.wday.days
       return (pre_shortage_day.day..pre_shortage_day.end_of_month.day).to_a
    end

    def get_post_shortage_days(date)
      end_day = date.end_of_month
      return 0 if end_day.wday == 6
      post_shortage_day = end_day + -(end_day.wday - 6).days
      return (1..post_shortage_day.day).to_a
    end
  end

```

### 部分的な解説

配列の足し算、便利です。

```rb
[1, 2, 3] + [4, 5, 6]
=> [1, 2, 3, 4, 5, 6]
```

肝になったのは以下の処理です。
これで日曜日〜土曜日までが0~6でとれるので、それで日を前後させてます。

```
Date.today.wday
```

ちなみに前後させるのに使ってる処理ですが、以下のように日付って足し引きできて便利です。

```ruby
Date.today + 6.days
```

あとはrange型をarray型に変えるのも重宝しました。最初からarrayでもっと簡単にできそうな気配しかないですが。

```ruby

(1..2).to_a
=> [1, 2]

```

## scssについて

あるサイトを参考にして以下のようなscssを書きました。

```scss

div.event-calendar {
  float: left;

  table {
    width: 325px;
    margin-right: 5px;

    caption {
      font-size: 14px;
      color: #479384;
      border: 1px solid #b9b9b9;
      border-bottom: none;
      padding: 14px 0 12px;
      text-align: center;
    }

    tbody {
      display: table-row-group;
      vertical-align: middle;
      border-color: inherit;

      tr {
        display: table-row-group;
        vertical-align: inherit;
        border-color: inherit;

        th {
          width: 325px;
          text-align: center;
          vertical-align: top;
          color: #479384;
          background-color: #ecf7f5;
          border: 1px solid #b9b9b9;
          padding: 6px;
        }

        td {
          text-align: center;
          border: 1px solid #b9b9b9;
          font-size: 11px;
          width: 14%;
          height: 60px;

          i {
            font-size: 20px;
          }
        }
      }
    }
  }
}

```


稚拙な説明が極まってますが、誰かのお役に立てれば幸いです。