Ruby on Rails замечательно подходит для создания мощного и гибкого бэкенда. Однако из-за популярности и гибкости JavaScript, Ruby используется для фронтэнда не так часто. Тем не менее я считаю, что, используя только HTML, Ruby и CSS, разработчики смогут создавать более качественные сайты. Экспериментируя с созданием более динамических страниц без JavaScript, мы можем научиться грамотно использовать cookie-файлы и снизить зависимость от скриптов, влияющих на производительность.
Хороший способ попрактиковаться в использовании cookie-файлов с Rails — это создать для веб-сайта простую функцию поиска и сортировки. Давайте рассмотрим компоненты, которые делают возможными оба эти действия одновременно.
Код
Для этого примера используем очень простое приложение для фэнтези-футбола, полный код которого можно найти здесь.
ruby
def initialize_search
@teams = Team.alphabetical
session[:search_name] ||= params[:search_name]
session[:filter] = params[:filter]
params[:filter_option] = nil if params[:filter_option] == ""
session[:filter_option] = params[:filter_option]
end
def handle_search_name
if session[:search_name]
@players = Player.where("name LIKE ?", "%#{session[:search_name].titleize}%")
@teams = @teams.where(code: @players.pluck(:team))
else
@players = Player.all
end
end
def handle_filters
if session[:filter_option] && session[:filter] == "position"
@players = @players.where(position: session[:filter_option])
@teams = @teams.where(code: @players.pluck(:team))
elsif session[:filter_option] && session[:filter] == "team"
@teams = @teams.where(code: session[:filter_option])
end
end
Эти методы обрабатывают запросы имен игроков из базы данных.
Первый метод, handle_search_name
, берет cookie-файл, содержащий данные поиска, введенные пользователем, и использует их для выделения игроков, чьи имена соответствуют поисковому запросу, используя метод activerecord
, где @players = Player.where("name LIKE ?", "%#{session[:search_name].titleize}%")
.
Метод handle_filters
берет доступный в данный момент список игроков и отфильтровывает по подходящему параметру @players = @players.where(position: session[:filter_option])
.
Оба эти метода основаны на сессиях. Сессия — это фактически набор cookie-файлов. Эти cookie-файлы передаются через параметры, отправленные обратно на сервер как часть запроса get
из формы. Давайте посмотрим, как они отправляются.
ruby
def initialize_search
@teams = Team.alphabetical
session[:search_name] ||= params[:search_name]
session[:filter] = params[:filter]
params[:filter_option] = nil if params[:filter_option] == ""
session[:filter_option] = params[:filter_option]
end
def handle_search_name
if session[:search_name]
@players = Player.where("name LIKE ?", "%#{session[:search_name].titleize}%")
@teams = @teams.where(code: @players.pluck(:team))
else
@players = Player.all
end
end
def handle_filters
if session[:filter_option] && session[:filter] == "position"
@players = @players.where(position: session[:filter_option])
@teams = @teams.where(code: @players.pluck(:team))
elsif session[:filter_option] && session[:filter] == "team"
@teams = @teams.where(code: session[:filter_option])
end
end
Форма выше отправляет запрос get
обратно той же странице, но передает пользовательский поисковый запрос как параметр search_name
.
Затем в контроллере Rails используем:
session[:search_name] = params[:search_name]
В приведенной строчке как часть нашей сессии хранится параметр search_name
, который будет позднее использован методом handle_search_name
. Чтобы поиск работал, можно просто использовать параметр, но существует проблема — параметры не сохраняются между запросами.
Почему сессии?
Если параметр не сохраняется в течение нескольких запросов, когда мы выберем параметр фильтрации (который осуществляет запрос к серверу), для пользователя поисковый запрос будет пустым. Вот почему мы должны хранить параметр как часть сессии.
Сессия в Rails — это зашифрованный набор cookie-файлов. Если мы не хотим, чтобы пользователи вручную редактировали отдельные cookie-файлы, мы используем сессию. В данном конкретном случае мы хотим контролировать, когда конкретные cookie-файлы сохраняются и удаляются. Для этого мы поместим все cookie-файлы в сессию, а не будем хранить отдельными файлами.
Поиск и фильтрация одновременно
Теперь, когда пользователь дал нам поисковый запрос, мы можем сузить область поиска, используя фильтр. В нашем HTML есть форма для каждого параметра фильтра, давайте посмотрим на один из них:
html
<select name="filter_option" onchange="this.form.submit()">
<option value="">Pick a Team</option>
<% @teams.each do |team| %>
<option value="<%= team.code %>"><%= team.name %></option>
<% end %>
</select>
Код создает выпадающее меню, которое после изменения отправит запрос обратно серверу с выбранным параметром. На стороне контроллера Rails мы обрабатываем параметр и сохраняем его в сессию. Теперь у нас есть и поисковый запрос, и параметр фильтра, то есть все, что нужно для отображения результатов.
Отображение результатов
Самый приятный момент — отображение результатов на странице.
При условии, что маршруты сконфигурированы корректно, все, что нужно сделать, это вызвать обработчики поиска и фильтрации в контроллере. Они будут каждый раз обрабатывать параметры, сохранять нужные в сессии и затем формировать данные из базы данных.
ruby
def index
initialize_search
handle_search_name
handle_filters
end
Затем в HTML создаем элементы, которые будут возвращены в отсортированный набор данных.
html
<% @teams.each do |team| %>
<h2>
<%= team.name %>
</h2>
<ul>
<% @players.where(team: team.code).each do |player| %>
<li>
<%= link_to "#{player.name} | #{player.position}", player %>
</li>
<% end %>
</ul>
<% end %>
Вуаля! Конечный результат должен выглядеть примерно так:
Используя те же принципы, мы можем сделать Rails более интерактивным в качестве фронтэнда, а также научиться лучше использовать такие инструменты, как cookie-файлы.
Читайте также:
- Основы JavaScript: функции
- Функции-генераторы в JavaScript для оптимизации памяти
- Как работает JavaScript
Перевод статьи Sukrit Walia: Making a Search and Filter Function in Ruby on Rails