This portfolio is currently being highly acclaimed, and last time we implemented an ambiguous search function. So, next, I created it with the intention of implementing a search function using gem's ransack. There were many articles that could be helpful, but even so, searching with checkboxes was quite clogged, so I'd like to mention it as a reference for someone.
Please refer to the previous article if necessary. [Rails] How to add fuzzy search function
ruby 2.6.5 Rails 6.0.3.2 haml used
1, introduction of gem 2, create a view of the search form 3, set to controller 4, create a view of search results
There are four steps.
First, let's put in a gem quickly.
Gemfile.
gem 'ransack'
It is desirable to list it at the bottom so that there are no strange mistakes.
After inputting,
Don't forget to do % bundle install
in your terminal% rails s
.
Don't forget that it will not be reflected unless you rails s
!
This completes the gem installation.
First, from the code The composition consists of (1) keyword search, (2) price search, (3) status search, and (4) shipping charge search.
index.html.haml
.title-box
%p.title Advanced search
.detail_search--box
= search_form_for(@q,url: detail_search_items_path) do |f|
.detail-keyword
.detail-keyword--box
%i.fas.fa-plus
%p.Add wd keyword
= f.search_field :name_cont, placeholder: "Example) Bike", class: "detail-keyword--form"
.detail-price
.detail-price--label
%i.fas.fa-coins
%p.wd price
.detail-price--forms
= f.search_field :price_gteq, placeholder: "¥ 300 or more", min:300, class: "price-min"
%p.wd 〜
= f.search_field :price_lteq, placeholder: "¥ 9999999 or less", max:9999999, class: "price-max"
.detail-status
.detail-status--label
%i.fas.fa-paperclip
%p.wd product status
.detail-status--checkbox
.checkboxes
= f.check_box :status_id_eq_any, { multiple: true }, 1, ''
= 'New, unused'
.checkboxes
= f.check_box :status_id_eq_any, { multiple: true }, 2, ''
= 'Nearly unused'
.checkboxes
= f.check_box :status_id_eq_any, { multiple: true }, 3, ''
= 'No noticeable scratches or stains'
.checkboxes
= f.check_box :status_id_eq_any, { multiple: true }, 4, ''
= 'Slightly scratched and dirty'
.checkboxes
= f.check_box :status_id_eq_any, { multiple: true }, 5, ''
= 'There are scratches and dirt'
.checkboxes
= f.check_box :status_id_eq_any, { multiple: true }, 6, ''
= 'Overall poor condition'
.detail-deliveryFee
.detail-deliveryFee--label
%i.fas.fa-truck
%p.wd shipping charges
.detail-deliveryFee--checkbox
.checkboxes
= f.check_box :delivery_fee_id_eq_any, { multiple: true }, 1, ''
= 'postage included(Exhibitor burden)'
.checkboxes
= f.check_box :delivery_fee_id_eq_any, { multiple: true }, 2, ''
= 'Cash on delivery(Buyer burden)'
.detail-btn
= f.submit "Search", class: "sbt-btn"
Now, let's explain the code.
・= search_form_for(@q,url: detail_search_items_path) do |f|
When creating a normal form, use form_for and form_with, but when creating a search form with Lansack, use the search_form_for method </ b>.
Well, if you use Ransack, you should understand that you should use search_form_for.
Next, I took @q as an argument of search_form_for. We will search based on the query information of @q. This will be defined later in the controller.
And, regarding the url setting part, this is the path to the location where the search results are displayed, so please change it as appropriate. This time, the search results are displayed in detail_search.html.haml
, so write the plefix set by routing. When writing plefix as a path, add _path to the end of the character.
To find out, use % rails routes
in the terminal.
① Search by keyword
This part in code
.detail-keyword
.detail-keyword--box
%i.fas.fa-plus
%p.Add wd keyword
= f.search_field :name_cont, placeholder: "Example) Bike", class: "detail-keyword--form"
The characteristic of the search using Ransack is the _cont
part of the ": name_cont" that follows.
By the way,: name is the column name. So please change it accordingly. In addition, which table (model) column data to acquire is set by the controller.
Returning to the story, this means doing a partial match search using the Like clause on the name column. To make it easier to understand and imagine, it means to search and extract data that contains the keyword (for example) mandarin orange in the name column.
The _cont part is called a predicate in Ransack, and I will list some predicates that are likely to be used frequently.
predicate | meaning |
---|---|
*_eq | Extract the exact match. |
*_in | Extracts what is contained in the given array. |
*_cont | Extracts those that contain strings. |
*_lteq | Extracts less than a certain value. |
*_gteq | Extracts anything larger than a certain value. |
② Search by price This part in code
.detail-price
.detail-price--label
%i.fas.fa-coins
%p.wd price
.detail-price--forms
= f.number_field :price_gteq, placeholder: "¥ 300 or more", min:300, class: "price-min"
%p.wd 〜
= f.number_field :price_lteq, placeholder: "¥ 9999999 or less", max:9999999, class: "price-max"
What needs to be explained here is the _gteq
part of": price_gteq "and the _lteq
part of ": price_lteq" that follow.
This is also written in the table above,
_gteq
extracts more than a certain value,
_lteq
means to extract less than a certain value.
The point is to extract the price column that is larger than 300 (for example) and smaller than 2000.
③ Status search This part in code
.checkboxes
= f.check_box :status_id_eq_any, { multiple: true }, 1, ''
= 'New, unused'
(Omitted)
.checkboxes
= f.check_box :status_id_eq_any, { multiple: true }, 6, ''
= 'Overall poor condition'
It's a bit confusing here, or it may be a poor explanation because I don't understand it properly.
First of all, it is the _eq_any
part of": status_id_eq_any "at the back.
The _eq
part, as it is also written in the table above,
_eq
means to extract the exact match. Then, when you say _any
, you have to add this if there are multiple cases. This time, there are 6 checkboxes, so it is _eq_any
.
And "multiple: true" is also needed for the same reason. If you use multiple checkboxes, you must include this. By describing this, the variables of the data will be recognized as an array.
The data actually sent as parameters: ["1", "", "", "", "", ""]
The ones listed in numbers are the ones with checked checkboxes.
In short, if you use multiple checkboxes, remember to add _any
and enter multiple: true
.
Next is the 1,''
part.
This means that if the checkbox is checked, it will return the data 1, and if the checkbox is not checked, it will return ''
.
''
? ?? I wonder what it is, but the point is that I will not send any data because the check box was not checked. Isn't it easier to say that it's empty?
So, the meaning of this number is the id number this time.
This time, I used a gem called ActiveHash to put data like this.
↓↓↓
The number will be the number of this id.
ActiveHash can be easily done by looking at this article. I tried to create prefecture data with Rails gem'active_hash'
To explain again using the data sent by the parameters, ["1", "", "", "", "", ""] Only the new and unused checkboxes with id: 1 are checked, and the remaining 5 are unchecked, so it is''. Therefore, the data that matches the data of new and unused in the status_id column is extracted.
I hope you can understand this somehow.
First, from the code
item_controller.rb
def index #index is the view of the search form
@q = Item.ransack(params[:q])
end
def detail_search #detail_search is a view of search results
@q = Item.ransack(params[:q])
@items = @q.result(distinct: true)
end
If you receive the parameters received in the search form with params [: q]
and set ʻItem.ransack (params [: q]), create an object of the search result based on the received parameters (search data). Can be done. Then, for that object, you can get the search results by setting
@items = @ q.result`.
It's hard to understand, but it's okay if you can recognize that you are receiving the input data, creating a search object, and outputting the search results.
And about distinct: true
, distinct is a feature in SQL that eliminates duplication. By setting it to true, you can eliminate duplicate contents from the result.
After that, you can create a view of the search results (here, the file is detail_search.html.haml
) and output it using the each method.
detail_search.html.haml
.contents__box
- @items.each do |item|
Below this, please make it in light of what you are making now.
I will also attach SCSS for the time being.
*****.scss
.title-box{
width: 40%;
height: 60px;
border: 1px solid #EEEEEE;
background-color: red;
box-shadow: 1px 1px 1px rgba(1,0,0,0.4);
margin-left: 40%;
margin-top: 40px;
padding: 14px 3px 0 0;
.title{
color: #fff;
font-size: 20px;
font-weight: bold;
text-align: center;
}
}
.detail_search--box{
margin-left: 40%;
margin-top: 5px;
width: 40%;
border: 1px solid #EEEEEE;
background-color: #fff;
box-shadow: 1px 1px 1px rgba(1,0,0,0.1);
.detail-keyword{
margin-top: 20px;
&--box{
display: flex;
margin-left: 15px;
.fa-plus{
margin: 3px 5px 0 0;
}
}
&--form{
width: 90%;
height: 40px;
margin-left: 15px;
margin-top: 5px;
padding-left: 5px;
border: 1px solid #cccccc;
border-radius: 5px 5px 5px 5px / 5px 5px 5px 5px;
}
}
.detail-price{
margin-top: 25px;
&--label{
display: flex;
margin-left: 15px;
.fa-coins{
margin: 3px 5px 0 0;
}
}
&--forms{
margin-top: 5px;
.price-min{
width: 90%;
height: 40px;
margin-left: 15px;
border: 1px solid #cccccc;
border-radius: 5px 5px 5px 5px / 5px 5px 5px 5px;
padding-left: 5px;
}
.wd{
margin-left: 15px;
color: #AAAAAA;
}
.price-max{
width: 90%;
height: 40px;
margin-left: 15px;
border: 1px solid #cccccc;
border-radius: 5px 5px 5px 5px / 5px 5px 5px 5px;
padding-left: 5px;
}
}
}
.detail-status{
margin-top: 25px;
&--label{
display: flex;
margin-left: 15px;
.fa-paperclip{
margin: 3px 5px 0 0;
}
}
&--checkbox{
margin-top: 5px;
.checkboxes{
margin-left: 15px;
}
}
}
.detail-deliveryFee{
margin-top: 25px;
&--label{
display: flex;
margin-left: 15px;
.fa-truck{
margin: 3px 5px 0 0;
}
}
&--checkbox{
margin-top: 5px;
.checkboxes{
margin-left: 15px;
}
}
}
.detail-btn{
margin-top: 20px;
.sbt-btn{
width: 60%;
height: 35px;
margin: 15px 0 20px 45px;
border: none;
border-radius: 10px;
}
.sbt-btn:hover{
opacity: 0.5 ;
background-color: #C0C0C0;
}
}
}
After that, since we are using icons this time, we also need to install gem'font-awesome-sass'
. If you need this, it's easy, so please start from the article below.
rails font-awesome-sass installation method
This should look like the image attached earlier above! Please contact us if there are any deficiencies such as failure to implement!
Thank you very much.
Recommended Posts