Edit in JSFiddle

// include: lodash 2.2.1
const data = [
  { id: 1, name: 'rikko' },
  { age: [20, 30, 40], email: 'test@example.com' }
];

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と書く
-->