【Ruby on Rails】railsでスタディープラスっぽいもの作ろうとしてみた（グラフ表示）

# はじめに
自分のスキルアップのために人気アプリ、スタディープラスのトレースをしていてその過程でちょっと悩んだところがあったので備忘録として記事として残します。もし、もっとスマートな書き方があったらご教示ください。

# 実装
実装に際して前提として①基本となる投稿機能(Tweetモデル)　②deviseを用いたユーザー機能　の２つが実装されているという前提で作成を進めていきます。
また、tweetsテーブルにstrig型でtagという名前のカラムを事前に追加しておくようにお願いします。

## カテゴリの選択と追加
### 1.モデルの作成とアソシエーション
勉強した科目などのカテゴリを追加・保存するためのテーブル(tagsテーブル）の作成を行います。
コマンドプロンプトで以下のコマンドを実行してください
```
rails g model Tag name:string
```


```
rails db:migrate
```


また、アソシエーションの設定もしておきましょう！

```ruby:tweet.rb
  has_many :tags
```

```ruby:tag.rb
  has_many :tweets
```
### viewの編集
次にviewの作成・編集を行います。
```ruby:app/views/tweets/index.html.erb
<%= form_tag({controller:"tweets",action:"index"}, method: :get) do %>
    <%= text_field_tag :tag %>
    <%= submit_tag 'タグを追加' %>
<% end %>
```
これは新しいタグを追加するための記述です。form_tagの基本的な使い方で記述することができます。

```ruby:app/views/tweets/new.html.erb
<%= form_with(model: @tweet, url: {controller: 'tweets', action: 'create'} ,local: true) do |form|%>
    <div class="form">
        <div class="form-body">
            <p>tag_name</p>

　　　　　　 <!-- tagsテーブルに入っているデータを参照してプルダウンを作成 -->
            <%= form.collection_select(:tag,@tags,:name,:name)%>

　　　　　　 <!-- timeカラムに学習時間を記録するためのnumber_field -->
            <%= form.number_field :time %>

            <%= form.submit "保存"%>
        </div>
    </div>
<% end %>
```
これは記録の投稿画面です。
```
<%= form.collection_select(:tag,@tags,:name,:name)%>
```
この記述がちょっと難しいかもしれないので解説を少し書いておきます。railsの公式ドキュメントを見ると
[rails公式ドキュメント](https://railsdoc.com/page/collection_select "公式ドキュメント")

```ruby:使いかた
f.collection_select(メソッド名, 要素の配列, value属性の項目, テキストの項目, オプション={}, HTML属性={} or イベント属性={})
```

これだけ見ても良く分からないと思いますが、簡単に言うと、モデルから選択肢を持ってきてその中から選びDBに送ろうとしている、って思ってもらえれば大丈夫。
詳しいことは↓の記事に綺麗にまとまっているので参考にしてみてください
[【Ruby】f.collection_select　を使ってみた
](https://qiita.com/ohnitakahiro/items/c536fe65e37980e1087e "【Ruby】f.collection_select　を使ってみた
")



```ruby:app/views/tweets/show.html.erb
<!-- 投稿ごとのタグを表示する -->
<%= @tweet.tag %>
```


```ruby:app/views/users/show.html.erb
<!-- userの投稿を一覧で表示する -->
<h2>ユーザーの投稿一覧</h2>
<% @user.tweets.each do |t| %>
    <%= t.user.email %>
    <%= t.body %>
    <%= t.time%>
    <%= t.tag %>
    <br>
<% end %>
```

### controllerの記述
次にコントローラーにいくつか追加の記述をします。


```ruby:app/controllers/tweets_controller.rb
def index
#下の3行を追加。新たなタグを追加することができるようになる。
    if params[:tag]
      Tag.create(name: params[:tag])
    end

end
```

```ruby:app/controllers/tweets_controller.rb
# tagに値を受け取ることができるようにする
private
def tweet_params
   params.require(:tweet).permit(:body,:time,:tag)
end
```


```ruby:app/controllers/users_controller.rb
def show
    @user = User.find(params[:id]) 
end
```
ここまでで投稿機能の拡張が完了です！
## グラフ表示
グラフの表示にはchartkickというgemを利用します。

### chartkickの導入
chartkickはrails のバージョンによって導入方法が異なるので自分のバージョンに合った方法で導入してください！！
### 導入

まずはkickchartの導入からです。rails のバージョンによって導入方法が違うので注意してください！
どのバージョンであってもまずはgemファイルに以下の記述を書き加えてください！！



```ruby:gemfile.rb
gem "chartkick"
```
その後コマンドプロンプトで
```
bundle install
```

### rails7の場合

configのimport.rbに以下の記述を追加してください。

```ruby:config/importmap.rb
pin "chartkick", to: "chartkick.js"
pin "Chart.bundle", to: "Chart.bundle.js"
```

また、app/javascript/application.jsに以下の記述を追加してください。
```ruby:app/javascript/application.js
import "chartkick"
import "Chart.bundle"
```

これでrails7における導入は完了です！！

### rails6の場合

ターミナルorコマンドプロンプトにて以下のコマンドを実行してください！

```
yarn add chartkick chart.js
```

app/javascript/packs/application.jsに以下の記述を追加してください！
```ruby:app/javascript/packs/application.js
import "chartkick/chart.js"
```
これでrails6における導入は完了です！

### rails5の場合
app/assets/javascripts/application.jsに以下の記述を追加してください！
```ruby:app/assets/javascripts/application.js
//= require chartkick
//= require Chart.bundle
```

これでrails5における導入は完了です！

### ユーザーマイページに円グラフを表示する
ユーザーマイページにグラフを表示できるように編集します！

```ruby:app/controllers/users_controller.rb

#変数tweetsに現在ログインしているユーザがした投稿全てを代入
tweets = Tweet.where(user_id: current_user.id)

#変数@sumにtagごとの合計値を代入する
@sum = tweets.group(:tag).sum(:time)
```


```ruby:app/views/users/show.html.erb
#グラフを表示する
<%= pie_chart @sum %>
```
# 終わりに
閲覧いただきありがとうございました。