Делаем простую пагинацию в Rails 3 ч. 2
августа 24, 2011 | Published in Ruby on Rails, Ruby on Rails 3 | 3 Comments
В предыдущей статье мы сделали самую простую пагинацию, которая выводит ссылки на все существующие страницы. В этой статье мы несколько расширим функционал.
Для начала откроем хелпер постов:
#../app/helpers/posts_helper.rb module PostsHelper end
В этот хелпер мы поместим весь код отвечающий за представление ссылок пагинации.
Сразу оговорюсь (предсказывая гневные комментарии типа: «Что за говнокод?»), что данная статья не ставит целью описать окончательный вариант разработки пагинации. Рефакторинг, добавление конфигурирования представления ссылок и т.д. будет рассмотрено в следующей статье или статьях. Это пошаговое руководство разработки пагинации, которое показывает не только правильный вариант пагинации, но и попутно демонстрирует распространенные у новичков ошибки.
В моей реализации пагинации я буду использовать три стандартных варианта представления:
- Вывод ссылок на все страницы,
- Вывод ссылок на первую и последнюю страницы а также ссылок на две предыдущие и две следующие страницы по отношению к текущей,
- Вывод ссылок на предыдущую и следующую страницы по отношению к текущей.
Ниже привожу код с комментариями:
module PostsHelper #Использую этот метод для получения массива ссылок def page_links pg_links = [] Post.pgcount.times do |pg| #индексация массива начинается с единицы p = pg+1 pg_links[p] = link_to(p, "/posts/#{p}") end #возвращаем массив строк - ссылок на все страницы return pg_links end def paginate(style = :full_list) #переменная pg_html хранит строку - html код отображения пагинации pg_html = "" #Если params["page"] не определен(в адресной строке нет номера страницы), то номер текущей страницы = 1 params["page"] ? current_page = params["page"].to_i : current_page = 1 pg_links = page_links #проверяем какой режим выбран case style #если :full_list, то выводим ссылки на все страницы when :full_list then pg_links.each_with_index do |page,key| if key == current_page.to_i pg_html += "<span class=\"page_link current_page\">#{page}</span>" elsif !page.nil? pg_html += "<span class=\"page_link\">#{page}</span>" end end #если :short_list, то выводим ссылки на первую, последнюю и соседние страницы (по 2 с каждой стороны от текущей) when :short_list then pg_html += "<span class=\"page_link first_page\"><b>#{pg_links[1]}</b></span>" if current_page > 3 pg_html += "<span class=\"page_link\"><b>#{pg_links[current_page-2]}</b></span>" end if current_page > 2 pg_html += "<span class=\"page_link\"><b>#{pg_links[current_page-1]}</b></span>" end if current_page > 1 and current_page < pg_links.size pg_html += "<span class=\"page_link current_page\"><b>#{pg_links[current_page]}</b></span>" end if current_page < pg_links.count - 2 pg_html += "<span class=\"page_link\"><b>#{pg_links[current_page+1]}</b></span>" end if current_page < pg_links.count - 3 pg_html += "<span class=\"page_link\"><b>#{pg_links[current_page+2]}</b></span>" end pg_html += "<span class=\"page_link last_page\"><b>#{pg_links.last}</b></span>" #если вибран режим :prev_next, то показываем только ссылкии на предыдущую страницу и следующую when :prev_next then if current_page > 1 pg_html += "<span class=\"page_link prev_page\"><b>#{pg_links[current_page - 1]}</b></span>" end if current_page < pg_links.size pg_html += "<span class=\"page_link next_page\"><b>#{pg_links[current_page + 1]}</b></span>" end end #возвращаем html-код представляющий ссылки return raw pg_html end end
Для того, чтобы ссылки отображались красиво, мы обернули их в <span></span> и присвоили им стили. Давайте откроем файл со стилями и определим свойства классов: page_link, current_page, first_page, last_page, prev_page и next_page:
/*../public/stylesheets/paginate.css*/ div#paginate{ width:100%; background:#A4C639; overflow:hidden; padding:5px 0; } span.page_link{ float:left; padding:2px; border:1px solid #008000; margin-left:5px; background:#8DB600; margin-top:5px; line-height:1em; } .page_link a, .page_link a:visited { color:#fff; font-size:10px; display:block; } .page_link a:hover{ color:#FDEE00; background:none; } span.current_page{ border:1px solid #B31B1B; background:#EB4C42; } span.first_page, span.last_page{ border:1px solid #2A52BE; background: #4997D0; }
Теперь вы можете в шаблоне ../app/views/index.html.erb использовать метод paginate. Ниже приведены примеры представления ссылок при различных режимах. Как не сложно догадаться по приведенному выше CSS-коду, хэлпер представляющий ссылки помещен в <div id=»paginate»></div> для большей привлекательности представления.
<%= paginate #по умолчанию используется :full_list %>
<%= paginate(:short_list) %>
<%= paginate(:prev_next) %>
На этом все, спасибо за внимание!
Лучшая благодарность автору — ваши комментарии!
августа 25, 2011 at 08:47 (#)
Предлагаю парочку улучшений:
вместо:
напрашивается:
А вместо:
читабельнее сделать:
августа 25, 2011 at 09:42 (#)
Спасибо, Антон, реально красивее и короче код.
августа 27, 2011 at 09:10 (#)
Почему бы не использовать kaminari?