【rails】simple_calendarを用いたカレンダー機能にて、複数日程にも対応できるようにする。

# 経緯的な
railsにてカレンダーを簡単に実装できる`simple_calendar`を先人の方々の記事を使って実装した際に、「旅行等々の日付跨ぐ予定に対応させたい！」となったものの、ちょうどいい記事がぱっと見つからなかったので書いてみました。

多分すでに書いてある記事はある。はず。
# 完成形
![qiita-simple_calendar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1874115/13b24cb1-bd89-1837-80fd-6fc4e3aa572d.png)
「テスト週間の期間」と「旅行の期間」をそれぞれ一度の投稿で指定した期間をカレンダーに表示できるようになります。

# 前提
- 本記事はPostモデルを使用している前提で書いています。
- 投稿機能は実装済みの前提で書いています
またカラムは
- `予定名`を保存するカラムとして`title:string`
- `予定開始`を保存するカラムとして`start_time:datetime`
- `予定終了`を保存するカラムとして`end_time:datetime`
をそれぞれ用意しています。

本記事と全く同じ様に作成する際は以下の通りにコマンド打って作っちゃってください。
```powershell:ターミナル
$ rails g model Post title:string start_time:datetime end_time:datetime
$ rails db:migrate

```

# 実装
## gemの導入
```ruby:Gemfile
gem 'simple_calendar', '~> 2.0'
```
`bundle install` を忘れずに打ってください

## コントローラーの記述
::: note warn
既に投稿用のMVCを作成している方はindexアクションの中身のみ参考にしてください
(ストロングパラメータへの追記もお忘れなく)
:::

```ruby:posts_contoroller.rb
class PostsController < ApplicationController
  def index
      start_date = params.fetch(:start_date, Date.today).to_date
      @events = Post.where('start_time <= ? AND (end_time >= ? OR end_time IS NULL)', start_date.end_of_month.end_of_week, start_date.beginning_of_month.beginning_of_week)

  end

  def new
      @post = Post.new
  end

  def create
      post = Post.new(post_params)
      if post.save
          redirect_to :action => "index"
      else
          redirect_to :action => "new"
      end
  end
  def show
      @post = Post.find(params[:id])
  end

  def edit
      @post = Post.find(params[:id])
  end

  def update
      post = Post.find(params[:id])
      if post.update(post_params)
          redirect_to :action => "show", :id => post.id
      else
          redirect_to :action => "new"
      end
  end

  def destroy
      post = Post.find(params[:id])
      post.destroy
      redirect_to action: :index
  end

  private
  def post_params
      params.require(:post).permit(:title,:start_time,:end_time)
  end

end
```
## viewの記述
```ruby:views/posts/new.html.erb
<%= form_for @post do |f| %>
    <div class="field">
        <%= f.label :title %>
        <p><%= f.text_field :title, :size => 20 %></p>
        <%= f.label :start_time,"いつ/いつから" %>
        <p><%= f.date_field :start_time %></p>
        <%= f.label :end_time,"いつまで？/１日だけの予定の場合、未記入可" %>
        <p><%= f.date_field :end_time %></p>
    </div>
    <%= f.submit "投稿する" %>
<% end %>
```

```ruby:views/posts/index.html.erb
<%= month_calendar(attribute: :start_time, start_attribute: :start_time, end_attribute: :end_time, events: @events) do |date, events| %>
    <%= date %>
  <% events.each do |event| %>
      <p><%= link_to event.title, event %></p>
  <% end %>
<% end %>
```
## application.cssへの記述
`*= require simple_calendar`の追加をお忘れなく。
```diff_css:application.css
/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
 * vendor/assets/stylesheets directory can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
 * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
 * files in this directory. Styles in this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
+ *= require simple_calendar
 *= require_tree .
 *= require_self
 */
```

以上で実装自体は終了です！
カレンダーの見た目を編集したい場合は以下のコマンド実行してsimple_calendar専用のviewファイルを作成してください！

```powershell:ターミナル
 $ rails g simple_calendar:views
```
## 参考
https://github.com/excid3/simple_calendar

https://qiita.com/isaatsu0131/items/ad1d0a6130fe4fd339d0

ありがとうございました。