It is a search function like this. This time, we will extract the column named name from the table called shops and display it in the view.
--Asynchronous --Search and draw each time you type a character --Click the search result to link to the corresponding page
Probably, I think that the knowledge level and common sense level in programming for beginners are much lower than those thought by experienced people. So, I think I'll write as much as I can, "Is it necessary to explain such a thing?"
mac Ruby 2.5.1 Rails 5.2.3 jQuery
First, the files required for implementation are summarized below.
--Preparation of ** controller ** that defines the action to search
app/controllers/shops_controller.rb
def search
end
--Preparation of ** json.jbuilder ** corresponding to the above action
ruby:views/shops/search.json.jbuilder
#Pay attention to directory relations and file names to correspond to the controller and action created above
#In this case, views/shops(Corresponds to the controller name)/search(Corresponds to action name).json.jbuilder
--Preparing ** Routing ** for the above actions
config/route.rb
resources :shops do #in the shops controller
collection do
get 'search' #search action
end
end
--Preparing a ** view ** file to display the search form and results
ruby:app/views/shops/index.html.haml
#This time, the search is displayed on the shops list screen.
#I will write using haml, but it can be normal html or slim.
-** js ** File preparation
app/assets/javascripts/search.js
#.The name can be anything as long as it ends with js
As mentioned above, we will implement the search function using 5 files.
The flow of the search process is as follows.
○○.html.haml(○○.html.erb) → ○○.js
○○.js → ○○_controller
○○_controller → ○○.json.jbuilder
○○.json.jbuilder → ○○.js → ○○.html.haml
If you don't know the process flow, you can't deal with an error and waste an hour or two. I will explain as much as possible in the actual code that I will write, so please read it with the above processing flow in mind.
Let's get started.
This time, as an example, set the ** search ** action inside ** shops_controller **.
app/controllers/shops_controller.rb
def search
end
config/route.rb
resources :shops do #in the shops controller
collection do
get 'search' #search action
end
end
ruby:app/views/shops/index.html.haml
.search-field
.fas.fa-search #I'm using fontawesome with magnifying glass.
.shop_search
= f.text_field :text, placeholder: "Search by store / address", id: "shop_search" #A text input field is set up.
#shop_search--result ← shop instead of commenting out_search--The id name is result. Display search results.
.shop-search-list
app/assets/javascripts/search.js
$("#shop_search").on("keyup", function(){
let input = $("#shop_search").val();
$.ajax({
type: 'GET',
url: '/shops/search',
data: {keyword: input},
dataType: 'json'
})
First, you will receive the information entered in the search form (f.text_field in the haml file) as a js file. ┗ Specify the id name given to the search form, and get the information with key up the moment you speak your finger from the keyboard when entering characters.
The information below ajax ·how ·where ·what ・ In what condition Specify whether to send.
In this case, I think that the GET method will send the input to the search action in the shops controller in the json method.
app/controllers/shops_controller.rb
def search
return nil if params[:keyword] == ""
@shops = Shop.where('name LIKE ? OR location LIKE ?', "%#{params[:keyword]}%", "%#{params[:keyword]}%").limit(10)
respond_to do |format|
format.html
format.json
end
end
This time I set the name (store name) column and location (location) column when creating the shops table, so I set it so that I can search with these two information, For example, if you want to search by store name only,
app/controllers/shops_controller.rb
def search
return nil if params[:keyword] == ""
@shops = Shop.where('name LIKE ?, "%#{params[:keyword]}%").limit(10)
respond_to do |format|
format.html
format.json
end
end
Is OK.
** params [: keyword] ** in the action comes from data: {keyword: input} under ajax in the previous js file. It may be difficult to understand, but it means that the characters entered in the search field are treated as input in the js file and as keywords in the controller file. If nothing is entered in the search field (second line ""), nil is returned.
Also, in the 3rd line, the shops table pulls out information from the DB based on that keyword (character entered in the search field). This time, the specification is to perform a partial match search by enclosing the quantity end of params [: keyword] in **% **. For other search methods, please refer to this article.
-Rails-Ambiguous search for characters using LIKE clause (when you want to search for words containing specific characters) I also referred to this article. Thank you very much.
And since the character data entered this time is in the controller in json format, it moves to jbuilder.
ruby:search.json.jbuilder
json.array! @shops do |shop|
json.name shop.name
json.location shop.location
end
I extracted the information from the DB in the controller, but I need to convert this data to json format. Do that with jbuilder.
First of all, the processing by the controller is completed under the js file ajax earlier, and the processing when returning is added.
app/assets/javascripts/search.js
$("#shop_search").on("keyup", function(){
let input = $("#shop_search").val();
$.ajax({
type: 'GET',
url: '/shops/search',
data: {keyword: input},
dataType: 'json'
})
.done(function(shops){
$("#shop_search--result").empty();
if (shops.length !== 0) {
shops.forEach(function(shop){
addShop(shop);
});
}
else if (input.length == 0){
return false;
} else {
addNoShop();
}
});
});
Below .done is the process.
Then, addShop and addNoShop are drawn in html respectively.
Below is the full js file.
app/assets/javascripts/search.js
$(function(){
function addShop(shop) {
let html = `
<a href="/shops/${shop.id} class="shop_search-list">
<div>${shop.name} - ${shop.location}</div>
</a>
`;
$("#shop_search--result").append(html);
};
function addNoShop(){
let html =`There is no shop`
$("#shop_search--result").append(html);
};
$("#shop_search").on("keyup", function(){
let input = $("#shop_search").val();
$.ajax({
type: 'GET',
url: '/shops/search',
data: {keyword: input},
dataType: 'json'
})
.done(function(shops){
$("#shop_search--result").empty();
if (shops.length !== 0) {
shops.forEach(function(shop){
addShop(shop);
});
}
else if (input.length == 0){
return false;
} else {
addNoShop();
}
})
});
});
Specify the standard when drawing as let html. This time, I tried to link to the details page when I clicked on the search result.
Insert the fixed phrase (html) created by using append in the place (#shop_search--result) where the search result is displayed in the haml file.
This completes the asynchronous search function (incremental search).
This content was created by trying the content learned at school by myself and deepening my understanding. At the beginning of the study, I was hoping that I could do it with a half-hearted understanding, but when I started from 1 on my own, I often stopped working. It is a reflection.
I think the point is to understand where and how each file changes. Also, as with any function, in this case it is strongly recommended to continue writing while debugging console.log etc.
Recommended Posts