Railsで複数のレコードを一つの塊として管理してみた

# はじめに
フロントにNuxt.js、バックエンドにRailsを使用してサービスを作っているのですが、データ量が多くなり一個ずつデータを送るのに時間がかかってしまったので配列でまとめてRailsに送って処理をしてもらおうと思ったのですが躓いたので記事にします。
# 目次
<!-- タイトルとアンカー名を編集 -->
1. [JSから送るデータ](#Chapter1)
1. [Railsでの実際の処理](#Chapter2)
1. [参考文献](#reference)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# JSから送るデータ
今回のケースではJSから60または250個のデータをバックエンド側に送る必要がありました。
実際のデータは以下のような感じです。
```js
[
　　{"id":7,"name":"","color":"#2196F3","start":1649115900000,"end":1649116800000,"timed":true,"long_time":true,"post_id":null,"long_term_id":1,"created_at":"2022-04-05T08:44:01.049+09:00","updated_at":"2022-04-05T08:44:01.049+09:00"},
　　・
　　・ // 250個のデータ
　　・
　　{"id":256,"name":"","color":"#2196F3","start":1670629500000,"end":1670630400000,"timed":true,"long_time":true,"post_id":null,"long_term_id":1,"created_at":"2022-04-05T08:44:02.329+09:00","updated_at":"2022-04-05T08:44:02.329+09:00"}
]
```
私の場合はカレンダー機能を作成していて、たくさんの予定を入れる必要がありました。データは連想配列になっています。
最初はJSONに変換してから送ろうとしていたのですが、Railsで上手く変換できなかったので配列で送ることにしました。送るときにheaderで``Content-Type``を指定するとJSONを勝手に解釈してハッシュに変換してくれる機能がRailsにはありますが、ネストしている値は上手く変換してくれませんでした。（ここ気付くのに時間かかりました。）


<a id="#Chapter2"></a>
# Railsでの実際の処理
Railsでは値を取り出すのに苦労しました。

#### ①paramsでの処理

```rb
    def schedule_params
      params.permit(post: [:id, :name, :start, :end, :color, :timed, :long_time, :post_id, :long_term_id])
    end
```
``post``が配列のため、``permit``は使えませんでした。なのでpermitの後に直接パラメーターを記載する必要がありました。


 
#### ②アクションを追加する
今回の場合、通常保存する場合（create）と、まとめて配列で大量のデータを保存する場合でアクションを分けたかったのでオリジナルのアクションを追加しました。
オリジナルアクションの追加は``routes``に``member``または``collection``で追加できます
今回は``member``と``collection``どちらも追加したかったので``on:``を使って追加していますが、まとめて追加したい場合はブロックを使います。

**一個ずつ追加**
```rb
        post :create_many_schedule, on: :collection
        post :delete_many_schedule, on: :member
```


**まとめて追加**
```rb
member do
    get 'preview'
    get 'sample'
  end
```
```rb
collection do
   get 'preview'
   get 'sample'
end
```

**memberとcollectionの違い**
``routing``にidが付くか付かないかの違いです。
私のコードの例だと``schedules``の後に``id``がついているのが``member``、ついていないのが``collection``です

```

collection
/api/v1/schedules/create_many_schedule(.:format)	

member
/api/v1/schedules/:id/delete_many_schedule(.:format)	
```

#### ④アクションでの処理
ここで難しかったのが、レコードを一つのまとまりとして管理する方法でした。JSから受け取った250個の値には同じIDを付与したかったのですが、やり方が分からず苦労しました。もしかしたらそういったライブラリもあるのかもしれませんが、見つけられなかったので我流で対処しました。
結局、以下の流れで値を処理しました

-taransactionを使用して250個の値の処理をした後にエラーまたは成功のレスポンスを返す。
-成功の場合は更に一番最後に登録したレコードのidに+1したものを共通の管理IDとして付与する(long_term_id)

model
```rb
  def self.create_schedule(params, array)
    # 送られてきた複数のイベントを保存
    index = Schedule.order(created_at: :desc).limit(1).ids.sum(1)
    Schedule.transaction do
      params.each do |data|
        schedule = Schedule.new(data)
        schedule.save!
        array.push(schedule)
      end

    # イベントにidを付与
      array.each do |data|
        data.long_term_id = index
        data.save!
      end
      return array
    end
  end 


```

controller

```rb
     def create_many_schedule
      schedule_array = []
      begin
        Schedule.create_schedule(schedule_params[:post], schedule_array)
        render  json: schedule_array, status: :created
      rescue => e
        render e
      end
    end

```

第一引数で受けった値(第一引数がparams、第二引数が空の配列)をeachで保存して、保存できたら第二引数の配列に保存していきます。更にその配列をeach使って値を取り出してIDを付与していきます。

これで送った複数のデータに対して同じIDを付与して管理することができました！

<a id="#reference"></a>
# 参考文献
[2.10 RESTfulなアクションをさらに追加する](https://railsguides.jp/routing.html)
[パラメーターが配列の場合、ストパラのparams.permitに含める方法](https://qiita.com/kaito_program/items/3d2a8821d22afd9f82e2)
[railsのroutes.rbのmemberとcollectionの違いは?](https://qiita.com/k152744/items/141345e34fc0095217fe)
[トランザクション
](https://railsdoc.com/page/transaction)