#はじめに
Qiita初投稿です。
アプリ作る際に一括でデータの登録をしたくて、activerecord-importのgemを導入して使ってみたので、その使い方について書いてみようと思います。間違い等あればご指摘いただけるとありがたいです。
bulk_insertはRails6では標準サポートされているようです。
開発環境
- Ruby2.5.1
- Rails5.2.4.2
- Haml
- Sass
今回実装した機能の概要
CRM(顧客管理)を作ってます。一斉DMを送るなど、複数の顧客に対して一括のデータを登録します。
モデル
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();
});
});
#最後に(気になっているところ)
- 配列に入れるのはモデルにメソッド書いたほうが良かったかもしれないです。
#参考にした記事
https://qiita.com/makicamel/items/b6d4f3d2661fc66103ed