LoginSignup
0
0

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-04-05

はじめに

フロントにNuxt.js、バックエンドにRailsを使用してサービスを作っているのですが、データ量が多くなり一個ずつデータを送るのに時間がかかってしまったので配列でまとめてRailsに送って処理をしてもらおうと思ったのですが躓いたので記事にします。

目次

  1. JSから送るデータ
  2. Railsでの実際の処理
  3. 参考文献

JSから送るデータ

今回のケースではJSから60または250個のデータをバックエンド側に送る必要がありました。
実際のデータは以下のような感じです。

[
  {"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にはありますが、ネストしている値は上手く変換してくれませんでした。(ここ気付くのに時間かかりました。)

Railsでの実際の処理

Railsでは値を取り出すのに苦労しました。

①paramsでの処理

    def schedule_params
      params.permit(post: [:id, :name, :start, :end, :color, :timed, :long_time, :post_id, :long_term_id])
    end

postが配列のため、permitは使えませんでした。なのでpermitの後に直接パラメーターを記載する必要がありました。

②アクションを追加する

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

一個ずつ追加

        post :create_many_schedule, on: :collection
        post :delete_many_schedule, on: :member

まとめて追加

member do
    get 'preview'
    get 'sample'
  end
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

  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

     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を付与して管理することができました!

参考文献

2.10 RESTfulなアクションをさらに追加する
パラメーターが配列の場合、ストパラのparams.permitに含める方法
railsのroutes.rbのmemberとcollectionの違いは?
トランザクション

0
0
0

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
0
0