Rails with RANSACK

## Rails with RANSACK
[前回の投稿](https://qiita.com/tsunemiso/items/edbc58becf55875c4fdb)でなんとか、CRUDの基本的なところまでModal Formを使用した構成で実現できました！
今回は、登録・更新されたテーブルに対して、一覧検索機能をつけたいと思いました。

## 要件

* 一覧画面に一覧検索機能を付加する
* 検索要件
  * User.id：完全一致
  * User.name：前方後方部分一致
  * User.created_at:以上・以下範囲検索
  * User.updated_at:以上・以下範囲検索

## なぜRANSACK？

Google先生に「Rails 一覧検索」みたいな感じでお伺いを立てましたが、当たり前ですが、ActiveRecordの#where()であったり、を書かなくてはならないようでした。確かにそれでも問題ないのですが、SQLをなるべくなら書きたくないということで、漁ったところRANSACKというGemに出会いました。

## いざRANSACK

では導入してみましょう

### Gemfile

```bash:Gemfile
gem 'ransack'
```
と記載し、

```bash:terminal
$ bundle install
```
しましょう。

### form.html.erb

```erb:form.html.erb
<%= search_form_for @q do |f| %>
	<div class="form-group">
		<%= f.label :name_cont, "name", class: "font-weight-bold" %>
		<%= f.search_field :name_cont, class: "form-control" %>
	</div>
	<%= f.submit sanitize('<i class="fa fa-search"></i> Search'), class: "btn btn-dark" %>
<% end %>
```

注意点として

* form_forの代わりに**search_form_for**を使用すること
* [カラム名]_[検索条件]で検索条件を指定します。

## 検索条件の指定

```ruby:_eq
User.ransack(name_eq: "test").result
# SELECT users.* FROM users WHERE users.name = 'test';
```
```ruby:_not_eq
User.ransack(name_not_eq: "test").result
# SELECT users.* FROM users WHERE users.name != 'test';
``` 

```ruby:_matches
User.ransack(name_matches: "test").result
# SELECT users.* FROM users WHERE users.name LIKE 'test';

User.ransack(name_matches: "test%").result
# SELECT users.* FROM users WHERE users.name LIKE 'test%';
```

```ruby:_does_not_match
User.ransack(name_does_not_match: "test").result
# SELECT users.* FROM users WHERE users.name NOT LIKE 'test';
```

```ruby:_matches_any
User.ransack(name_matches_any: "test").result
# SELECT users.* FROM users WHERE ( users.name LIKE 'test' );
User.ransack(name_matches_any: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name LIKE 'test' OR users.name LIKE 'hoge' );
```

```ruby:_matches_all
User.ransack(name_matches_all: "test").result
# SELECT users.* FROM users WHERE ( users.name LIKE 'test' );
User.ransack(name_matches_all: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name LIKE 'test' AND users.name LIKE 'hoge' );
```

```ruby:_does_not_match_any
User.ransack(name_does_not_match_any: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name NOT LIKE 'test' OR users.name NOT LIKE 'hoge' );
```

```ruby:_does_not_match_all
User.ransack(name_does_not_match_all: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name NOT LIKE 'test' AND users.name NOT LIKE 'hoge' );
```

```ruby:_lt
User.ransack(created_at_lt: "2019-01-01 00:00:00").result
# SELECT users.* FROM users WHERE users.created_at < '2019-01-01 00:00:00';
```

```ruby:_lteq
User.ransack(created_at_lteq: "2019-01-01 00:00:00").result
# SELECT users.* FROM users WHERE users.created_at <= '2019-01-01 00:00:00';
```

```ruby:_gt
User.ransack(created_at_gt: "2019-01-01 00:00:00").result
# SELECT users.* FROM users WHERE users.created_at > '2019-01-01 00:00:00';
```

```ruby:_gteq
User.ransack(created_at_gteq: "2019-01-01 00:00:00").result
# SELECT users.* FROM users WHERE users.created_at >= '2019-01-01 00:00:00';
```

```ruby:_present
User.ransack(name_present: 1).result
# SELECT users.* FROM users WHERE ( users.name IS NOT NULL AND users.name != '' );
# _presentは文字列のカラムのみ使用可能(NOT NULLかつ非空文字)
```

```ruby:_blank
User.ransack(name_blank: 1).result
# SELECT users.* FROM users WHERE ( users.name IS NULL OR users.name = '' );
# _blankはNULLまたは空文字
```

```ruby:_null
User.ransack(name_null: 1).result
# SELECT users.* FROM users WHERE users.name IS NULL;
```

```ruby:_not_null
User.ransack(name_not_null: 1).result
# SELECT users.* FROM users WHERE users.name IS NOT NULL;
```

```ruby:_in
User.ransack(name_in: "test").result
# SELECT users.* FROM users WHERE users.name IN ( 'test' );
User.ransack(name_in: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE users.name IN ( 'test', 'hoge' );
```

```ruby:_not_in
User.ransack(name_not_in: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE users.name NOT IN ( 'test', 'hoge' );
```

```ruby:_lt_any
User.ransack(created_at_lt_any: ["2019-01-01 00:00:00", "2018-01-01 00:10:00"]).result
# SELECT users.* FROM users WHERE ( users.created_at < '2019-01-01 00:00:00' OR users.created_at < '2018-01-01 00:10:00' )
```

```ruby:_lteq_any
User.ransack(created_at_lteq_any: ["2019-01-01 00:00:00", "2018-01-01 00:10:00"]).result
# SELECT users.* FROM users WHERE ( users.created_at <= '2019-01-01 00:00:00' OR users.created_at <= '2018-01-01 00:10:00' );
```

```ruby:_gt_any
User.ransack(created_at_gt_any: ["2019-01-01 00:00:00", "2018-01-01 00:10:00"]).result
# SELECT users.* FROM users WHERE ( users.created_at > '2019-01-01 00:00:00' OR users.created_at > '2018-01-01 00:10:00' )
```

```ruby:_gteq_any
User.ransack(created_at_gteq_any: ["2019-01-01 00:00:00", "2018-01-01 00:10:00"]).result
# SELECT users.* FROM users WHERE ( users.created_at >= '2019-01-01 00:00:00' OR users.created_at >= '2018-01-01 00:10:00' );
```

```ruby:_matches_any
User.ransack(name_matches_any: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name LIKE 'test' OR users.name LIKE 'hoge' );
```

```ruby:_lt_all
User.ransack(created_at_lt_all: ["2019-01-01 00:00:00", "2018-01-01 00:10:00"]).result
# SELECT users.* FROM users WHERE ( users.created_at < '2019-01-01 00:00:00' AND users.created_at < '2018-01-01 00:10:00' );
```

```ruby:_lteq_all
User.ransack(created_at_lteq_all: ["2019-01-01 00:00:00", "2018-01-01 00:10:00"]).result
# SELECT users.* FROM users WHERE ( users.created_at <= '2019-01-01 00:00:00' AND users.created_at <= '2018-01-01 00:10:00' );
```

```ruby:_gt_all
User.ransack(created_at_gt_all: ["2019-01-01 00:00:00", "2018-01-01 00:10:00"]).result
# SELECT users.* FROM users WHERE ( users.created_at > '2019-01-01 00:00:00' AND users.created_at > '2018-01-01 00:10:00' );
```

```ruby:_gteq_all
User.ransack(created_at_gteq_all: ["2019-01-01 00:00:00", "2018-01-01 00:10:00"]).result
# SELECT users.* FROM users WHERE ( users.created_at >= '2019-01-01 00:00:00' AND users.created_at >= '2018-01-01 00:10:00' );
```

```ruby:_matches_all
User.ransack(name_matches_all: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name LIKE 'test' AND users.name LIKE 'hoge' );
```

```ruby:_does_not_match_all
User.ransack(name_does_not_match_all: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name NOT LIKE 'test' AND users.name NOT LIKE 'hoge' );
```

```ruby:_start
User.ransack(name_start: "test").result
# SELECT users.* FROM users WHERE users.name LIKE 'test%';
```

```ruby:_not_start
User.ransack(name_not_start: "test").result
# SELECT users.* FROM users WHERE users.name NOT LIKE 'test%';
```

```ruby:_start_any
User.ransack(name_start_any: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name LIKE 'test%' OR users.name LIKE 'hoge%' );
```

```ruby:_start_all
User.ransack(name_start_all: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name LIKE 'test%' AND users.name LIKE 'hoge%' );
```

```ruby:_not_start_any
User.ransack(name_not_start_any: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name NOT LIKE 'test%' OR users.name NOT LIKE 'hoge%' );
```

```ruby:_not_start_all
User.ransack(name_not_start_all: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name NOT LIKE 'test%' AND users.name NOT LIKE 'hoge%' );
```

```ruby:_end
User.ransack(name_end: "test").result
# SELECT users.* FROM users WHERE users.name LIKE '%test';
```

```ruby:_not_end
User.ransack(name_not_end: "test").result
# SELECT users.* FROM users WHERE users.name NOT LIKE '%test';
```

```ruby:_end_any
User.ransack(name_end_any: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name LIKE '%test' OR users.name LIKE '%hoge' );
```

```ruby:_end_all
User.ransack(name_end_all: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name LIKE '%test' AND users.name LIKE '%hoge' );
```

```ruby:_not_end_any
User.ransack(name_not_end_any: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name NOT LIKE '%test' OR users.name NOT LIKE '%hoge' );
```

```ruby:_not_end_all
User.ransack(name_not_end_all: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name NOT LIKE '%test' AND users.name NOT LIKE '%hoge' );
```

```ruby:_cont
User.ransack(name_cont: "test").result
# SELECT users.* FROM users WHERE users.name LIKE '%test%' ;
```

```ruby:_cont_any
User.ransack(name_cont_any: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name LIKE '%test%' OR users.name LIKE '%hoge%' );
```

```ruby:_cont_all
User.ransack(name_cont_all: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name LIKE '%test%' AND users.name LIKE '%hoge%' );
```

```ruby:_not_cont
User.ransack(name_not_cont: "test").result
# SELECT users.* FROM users WHERE users.name NOT LIKE '%test%' ;
```

```ruby:_not_cont_any
User.ransack(name_not_cont_any: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name NOT LIKE '%test%' OR users.name NOT LIKE '%hoge%' );
```

```ruby:_cont_all
User.ransack(name_not_cont_all: ["test", "hoge"]).result
# SELECT users.* FROM users WHERE ( users.name NOT LIKE '%test%' AND users.name NOT LIKE '%hoge%' );
```

```ruby:_true
```

```ruby:_false
```