- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Программирование на языке Ruby - Хэл Фултон
Шрифт:
Интервал:
Закладка:
@@items[author] = self
end
def self.find(author)
@@items[author]
end
end
Теперь контроллер может запрашивать данные у класса Book. Изменим метод index:
def index
book = Book.find_by_author("Mark Twain")
@author = book.author
@title = book.title
@last_update = book.update_time
end
А в файл run.rb вставим ссылку на модель Book и загрузим какие-нибудь данные:
require 'model/book'
Book.new(:title => "Life on the Mississippi",
:author => "Mark Twain").save
После перезапуска приложения и перезагрузки страницы мы увидим сведения о книге. А если книг больше? Вместо того чтобы «зашивать» в код данные о них, мы можем попросить контроллер выполнить поиск по имени автора. Добавим в него новый метод find:
def find(author)
book = Book.find_by_author(author)
@author = book.author
@title = book.title
@last_update = book.update_time
end
Это тот же код, что в методе index (и для создания соответствующего ему шаблона достаточно было бы переименовать index.xhtml в find.xhtml), но он принимает один аргумент — имя автора. Хотя мы разрабатываем Web-приложение, класс контроллера мало чем отличается от класса в любом другом приложении, написанном на Ruby. Самое заметное отличие заключается в том, что методы не возвращают значений, но никаких зависимостей от специальных переменных окружения или каких-то особых объектов нет. (Впрочем, имейте в виду, что Nitro все же добавляет разные «приятности» для программирования Web-приложений; для доступа к ним достаточно унаследовать свой класс от Nitro::Controller.) Например, Nitro обеспечивает «обстраивание», быструю передачу сообщений от одного запроса другому и хитроумный конвейер конструирования страницы, но все это только если вы сами захотите.
Сделаем еще одно замечание по поводу методов контроллера. Методы, предназначенные для обработки запросов на получение страницы, обычно идут в паре с шаблонами, имеющими схожее имя. Для получения конечного результата Nitro объединяет метод и шаблон. Мы видели, что Nitro может работать без контроллеров, ограничиваясь только видами. Но верно и обратное. Метод контроллера может генерировать всю страницу вообще без шаблона. Запросы на получение страниц обрабатываются в Nitro как действия (actions). Действие — это комбинация вида и методов контроллера. Внутри себя Nitro динамически создает методы действия, объединяющие то и другое. Но если какой-то компоненты недостает, ничего страшного не случится. Если у действия нет шаблона, результатом становится значение, возвращаемое методом контроллера.
Например, некоторый URL может отвечать на запрос, возвращая лишь название книги. Для этого достаточно такого метода контроллера BookController:
def sparse(author)
@context.content_type = 'text/plain'
book = Book.find_by_author(author)
book.title
end
Если метод контроллера возвращает не HTML-документ, то следует изменить заголовок content-type, отравляемый вместе с ответом в результате присваивания @context.content_type=. (Кстати, даже если парный шаблон существует, его можно не использовать, переопределив метод render_text.)
Но откуда метод find или sparse получает аргумент? По умолчанию Nitro следует привычному для Web-приложений паттерну, согласно которому сегменты пути URL отображаются на контроллеры, методы и аргументы. Перезапустите приложение и введите такой URL: http://127.0.0.1:9999/books/find/Hal%20Fulton.
Обратите внимание, что %20 — это кодированное представление пробела в имени автора. Nitro производит декодирование еще до вызова метода find.
В общем случае отображение URL выполняется так: /controller/method/arg1. Дополнительные аргументы можно передать в виде последующих сегментов пути. Впрочем, в Nitro есть механизм настройки маршрутизации, так что вы не обязаны отражать в URL детали реализации.
19.4.3. Nitro и Og
Хотя библиотека объектно-реляционного отображения Og, используемая в паре с Nitro, рассматривалась в другом месте, наше изложение было бы неполным без демонстрации того, как просто добавить к приложению интерфейс с базой данных. Сначала настроим Og в файле run.rb:
# Прямо перед вызовом Book.new :
require 'og'
Og.setup(:store => 'mysql',
:name => 'demo',
:user => 'root',
:destroy => true,
:port => 3316)
Затем изменим модель Book:
require 'glue/timestamped'
class Book
is Timestamped
property :title, String
property :author, String
def initialize{ values = {} )
@title, @author = values[:title], values[:author]
end
end
От хранения экземпляров Book в переменных класса мы отказались. Вызовы attr_accessor заменены обращением к методу property, который служит нескольким целям. Он тоже создает методы доступа к переменным, но, кроме того, сообщает Og, что этот класс должен обладать устойчивостью. Метод initialize почти не изменяется, но затребовав файл timestamped и поместив в класс маркер is Timestamped, мы автоматически получаем атрибут update_time.
Остальные методы можно удалить, теперь они реализуются библиотекой Og. При перезапуске приложения Nitro создаст для него базу данных MySQL, а в ней — таблицу для хранения объектов Book. Так разрабатываются приложения «на чистом Ruby без SQL».
19.4.4. Решение типичных для Web-приложений задач в Nitro
Nitro обладает поразительно богатой системой составления страниц. Ее полное описание выходит за рамки данной книги. Но любому Web-разработчику приходится постоянно решать некоторые типичные задачи, поэтому посмотрим, как это можно сделать в Nitro.
Если вы создаете сайт с одной-двумя страницами, не так уж важно, повторяются ли многократно одна и та же разметка и текст. Но когда страниц больше, обновлять все одинаковые фрагменты вручную становится утомительно и чревато ошибками. Nitro помогает следовать принципу DRY (Don't Repeat Yourself — «Не повторяйся»), предлагая целый ряд способов повторного использования.
Простейший из них — включение файла. Пусть, например, все страницы должны иметь общий хвостовик. Можно было бы поместить его в отдельный файл шаблона и включить во все страницы, как показано ниже:
<?include href='/footer' ?>
Сам файл footer.xinc мог бы выглядеть, к примеру, так:
<div id='footer'>Read More Ruby Books</div>
Если в качестве значения атрибута href указан относительный путь, Nitro будет просматривать папки template, определенные для текущего контроллера. Если же путь абсолютный, то просматривается только папка template в корневом каталоге приложения.
Показанный выше способ лучше всего подходит для статического контента. Существует и иной синтаксис включения, позволяющий вставить указанный файл в вызывающий шаблон непосредственно перед компиляцией шаблона:
<include href='/footer' />
Результат получается таким, как если бы включаемый текст был частью вызывающего шаблона.
Более сложная форма включения контента связана с элементом render:
render href='/controller/action' />
где href — некий путь в каталоге приложения.
Процедура компиляции при включении частичных видов с помощью <render /> практически не отличается от случая полного вида. В контроллере могут быть методы, соответствующие включаемому файлу; их можно использовать для установки значений переменных экземпляра во включаемом шаблоне.
В Nitro граница между кодом шаблона и кодом на Ruby размыта. Один из примеров мы уже приводили: действие контроллера может быть «размазано» между методом и файлом шаблона, а может целиком входить туда или сюда. Другой пример — элементы Nitro (Nitro Elements), способ инкапсуляции кода и разметки в нестандартном теге, который можно использовать в видах.
Вместо того чтобы определять в каждом виде HTML-разметку всей страницы, мы можем определить общий HTML-код и повторно использовать его в различных действиях. Создадим файл element/layout.xhtml:
<html>
<head>
<title>#{@title}</title>
<style>
body {
background-соlor: white; font-family: sans-serif;
}
</style>
</head>
#{content}
</html>
Теперь воспользуемся новым элементом в файле template/books/find.xhtml:
<Layout title='Details for #{@title}'>
<h1>#{@title}</h1>
<h2>#{@author}</h2>
<p>Page last updated: #{@last_update}</p>
</Layout>
Все содержимое элемента Layout вставляется в переменную content в файле layout.xhtml. Элементы могут принимать параметры; атрибут title в открывающем теге Layout становится значением переменной экземпляра @title в файле layout.xhtml.

