Я обнаружил то, что для такой, казалось бы, стандартной задачи как добавлени Wiki-функциональности в Rails нет полноценного готового плагина, которое бы легко интегрировалось с существующим приложением. В связи с этим был написан свой.
Основными критериями при разработке были:
То, что получилось представляет из себя что-то среднее между генератором (что обеспечивает хорошую расширяемость и модифицируемость) и engine'ом (чтобы можно было легко обновлять его).
Для работы плагина (в частности истории страниц) необходимо наличие гема diff-lcs. Для форматирования по умолчанию используется RedCloth, однако можно выбрать и другой форматтер. Таким образом:
Для установки плагина достаточно выполнить в директории Rails-приложения:
После установки необходимо сгенерировать миграцию, моделиь и контроллер… Стойте, это вовсе не значит, что у вас в приложении появится куча чужого кода, который непонятно как поддерживать! Контроллер и модель содержат всего по одной строке вида acts_as_* и генерируется для того, чтобы в последствии Вам было бы проще расширять функциональность. Вся собственная функциональность вики реализуется в файлах плагина, что позволяет безболезненно обновлять ее.
Итак, чтобы сгенерировать необходимые файлы необходимо вызвать соответсвующий генератор:
После вызова генератора в приложение будут произведены следующие изменения:
Также в роуты будет добавлена следующая строка:
Как несложно догадаться, в ней указывается корень wiki в вашем приложении. Вы можете легко его изменить на тот, который Вам больше нравится.
Все, работающая вики в вашем приложении сгенерирована. В принципе, можно уже использовать ее, но наверное вам все-таки хотелось бы изменить некоторые ее аспекты под свое приложение, например, изменить шаблоны, используемые для отображения или привязать ее к своей системе пользователей и ограничить права на редактирование страниц. Об этом и пойдет речь далее.
Изменение внешнего вида можно производить двумя путями:
Для замены какого-то шаблона (включая partial'ы) необходимо определить шаблон с соответствующим именем в директории видов для вашего контроллера. Ничего необычного, правда? Если вы не знаете, что же туда писать, можете посмотреть на дефолтные шаблоны в исходниках плагина (они там в app/views), благо они крайне простые.
Скорее всего, вы будете применять первый способ, но о первом все же стоит упомянуть. По умолчанию в каждый дефолтный шаблон добавляется CSS с описанием дефолтного стиля. Наверное, вам захочется его выкинуть (и подключить свой собственный в layout'е). Для этого достаточно переопределить в хелпере метод wiki_page_style своим, который возвращает пустую строку. Таким образом вы просто уберете стили из страниц.
Что необходимо для того, чтобы привязать вики к существующей системе пользователей в приложении?
Самый простой случай, если модель вашего пользователя называется User и у вас в контроллере определен метод current_user, который возвращает текущего пользователя. Согласитесь, это достаточно распространенный случай. В этом случае вики автоматически привяжется к пользователям и считать текущего пользователя автором изменений.
Единственная проблема — на всех страницах имя пользователя будет отображаться как-нибудь вроде User123. Наверное, это все-таки не то, что вы хотите. Чтобы исправить эту ситуацию достаточно определить метод wiki_user в классе WikiPagesHelper. Например, следующим образом:
Если же ваша модель называется как-то по-другому, придется добавить еще одну строчку при инициализации приложения:
Я рекомендую для этого создать отдельный initializer, чтобы потом туда же добавлять и прочие опции, которые вы, быть может захотите установить, но в принципе, вы вольны поступать как вам хочется.
Скорее всего, Вам захочется добавить ограничение прав на просмотр или редактирование страниц вики (вообще говоря, я считаю, что это весьма неплохая идея). Например, как минимум, дать права на редактирование только зарегистрированным пользователям.
Для этого необходимо всего-навсего переопределить в контроллере три метода, осуществляющие проверку прав: show_allowed?, history_allowed? и edit_allowed?. В каждом из методов необходимо проверить имеет ли текущий пользователь права на совершение действия (просмотр, просмотр истории, редактирование) с текущей страницей (@page) и соответственно вернуть что-то, что расценивается как исттина или как ложь. В случае, если соответствующий метод возвращает ложь, то действие не совершается и в контроллере вызывается метод not_allowed, который по умолчанию рендерит текст об ошибке, но скорее всего вам захочется переопределить и его (например, чтобы редиректить пользователя на страницу логина).
Таким образом, примерный код контроллера может выглядеть следующим образом:
Я вкратце описал использование своего плагина для вики в Rails. Некоторые моменты, конечно, остались за границами этой статьи, но я опишу их позже. Приветствуются всякие замечания, предложения и идеи (через комменты, github, или любые мои контакты), а также патчи и форки (если кто-то хочет добавить что-то в плагин).
Исходный код доступен на GItHub: github.com/alno/irwi
Основными критериями при разработке были:
- Возможность быстрой интеграции в приложение.
- Хорошая расширяемость.
- Отсутствие чужого кода (в смысле кода плагина) в приложении, к чему часто приводит использование генераторов. В этом смысле я пытался равняться на Authlogic.
То, что получилось представляет из себя что-то среднее между генератором (что обеспечивает хорошую расширяемость и модифицируемость) и engine'ом (чтобы можно было легко обновлять его).
Установка и использование
Для работы плагина (в частности истории страниц) необходимо наличие гема diff-lcs. Для форматирования по умолчанию используется RedCloth, однако можно выбрать и другой форматтер. Таким образом:
gem install diff-lcs RedCloth
Для установки плагина достаточно выполнить в директории Rails-приложения:
script/plugin install git://github.com/alno/irwi
После установки необходимо сгенерировать миграцию, моделиь и контроллер… Стойте, это вовсе не значит, что у вас в приложении появится куча чужого кода, который непонятно как поддерживать! Контроллер и модель содержат всего по одной строке вида acts_as_* и генерируется для того, чтобы в последствии Вам было бы проще расширять функциональность. Вся собственная функциональность вики реализуется в файлах плагина, что позволяет безболезненно обновлять ее.
Итак, чтобы сгенерировать необходимые файлы необходимо вызвать соответсвующий генератор:
script/generate irwi_wiki
После вызова генератора в приложение будут произведены следующие изменения:
- Добавлен WikiPageController и соответствующий хелпер для обработки страниц
- Добавлены модели WikiPage и WikiPageVersion для представления страниц
- Будет сгенерирована миграция, создающая таблицы в БД
Также в роуты будет добавлена следующая строка:
Copy Source | Copy HTML
- map.wiki_root '/wiki'
Как несложно догадаться, в ней указывается корень wiki в вашем приложении. Вы можете легко его изменить на тот, который Вам больше нравится.
Все, работающая вики в вашем приложении сгенерирована. В принципе, можно уже использовать ее, но наверное вам все-таки хотелось бы изменить некоторые ее аспекты под свое приложение, например, изменить шаблоны, используемые для отображения или привязать ее к своей системе пользователей и ограничить права на редактирование страниц. Об этом и пойдет речь далее.
Изменение внешнего вида
Изменение внешнего вида можно производить двумя путями:
- Замена шаблонов
- Замена стилей в дефолтных шаблонах
Для замены какого-то шаблона (включая partial'ы) необходимо определить шаблон с соответствующим именем в директории видов для вашего контроллера. Ничего необычного, правда? Если вы не знаете, что же туда писать, можете посмотреть на дефолтные шаблоны в исходниках плагина (они там в app/views), благо они крайне простые.
Скорее всего, вы будете применять первый способ, но о первом все же стоит упомянуть. По умолчанию в каждый дефолтный шаблон добавляется CSS с описанием дефолтного стиля. Наверное, вам захочется его выкинуть (и подключить свой собственный в layout'е). Для этого достаточно переопределить в хелпере метод wiki_page_style своим, который возвращает пустую строку. Таким образом вы просто уберете стили из страниц.
Привязка к пользователям
Что необходимо для того, чтобы привязать вики к существующей системе пользователей в приложении?
Самый простой случай, если модель вашего пользователя называется User и у вас в контроллере определен метод current_user, который возвращает текущего пользователя. Согласитесь, это достаточно распространенный случай. В этом случае вики автоматически привяжется к пользователям и считать текущего пользователя автором изменений.
Единственная проблема — на всех страницах имя пользователя будет отображаться как-нибудь вроде User123. Наверное, это все-таки не то, что вы хотите. Чтобы исправить эту ситуацию достаточно определить метод wiki_user в классе WikiPagesHelper. Например, следующим образом:
Copy Source | Copy HTML
- module WikiPagesHelper
- include Irwi::Helpers::WikiPagesHelper
-
- def wiki_user( user )
- user ? link_to( user.login, user_path( user ) ) : "Guest"
- end
-
- end
Если же ваша модель называется как-то по-другому, придется добавить еще одну строчку при инициализации приложения:
Irwi.config.user_class_name = 'Account' # Разумеется, если ваша модель называется именно так
Я рекомендую для этого создать отдельный initializer, чтобы потом туда же добавлять и прочие опции, которые вы, быть может захотите установить, но в принципе, вы вольны поступать как вам хочется.
Ограничение прав на выполнение операций
Скорее всего, Вам захочется добавить ограничение прав на просмотр или редактирование страниц вики (вообще говоря, я считаю, что это весьма неплохая идея). Например, как минимум, дать права на редактирование только зарегистрированным пользователям.
Для этого необходимо всего-навсего переопределить в контроллере три метода, осуществляющие проверку прав: show_allowed?, history_allowed? и edit_allowed?. В каждом из методов необходимо проверить имеет ли текущий пользователь права на совершение действия (просмотр, просмотр истории, редактирование) с текущей страницей (@page) и соответственно вернуть что-то, что расценивается как исттина или как ложь. В случае, если соответствующий метод возвращает ложь, то действие не совершается и в контроллере вызывается метод not_allowed, который по умолчанию рендерит текст об ошибке, но скорее всего вам захочется переопределить и его (например, чтобы редиректить пользователя на страницу логина).
Таким образом, примерный код контроллера может выглядеть следующим образом:
Copy Source | Copy HTML
- class WikiPagesController < ApplicationController
-
- acts_as_wiki_pages_controller
-
- def show_allowed?
- true # Показывать всем
- end
-
- def history_allowed?
- true # И историю пусть все смотрят
- end
-
- def edit_allowed?
- current_user # А редактируют только те, кто залогинены
- end
-
- def not_allowed
- redirect_to login_path # Всех нарушителей редиректим на страницу логина
- end
-
- end
Итого
Я вкратце описал использование своего плагина для вики в Rails. Некоторые моменты, конечно, остались за границами этой статьи, но я опишу их позже. Приветствуются всякие замечания, предложения и идеи (через комменты, github, или любые мои контакты), а также патчи и форки (если кто-то хочет добавить что-то в плагин).
Исходный код доступен на GItHub: github.com/alno/irwi