# Sort without Ransack
[![hackmd-github-sync-badge](https://hackmd.io/g8X3rAaFRXu84DYKWi7jew/badge)](https://hackmd.io/g8X3rAaFRXu84DYKWi7jew)
<img src="https://user-images.githubusercontent.com/37478830/194869304-c70b8392-995f-43eb-81b7-6a4affba3975.png" alt="Ruby on Rails" />
## 1. Environment
* Ubuntu 20.04.5 LTS
* ruby 3.1.2
* Rails 7.0.4
## 2. Requirements
* Sort data by `学生コード (student_code)`, `学生名 (name)`, `学年 (grade_id)` in `students` table
* Sustain the search result
* Properly modularize the function to apply to other pages in the future
## 3. Custom Helpers
### 3-1. StudentHelper
Implement custom helpers for each model.
```ruby
module StudentHelper
def student_sort_link(column)
search_params = search_students_params.empty? ? {} : { search_students_form: search_students_params }
sort_link(Student.human_attribute_name(column), column, search_params)
end
end
```
* Take column as argument
* Return an empty hash if search form parameter is empty or return a hash including key and value of the search result
* Pass column to the common method `sort_link`
* 1st argument: String with a link for sorting localised in Japanese
* 2nd argument: Generate a query string `column=[column]`
* 3rd argument: A hash of key and value of search from parameter
### 3-2. ApplicationHelper
Implement a common procedure.
```ruby
module ApplicationHelper
def sort_link(column_name, column, **additional_params)
if params[:column] != column.to_s || params[:direction].nil?
link_to column_name, { column: column, direction: :asc, **additional_params }
elsif params[:column] == column.to_s && params[:direction] == 'asc'
link_to "#{column_name} ▲", { column: column, direction: :desc, **additional_params }
elsif params[:column] == column.to_s && params[:direction] == 'desc'
link_to "#{column_name} ▼", { column: column, direction: :asc, **additional_params }
end
end
end
```
* Receive the search result in 3rd argument as a variable one
* Here are three conditions
* The sorted column is not equal to the one you try to sort, or no column is sorted
* => Sort the column in asc
* The sorted column is equal to the one you try to sort, and the column is sorted in asc
* => Sort the column in desc and `▲` appears
* The sorted column is equal to the one you try to sort, and the column is sorted in desc
* => Sort the column in asc and `▼` appears
## 4. Controllers
Run SQL with the query string.
```ruby
def index
@students = Student.search(@search_form).order(sort_column => sort_direction).preload(:grade)
end
...
private
def sort_column
params[:column].in?(%w(student_code name grade_id)) ? params[:column] : :id
end
def sort_direction
params[:direction].in?(%w(asc desc)) ? params[:direction] : :asc
end
```
* `order` receives `column to sort => asc/desc` as a hash
* `sort_column`: If the column exists in the white list, it is assigned to the key of `order`. If not, `id` is allotted.
* `sort_direction`: If the sorting direction is in the white list, it is assigned to the value of `order`. If not, `asc` is allotted.
## 5. Views
Take symbols as arguments as follows.
```html
<th class="col-sm-2"><%= student_sort_link(:user_code) %></th>
<th class="col-sm-3"><%= student_sort_link(:name) %></th>
<th class="col-sm-2"><%= student_sort_link(:grade_id) %></th>
```
## 6. Sort by student_code
* Default: No query string
<img src="https://user-images.githubusercontent.com/37478830/194869307-94ff8e33-5850-44d7-b490-1b4472170e25.png" alt="Default" />
***
* Asc: `?column=user_code&direction=asc`
<img src="https://user-images.githubusercontent.com/37478830/194869311-1cf9e6f8-4b78-4d23-be00-f201f658b588.png" alt="Ascendimg Order" />
***
* Desc: `?column=user_code&direction=desc`
<img src="https://user-images.githubusercontent.com/37478830/194869316-15fb9bdd-460e-4d55-8a5a-888240277123.png" alt="Descendimg Order" />