Навигация
Шаг Б1: создание каталога товаров
Ранее мы сказали, что будем использовать для этого приложения два класса кон¬троллеров. Контроллер Admin, используемый продавцом для управления прило¬жением Depot, мы уже создали. Настало время создать второй контроллер, кото¬рый будет работать при работе с покупателями. Назовем его Store.
depot> ruby script/generate controller store index exists app/controllers/ exists app/helpers/
create app/views/store exists test/functional/
create app/controllers/store_controller.rb create test/functional/store_controller_test.rb create app/helpers/store_helper.rb create app/views/store/index.rhtmt
Так же как и в предыдущей главе, в которой для создания контроллера по ве¬дению учета товаров мы использовали утилиту generate, в этой главе мы исполь¬зуем ее же для создания нового контроллера (класс StoreController в файле store_controller.rb), в котором содержится единственный метод действия — index.
Почему же мы назвали наш первый метод i ndex? Да потому, что, как и в слу¬чае работы с большинством других веб-серверов, если вы вызываете Rails-кон¬троллер и не указываете действие в явном виде, Rails автоматически вызывает действие index. Давайте попробуем это на практике. Введите в браузер адрес http://localhost:3000/store и перейдите на нашу веб-страницу1.Конечно, новых знаний это вам не добавит, но по крайней покажет, что все взаимосвязано именно так, как мы и предполагали. Страница просто сообщит нам, где найти тот файл шаблона, которым вызвано ее появление.
Начнем с отображения простого перечня всех товаров, имеющихся в базе дан¬ных. Мы знаем, что в конечном счете понадобится более сложный подход с раз¬биением товаров на категории, к чему мы и будем стремиться.
Нам нужно извлечь перечень товаров из базы данных и сделать его доступным для кода представления, который и отобразит таблицу. Это означает, что мы должны внести изменения в метод index в файле store_controller.rb. Мы хотим программировать на соответствующем уровне абстракции, поэтому просто пред¬положим, что мы можем запросить у модели перечень продаваемых товаров.
Листинг файла app/controllers/store_controller.rb
class StoreController < ApplicationController def index
©products = Product.find_products_for_sale
end
end
Если вместо этого вы увидите сообщение о том, что браузер не может отобразить эту веб¬страницу, то вам, скорее всего, понадобится остановить и перезапустить приложение. Нажмите в консольном окне, в котором выполнялась команда script/server, сочетание клавиш Ctrl+C, а затем снова выполните ту же самую команду.
Разумеется, на данный момент этот код работать не будет. Сначала нам необходи¬мо в модели product.rb определить метод find_products_for_sale. В приводи¬мом далее коде используется Rails-метод f i nd. Параметр : all указывает Rails, что мы хотим сравнить с заданными условиями все строки. Мы спросили у заказчика, в каком порядке он хочет увидеть товары, которые должны быть выведены в переч¬не, и приняли совместное решение: посмотреть, что получится, если мы отобразим их в алфавитном порядке, применив код, сортирующий товары по наименованиям.
Листинг файла app/models/product.rb
class Product < ActiveRecord::Base def self.find_products_for_sale find(:all, .-order => "title" )
end
# блок проверки ... end
Метод f i nd возвращает массив, содержащий объект Product для каждой стро¬ки, извлеченной из базы данных. Для того чтобы эти строки были отсортированы по наименованию товара, мы воспользовались необязательным параметром этого метода — :order. Метод f ind_products_for_sale просто передаст созданный массив контроллеру. Заметьте, что мы превратили f i nd_products_f or_sale в ме¬тод класса, поместив в определении перед его именем префикс self.. Мы так сделали потому, что хотим иметь возможность вызывать его из всего класса в це¬лом, а не только из его конкретного экземпляра — этот метод можно будет вы¬звать, воспользовавшись выражением Product.f ind_products_for_sale.
Теперь нам надо создать шаблон представления. Для этого мы отредактируем файл index.rhtml в каталоге app/views/store. (Помните, что путь к имени представ¬ления составляется из имени контроллера [store] и имени действия [index]. Рас¬ширение .rhtml означает, что это ERb-шаблон.)
Листинг файла app/views/store/index. rhtml Your Pragmatic Catalog
<% for product in ^products -%>
" /> <%= h(product.title) %> <%= product.description %>
<%= product.price %> <% end %>
На этот раз мы используем метод h (строка) для нейтрализации любых HTML-элементов в наименовании товара, но не применяем его для такой же нейтрализа¬ции в описании. Это позволяет нам использовать стилевое оформление HTML для создания привлекательных в глазах заказчика описаний .
Вообще-то постарайтесь выработать привычку набирать в шаблонах структу¬ру вида <%= h(. . .) %>, удаляя затем вспомогательный метод п, если посчитаете это безопасным.
Щелчок на кнопке Refresh (Обновить) приведет к появлению страницы, изо¬браженной на рис. 7.1. Она не отличается привлекательностью, поскольку мы еще не подключили каскадную таблицу стилей — таблицу CSS. Заказчик случай¬но проходил мимо, когда мы обдумывали этот вопрос, и указал на то, что хо¬тел бы видеть на общедоступных страницах более выразительные наименования товаров и присутствие боковой панели.
Столкнись с такой ситуацией в реальном мире, мы, наверное, испытали бы же¬лание обратиться к дизайнеру — нам всем приходилось видеть такое количество веб-сайтов, спроектированных самими программистами, что мы без стеснений привлекли бы к этому делу кого-нибудь другого. Но наш веб-дизайнер в отпуске,черпает вдохновение на каком-нибудь пляже и вряд ли вернется до конца года, поэтому пока в этой графе поставим прочерк. А тем временем пришла пора сде¬лать следующий шаг.