This time, the post data (Post) is displayed by performing a keyword search on the search bar. In addition, we will join multiple tables and implement them so that they can be searched within that range.
MacOS 10.15.7 ruby 2.6.5 Ruby on Rails 6.0.0
We have created a table with the user as "User", the post as "Post", the image as "Image", and the prefecture as "Prefecture" (seed data). (The contents of the table are simplified for posting)
The relations are as follows.
user.rb
has_many :posts, dependent: :destory
post.rb
belongs_to :user
belongs_to :prefecture
has_many :images, dependent: :destory
accepts_nested_attributes_for :images, allow_destroy: true
image.rb
belongs_to :post
mount_uploader :image, ImageUploader
prefecture.rb
has_many :posts
It looks like this. I have also introduced user and image, but this time I will omit the explanation because they are not related. Since prefecture has multiple posts, it is set as "has_many: posts". Since post belongs to prefecture, it will be "belongs_to: prefecture".
Create a search bar in this way.
erb:index.html.erb
<%= form_with(url: search_posts_path, local: true, method: :get, class: "rootpageSearchForm") do |form| %>
<%= form.text_field :keyword, placeholder: "Enter a keyword", id: 'Search_Form', class: "rootpageSearchForm__content" %>
<%= form.submit "Search", class: "rootpageSearchForm__bottum" %>
<% end %>
index.scss
.rootpageSearchForm {
width: auto;
&__content {
width: 40vw;
height: 30px;
color: #000000;
border-radius: 5px;
border-color: #008bbb;
}
&__bottum {
margin-left: 0.5vw;
height: 30px;
width: 150px;
border-radius: 20px;
background-color: #87cefa;
border: none;
box-shadow: 0 0 8px gray;
color: #ffffff;
-webkit-transition: all 0.3s ease;
-moz-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
transition: all 0.3s ease;
}
.rootpageSearchForm__bottum:hover {
background-color: #00bfff;
}
}
That is all. The completed image looks like this.
Define a new search action in routes.rb. This time, we will define it in a nested form in the post action. Define it as follows.
routes.rb
Rails.application.routes.draw do
resources :posts do
collection do
get 'search'
end
end
Some of the following are omitted...
end
This time, the corresponding posts are displayed as a list with the search keyword, so id is unnecessary.
collection do
get 'search'
end
Is defined as.
If you need an id (such as a post detail page), define it using member instead of collection. The difference between collection and member is whether the URL has an id or not.
collection ・ ・ ・ The routing does not have an id. member ・ ・ ・ An id is attached to the routing.
class Post < ApplicationRecord
...Part of the above omitted
def self.search(search)
if search != ""
Post.where('content LIKE(?) OR title LIKE(?), "%#{search}%", "%#{search}%")
else
Post.all
end
end
Some of the following are omitted...
end
Use the where method
to get the" instance of the record that matches the condition "in the form of an array based on the condition described in the argument.
I use the LIKE clause
to search for ambiguous strings.
String | meaning |
---|---|
% | Arbitrary character string (including blank character string) |
_ | Any one character |
Execution example
Execution example | meaning |
---|---|
where('title LIKE(?)', "a%") | Titles starting with a |
where('title LIKE(?)', "%b") | Titles ending in b |
where('title LIKE(?)', "d_") | Titles containing c |
where('title LIKE(?)', "%b") | Two-letter title starting with d |
where('title LIKE(?)', "_e") | Two-letter title ending in e |
The argument search contains the parameters sent from the search form.
Therefore, write if search! =" "
, And the condition is that some value is entered in the search form.
If the search button is pressed when nothing is entered in the search form (empty state), the contents of search passed to the argument will be empty, so describe the processing in that case in the else statement.
This time, as Post.all
, all posts will be acquired and displayed.
__ Basically, the method related to the interaction with the table is put in the model! __
Define a search action in posts_controller.rb.
posts_controller.rb
class PostsController < ApplicationController
...Part of the above omitted...
def search
@posts = Post.search(params[:keyword]).order(created_at: :desc)
end
...Some of the following are omitted...
Write params [: keyword]
in the argument of the search method and pass the search result.
Also, since the search results are arranged in the order of newest posts, it is described as order (created_at: desc)
.
After that, create search.html.erb to display the search result screen and it is completed.
ruby:search.html.erb
<div class="wrapper">
<% @posts.each do |post| %>
<div class='contents row'>
...Omitted below...
<% end %>
</div>
You can now view the search results using the search bar and keyword search. With the settings up to this point, the "content (post text)" and "title (post title)" of the Post table are being searched.
This time, I would like to add "name (prefecture name)" in the Prefecture table to the search target so that you can also search by prefecture name.
We will add a description to the post model.
class Post < ApplicationRecord
...Part of the above omitted
def self.search(search)
if search != ""
Post.joins(:prefecture).where('content LIKE(?) OR title LIKE(?) OR prefectures.name LIKE(?)', "%#{search}%", "%#{search}%", "%#{search}%")
else
Post.all
end
end
Some of the following are omitted...
end
The prefecture table is also added as joins (: prefecture)
to be searched.
The join method
is a method` used when you want to join multiple tables into one.
In this case, the post table and the prefecture table are joined and treated as one table.
In the argument part of the where method, OR prefectures.name LIKE (?)'
Is added to specify the prefecture name as the search target. Add one "% # {search}% "
for this amount and you're done.
Since I am a beginner, I would appreciate it if you could point out any mistakes. Thank you for watching until the end.
Recommended Posts