LoginSignup
0
1

More than 3 years have passed since last update.

activerecord-importを使った一括登録について

Posted at

はじめに

Qiita初投稿です。

アプリ作る際に一括でデータの登録をしたくて、activerecord-importのgemを導入して使ってみたので、その使い方について書いてみようと思います。間違い等あればご指摘いただけるとありがたいです。

bulk_insertはRails6では標準サポートされているようです。

開発環境

  • Ruby2.5.1
  • Rails5.2.4.2
  • Haml
  • Sass

今回実装した機能の概要

CRM(顧客管理)を作ってます。一斉DMを送るなど、複数の顧客に対して一括のデータを登録します。
ab73ba83eed44a1b04abeb7f083b020d.gif

モデル

client(顧客)モデルとcontact(顧客に対してのコンタクト)モデルがあり、ネスティングさせています。

client.rb
 has_many :contacts
contact.rb
 belongs_to :client

コントローラー(該当部分のみ抜粋)

一括登録のためのbulk_insertアクションを作成しました。client_idを配列で取っています。1つずつ配列に入れて、importします。

clients_controller.rb
  def bulk_insert
    contact_array=[]
    bulk_params[:client_ids].each do |cid|
      contact=Contact.new(act_cat_id: bulk_params[:act_cat_id],detail: bulk_params[:detail],start_date: bulk_params[:start_date],end_date: bulk_params[:end_date],in_progress: bulk_params[:in_progress],client_id: cid)
      contact_array << contact
    end
    Contact.import contact_array
    redirect_to clients_path
  end

  private
  def bulk_params
    params.require(:contact).permit(:act_cat_id,:detail,:start_date,:end_date,:in_progress,{:client_ids => []})
  end

ルーティング

routes.rb
Rails.application.routes.draw do
  devise_for :users
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  root to: 'clients#index'
  resources :clients do
    resources :contacts
    collection do
      post :bulk_insert
    end
  end
end

ビュー(該当部分のみ抜粋)

下から2行目のところにJSで登録するユーザーを追加していく形です。

_main-contact-register-at-once.html.haml
.main-header
  .main-title
    コンタクト一括登録
.main-contents
  .form
    =form_with model:@contact, url:bulk_insert_clients_path,local: true do |f|
      .input-field
        = f.label 'カテゴリ', for: "act_cat"
        = f.collection_select :act_cat_id, ActCat.all, :id, :category, {include_blank: true},{id: "act_cat"}
      .input-field
        = f.label '詳細', for: "detail"
        = f.text_field :detail, id: "detail"
      .input-field
        = f.label '開始日', for: "start_date"
        = f.date_field :start_date, id: "start_date"
      .input-field
        = f.label '終了日', for: "end_date"
        = f.date_field :end_date, id: "end_date"
      .input-field
        = f.label '進行中'
        = f.select :in_progress,[["進行中",1], ["完了",0]],{},{id: "in_progress"}
      .register-wrapper
        .register-list
          .register-list__title
            クライアント一覧
          .register-list__box
            %table
              %tbody#client-list
                - @clients.each do |client|
                  %tr.register-list__element.client-list{data: {id: "#{client.id}",name: "#{client.client_name1+client.client_name2}"}}
                    %td
                      =client.client_name1 + client.client_name2
                    %td
                      
        .register-list
          .register-list__title
            登録するクライアント
          .register-list__box
            %table
              %tbody#register-list
      = f.submit '登録',class: "form-btn" 

JavaScript

hiddenでclient_idのテキストフィールドを追加しています。

contact.js
$(function(){
  function addClient(clientId,clientName){
    var html = `<tr class="register-list__element candidate-list" data-id=${clientId} data-name=${clientName}>
                  <td>
                    ←
                  </td>
                  <td>
                    <input name='contact[client_ids][]' type='hidden' value='${clientId}'>
                  </td>
                  <td>
                    ${clientName}
                  </td>
                </tr>`
    return html;
  }
  function removeClient(clientId,clientName){
    var html = `<tr class="register-list__element client-list" data-id=${clientId} data-name=${clientName}>
                  <td>
                    ${clientName}
                  </td>
                  <td>
                    →
                  </>
                </tr>`
    return html;
  }
  $(document).on('click','tr.register-list__element.client-list',function(){
    $('#client-list').val();
    var clientId = (this).dataset.id;
    var clientName = (this).dataset.name;
    console.log(clientName);
    html = addClient(clientId,clientName);
    $('#register-list').append(html);
    $(this).remove();
  });
  $(document).on('click','tr.register-list__element.candidate-list',function(){
    $('#register-list').val();
    var clientId = (this).dataset.id;
    var clientName = (this).dataset.name;
    console.log(clientName);
    html = removeClient(clientId,clientName);
    $('#client-list').append(html);
    $(this).remove();
  });

});

最後に(気になっているところ)

  • 配列に入れるのはモデルにメソッド書いたほうが良かったかもしれないです。

参考にした記事

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