// include: lodash 2.2.1 const data = [ { id: 1, name: 'rikko' }, { age: [20, 30, 40], email: '[email protected]' } ]; class Ransack { constructor (data) { this.data = data } /** * 連想配列を配列に変換 * ex. [{ id: 1, name: 'rikko' }, { age: [20, 30, 40 ]} ] * → [ [{key: 'id', val: 1}, {key: 'name', val: 'rikko'}], {key: 'age', val: [20,30,40]} ] * @param target * @return [[{key: *, val: *}, {key: *, val: *}], {key: *, val: *}] **/ _toArray (target) { const r = []; target.forEach(a => { const _r = []; for (let b in a) { _r.push({ key: b, val: a[b] }); } r.push(_r); }); return r; } /** * 配列をDSLに変換 * @param target * @return DSL **/ _format (target, isRecursion) { const r = {}; target.forEach((a, i) => { if (isRecursion) { r['[m]'] = 'or'; } else { r['g[m]'] = 'or'; } _.forEach(a, (b, j) => { if (b.val && _.isArray(b.val)) { const _t = []; const data = b.val.map(c => { return { key: b.key, val: c}; }); _t.push(data); const _r = this._format(_t, true); _.forEach(_r, (v, k) => { r[`g[${i}]${k}`] = v; }); } else { const key = isRecursion ? `[g[${j}][${b.key}_eq]]` : `g[${i}][${b.key}_eq]`; r[key] = b.val; } }); }); return r; } /** * 連想配列をRansackDSLに変換 * ※検索条件の配列指定は1つのみ(順序は関係ない) this._formatの実装問題 * ex. [{key: id, val: 10}] → {q[g[m]]: 'or', q[g[0][id_eq]]: 10} * @param _toArray * @return {q[g[m]]: 'or', q[g[0][*_eq]]: *} **/ convertToDSL () { if (_.size(this.data) === 0) { return {}; } const a = this._toArray(this.data); const f = this._format(a); const r = {}; for (let a in f) { r[`q[${a}]`] = f[a]; } return r; } } const app = document.getElementById('app'); const d = (new Ransack(data)).convertToDSL(); app.innerText = JSON.stringify(d, null, ' ');
<pre id="app"></pre> <!-- JSONをRansack用DSLに変換するライブラリ ## 変換元 [ { id: 1, name: 'rikko' }, { age: [20, 30, 40] } ] ## 変換後の構造 q: { g: { m: 'or', '0' => { id_eq: 1, name_eq: 'rikko' }, '1' => { g: { m: 'or', '0' => { age_eq: 20 }, '1' => { age_eq: 30 }, '2' => { age_eq: 40 } } } } } ## 変換後のクエリ { q[g[m]]: 'or', q[g[0][id_eq]]: 1, q[g[0][name_eq]]: 'rikko' q[g[1][g[m]]]: 'or', q[g[1][g[0][age_eq]]]: 20, q[g[1][g[1][age_eq]]]: 30, q[g[1][g[2][age_eq]]]: 40, } ※ _in を使わないのは、連想配列だと同じキーで異なる値を設定できないため ※ 本来は q[g[age_in]][]: 20, q[g[age_in]][]: 30, q[g[age_in]][]: 40と書く -->