Я построил функцию поиска поверх своего приложения rails, где я могу искать и фильтровать по имени и полу пользователя. Поиск работает исправно, единственное, он работает не точно!
Например, если я ищу пользователей-мужчин, в результатах поиска также будут указаны пользователи-женщины. И я думаю, это связано с тем, что я использую запрос ActiveRecord, в котором я сравниваю столбец пола в таблице пользователей со вставленными параметрами, и потому что «женский» и «мужской» - два очень похожих слова, и его результаты связаны с двумя атрибуты. Это запрос ActiveRecord, который я использовал и который работает (хотя и не совсем точно):
"gender LIKE ? ", "%#{params[:gender]}%"
Поэтому я использовал другой запрос ActiveRecord:
"gender: %#{params[:gender]}%"
Второй запрос, к сожалению, все ломает. Я получаю эту ошибку в своем терминале:
SQLite3::SQLException: unrecognized token: ":": SELECT "users".* FROM "users" WHERE (gender: %Male%))
Предполагается, что эти запросы ActiveRecord принадлежат search_controller моей «поисковой» модели. Это мой контроллер:
def index
if params[:username] || params[:gender].present?
@search = User.where('true').paginate(page: params[:page], per_page: 10)
@search = User.where("name LIKE ? ", "%#{params[:username]}%") unless params[:username].blank?
@search = User.where("gender LIKE ? ", "%#{params[:gender]}%") unless params[:gender].blank?
else
@search = User.all.paginate(page: params[:page], per_page: 10)
end
end
def create
@search = Search.create(username: params[:username], gender: params[:gender])
redirect to @search
end
private
def search_params
params.require(:search).permit(:users, :gender)
end
Это мой индекс моей модели поиска, где я перебираю то, что ищется (@search), и отображаю в результатах поиска:
<h1> Your Search Results </h1>
<% if @search.nil? %>
<p> No Results Found </p>
<% else %>
<ul class = "users">
<% @search.each do |user| %>
<%= user.name %>
<%= user.gender %>
<% end %>
</ul>
<% end %>
<p><%= link_to 'All Users', users_path %></p>
Это небольшое видео, в котором я могу объяснить, что я хочу делать: https://drive.google.com/file/d/1G5FYytvmdI6iKjmwlH16NeftGwsEnLQU/view?usp=sharing
🤔 А знаете ли вы, что...
SQL поддерживает транзакции с использованием команд BEGIN, COMMIT и ROLLBACK.
Использование LIKE ?
делает ваш код уязвимым для SQL-инъекции, поэтому я определенно рекомендую вам изменить свой подход.
Думаю, вы решите проблему, используя что-то вроде
User.where("name = ? AND gender = ?", params[:username], params[:gender])
Также используйте Руководство по запросам Active Record в качестве ссылки каждый раз, когда вы используете запросы. Там вы найдете много полезного.
Две проблемы: 1) чтобы точно соответствовать параметру, который вы можете сделать
@search = User.where(gender: params[:gender]) unless params[:gender].blank?
Остальное, что вы оставили, касается лежащего в основе LIKE clausa, и если вы хотите сделать это с помощью LIKE, это правильный синтаксис
@search = User.where("gender LIKE ? ", "#{params[:gender]}") unless params[:gender].blank?
2) вы перезаписываете переменную @search, поэтому, если у вас есть оба параметра, ваш запрос параметра имени никогда не останется. Попробуй в конце
@search = User.all
@search = @search.where("name LIKE ? ", "%#{params[:username]}%") unless params[:username].blank?
@search = @search.where("gender LIKE ? ", "%#{params[:gender]}%") unless params[:gender].blank?