Пользовательский контент

Опубликовано 07.03.2009

Еще со времен запуска первой версии Записок я ношу в себе идею разработки собственного блогодвижка. Задача, казалось бы, не ахти какая сложная и очень многие ее успешно решают, движков понаписано великое множество на всех языках. Собственно, поэтому идея и пролежала в моей голове без дела почти 4 года. И вот буквально после новогодних праздников я наконец нашел достойный повод взяться за нее – блоги практически не представлены на Facebook.

Существует всего несколько приложений под Facebook, относящихся в той или иной степени к блоггингу. Стандартные записки (Notes) убивают всякий коммерческий интерес к разработке альтернатив. И тем не менее, я взялся такую альтернативу создать, в первую очередь ради эксперимента. Получилась вот такая штука: Blog Box (демонстрационный блог)

По ходу работы над приложением выявилось множество нюансов, которые встречаются от проекта к проекту. Одним из первых вопросов, с которыми я столкнулся – как работать с пользовательским контентом.

Разметка

Практически каждый человек хочет как-то разнообразить свои посты, добавить в них ссылки, выделить текст жирным или курсивом, вставить список или табличку. Надо понимать, что большинство пользователей не знают и знать не хотят что такое HTML. В блогоплатформах для пользователей обычно ставится WYSIWYG-редактор типа TinyMCE, FCKEditor, Xinha или любой другой. Однако в Facebook такой вариант не пройдет – платформа очень жестко контролирует JavaScript, используемый приложением, и практически сводит на нет возможность использования готовых библиотек.

Для ручной разметки текста и избавления от необходимости в визуальном редакторе можно использовать упрощенные системы разметки, которые часто применяются в wiki-системах. Для Ruby есть два реализованных формата разметки – Textile (с помощью RedCloth) и Markdown (с помощью BlueCloth). Textile более гибок в плане стилевой разметки, Markdown проще для освоения. Я решил остановиться на Textile.

Обработку текста я вынес в отдельный хелпер, единый как для постов, так и для комментариев:

def format_content(content)
  textilize(content.to_s)
end

Метод textilize – стандартный рельсовый, становится доступен после установки RedCloth. Для обработки постов и комментариев я создал отдельные хелперы, передающие соответствующий контент для форматирования:

def post_content(post)
  format_content(post.text)
end

def post_excerpt(post)
  post.excerpt.blank? ? post_content(post) : format_content(post.excerpt)
end

def comment_content(comment)
  format_content(comment.text)
end

Далее вызываем нужные нам хелперы хоть на странице просмотра поста, хоть при выводе списка постов.

Очистка HTML

Если честно, я ожидал, что мое приложение сразу кто-нибудь попробует использовать в гнусных целях, похакать, засунуть XSS или какой-нибудь мерзкий JavaScript. Однако я не ожидал, что это случится в первый же день жизни приложения. Хорошо, что я озаботился где возможно прикрыть вывод пользовательских данных с помощью хелпера h():

<%=h @post.title %>

Однако текст поста, который форматируется с помощью Textile, так не обезопасишь. Поэтому следующее что пришлось делать – это очистку текста постов от потенциально опасных тэгов и атрибутов. Для решения этой задачи существует несколько различных вариантов. В рельсах есть встроенный хелпер для очистки от ненужных тэгов – sanitize. Есть сторонние решения, такие как xss_terminate, Dryopteris или sanitize, использующие возможности более быстрых библиотек для работы с HTMLHpricot и Nokigiri.

Я решил использовать в своем проекте плагин Sanitize – он для меня оказался более удобен в конфигурировании. Для интеграции с моделями я написал небольшой модуль, в котором немного поменял стандартные схемы очистки тэгов и атрибутов, а также добавил метод sanitize_attributes для быстрого привязывания очистки атрибутов. Весь входящий HTML разбирается средствами Hpricot, вычищаются ненужные тэги и атрибуты, добавляются нужные атрибуты (например, rel=nofollow для ссылок из комментариев) и обработанный код сохраняется в БД.

Специальные тэги

Мое знакомство с блоггингом, как и у многих, началось с LiveJournal. Система во многом неудобная, но в ней есть одна изюминка, которая мне очень нравилась – специальные тэги. Например, если я вставлю в текст поста тэг <lj user="my_friend">, то в тексте поста будет показана красиво оформленная ссылочка на журнал моего друга со всплывающей по наведению мышки информацией. Фишка очень интересная и я обязательно хотел использовать ее в своем блогодвижке.

Что самое смешное, я был даже вынужден ее использовать, когда дело дошло до вставки видео. В Facebook есть суровое ограничение на то, какие тэги можно использовать на страницах, а какие – нет. Это ограничение касается и тэга <object>, который по факту запрещен. Вместо него для вставки Flash используется тэг <fb:swf>, однако он сильно ограничен в плане конфигурирования. Видео-хостинги же для вставки видео дают только код на основе тэга <object>, без вариантов. Я задумался.

Решение нашлось довольно быстро – выводить обычный код вставки видео внутри тэга <iframe>, на который ограничение не накладывается. Однако опять же, код для iframe нужно каким-то образом сформировать, да и сам iframe нужно как-то вставить. Для формирования кода я решил использовать плагин acts_as_unvlogable, позволяющий из URL страницы с видео сформировать код. Вопрос со вставкой iframe встал на первый план.

На помощь пришла библиотека Radius, ключевая фишка Radiant CMS. С ее помощью можно создавать свои тэги, которые затем парсятся и обрабатываются ruby-кодом. Для размещения видео пользователю необходимо сформировать и вставить в текст поста вот такой код:

<bb:video url="http://www.youtube.com/watch?v=v9Lj0lF9Lao"></bb:video>

Обработка radius-кода вынесена в отдельный модуль, упрощающий добавление новых тэгов и их использование. Метод класса define_tag объявляет новый тэг, создает из блока метод экземпляра, который вызывается при обработке тэга, а так же добавляет тэг в общий список спец-тэгов, который можно затем использовать для расширения схемы очистки HTML, используемой sanitizer’ом:

  • Blogbox::RadiusContext.tags_with_namespace – все спецтэги
  • Blogbox::RadiusContext.tag_attributes – все разрешенные атрибуты

Для того, чтобы подключить спец-тэги стразу везде, меняем хелпер форматирования контента и хелперы вывода постов и комментариев:

def format_content(content, assigns = {}, &block)
  textilized_content = textilize(content.to_s)

  @@radius_context ||= Blogbox::RadiusContext.new(&block)
  @@radius_context.set_current_context(self, 
    assigns.merge(
      :view       => self,
      :controller => controller
    )
  )

  Radius::Parser.new(@@radius_context,
    :tag_prefix => Blogbox::RadiusContext::NAMESPACE
  ).parse(textilized_content)
end

def post_content(post)
  format_content(post.text, :post => post)
end

def post_excerpt(post)
  return post_content(post) if post.excerpt.blank? 

  format_content(post.excerpt, :post => post)
end

def comment_content(comment)
  format_content(comment.text, :post => post, :comment => comment)
end

Что особенно хорошо в спец-тэгах, так это возможность использования вашего приложения (или сторонних приложений) для создания действительно богатого пользовательского контента. Например, постов со вставленными в них фотогалереями, списками пользователей, голосованиями и т.д. От вас требуется только немного фантазии для создания набора спец-тэгов.

Резюме

Пользовательский контент – далеко не банальная вещь. Здесь есть и подводные камни, и простор для творчества, и необходимость в разумном обстоятельном подходе. Если вы работаете с пользовательским контентом – заранее обдумайте, какие возможности вы хотите дать пользователю и какие точно не хотите давать. Исходя из специфики задачи и среды можно использовать те инструменты, которые уже разработаны ruby-сообществом, и сделать свой проект по истине уникальным.

Кратко о проектах

Опубликовано 09.12.2008

Я последние несколько месяцев занимаюсь разработкой системы управления информационными порталами. Буквально несколько дней назад открыли в общий доступ один из клиентских проектов - портал МедиаЗавод, дочерний проект ООО “ЧР-Менеджер” (газеты Челябинский Рабочий, Тумба и еще несколько газет Челябинской области).

Проект сделан на рельсах, используется Single Sign-on для единой авторизации на всех сервисах. Всего в портал пока что включены 4 сервиса - система публикаций, доска объявлений, паспорт и баннерная система. Сервисы включают от 4 до 10 desert-модулей. В качестве JavaScript-библиотеки используется jQuery.

В системе публикаций используется упрощенная разметка Textile. Система администрирования интегрируется напрямую в дизайн, управляющие элементы при авторизации появляются прямо на страницах портала.

Развертывается все под nginx+passenger, используется кэширование в статику и вставка блоков через SSI. Сессии хранятся в memcache, через него же передается единая авторизацая.

[ANN] Furwall - prevents unauthorized access

Опубликовано 01.11.2008

Давно у меня зрела идея сделать управление правами для доступа к объектам через БД. На досуге наконец оформил идею в плагин. Приветствуем Furwall - плагин для ограничения доступа к объектам:

script/plugin install git://github.com/dekart/furwall.git

Далее читаем README.

Это пока что концепт, поэтому любая конструктивная критика приветствуется. В особенности критика в виде патчей :) Обсудить можно тут.

Игра переехала на Joyent

Опубликовано 29.11.2007

Буквально только что перенес игру на сервер Joyent. По сравнению с московским скорость отдачи увеличилась примерно раза в 4, а то и в 5. Видимо, помехи над морем мешали :)

Процесс переезда был, мягко говоря, нетривиален. Переползать с FreeBSD на Solaris - удовольствие то еще. Много непривычных моментов. В частности, долго не мог вникнуть в систему управления сервисами SMF. в wiki на сайте Joyent есть инструкции по развертыванию Rails-приложений на их серверах с помощью capistrano, но они писаны под стандартные акселераторы, а у фейсбуковых свои особенности, которые приходилось искать буквально на ощупь. В частности, пришлось руками прописывать все пути к исполняемым файлам. В общем, вчерашний вечер и сегодняшнее утро прошли не зря :)

Кстати, если кто-то еще не тестировал игру - милости просим. Судя по логам, суровые дядьки-девелоперы, читавшие прошлый пост, всерьез заигрались :)

Онлайн-игра под Facebook

Опубликовано 28.11.2007

Почти полтора месяца ушло на то, чтобы проработать и довести до ума мой новый проект - онлайн-игру под платформу Facebook. Суть игры достаточно простая: вы становитесь капитаном космического корабля и можете сражаться с другими игроками. В процессе битв вы получаете опыт и славу. Опыт дает вам возможность прокачивать своего персонажа, а слава позволяет получать назначения на новые корабли.

Прошу любить и жаловать - Star Fleet

С технической стороны вроде ничего особо сложного нет. Большая часть времени ушла на то, чтобы сделать нормальное покрытие спеками (еще не до конца доделал). По началу это доставало, но зато теперь я спокоен практически за все части приложения.

Конечно, еще много чего нужно довести до ума. В частности, практически никак не задействованы инструменты распространения информации о приложении самими юзерами, есть только форма привлечения друзей. После исправления ближайших багов возьмусь ковырять.

Хостится приложение пока на нашем сервере в Москве, поэтому тормоза те еще. Однако, уже получен бесплатный аккаунт на Joyent, надо просто перенести.

В общем, если у вас есть аккаунт на Facebook - милости просим потестировать. Если аккаунта нет - милости просим регистрироваться :)

Мой новый блог

Опубликовано 08.10.2007

Я уже писал о том, что мне надоело быть программером в глазах общества. Хочется так же поделиться своими знаниями из других сфер. Записки из тех. отдела - это больше для души, чем для продвижения каких-то собственных услуг. Если я правильно понимаю, меня читают в основном Rails-программисты, поэтому разбавлять сугубо рельсовую тематику бизнес-заметками мне бы не хотелось. Для бизнес-статей я завел отдельный блог.

Встречайте: Борода Декарта - о Web-сайтах назло Web-мастерам. Это блог о создании сайтов, ориентированный на бизнесменов. Для программистов и дизайнеров инфы уже дофига и больше, а вот для руководителей - маловато, на мой взгляд. Ну или эта инфа так глубоко закопана, что ее обычному человеку найти нереально. Я постараюсь эту ситуацию по мере сил исправить.

Блог функционирует с прошлой недели, уже даже есть пара заметок: “Вам нужен сайт? А зачем?” и “Цель номер 1: Продажа товара или услуг”. Это пока что статьи общего плана, чтобы привить более сознательное отношение к созданию сайтов.

В качестве движка был выбран WordPress. Мне очень хотелось взять какой-нибудь рельсовый движок, честное слово :) Однако, ни один из тех, которые я смотрел, не дотягивает по функционалу до вордпресса. А дописывать те плюшки, которые мне понадобятся, у меня просто нету времени. Если реально встанет необходимость развивать блог за пределы того функционала, который дает ворпресс с плагинами, я просто перепишу блог на свой движок. Патриотизм в отношении платформы тоже должен иметь разумные пределы :) Кстати, в новом блоге будет обязательно заметка о выборе платформы с точки зрения потребностей бизнеса.

Подписаться на новый блог можно через RSS: http://feeds.feedburner.com/baradekart

Быть не просто программером

Опубликовано 27.09.2007

Если честно, мне нравится программировать. Единственное что меня смущает - мне нравится программировать исключительно для себя, для своего личного удовлетворения, а не на заказ. Заказы на программинг я беру по двум причинам: реально хорошие деньги или хороший человек, которому я хочу помочь. Программить за обычное, стандартное бабло мне просто не интересно.

А вот что мне нравится больше чем программирование, так это давать людям новые знания. Мне нравится, когда меня спрашивают, что и как нужно сделать, чтобы добиться наилучшего результата. А еще больше - когда моим советам следуют. Наверное, это нормально :) За два года работы в студии у меня накопился существенный багаж знаний относительно того, как нужно делать сайты. Не как их программировать, а как их делать от начала до конца, включая поиск идеи, реализацию и дальнейшую жизнь. И мне очень хочется поделиться этими знаниями с другими людьми.

Это желание существенно окрепло с момента ухода из студии, а сейчас оно прямо таки готова воплотиться в жизнь. И тут весьма удачно пришелся эксперимент Сергея Жуковского, который “кратко” называется: «Как Сделать Более $1000 с Блога в Месяц!?» Пошаговая Стратегия Для Новичков В Бизнесе. Я решил что это знак свыше - пришло моё время. Нужно убить двух зайцев сразу - помочь людям и заработать бабла.

На следующей неделе я открываю блог о том, как российскому бизнесмену “сделать” сайт себе или своей фирме. Для многих бизнесменов и управленцев процесс создания сайта - темный лес, в котором живут страшные звери и ядовитые грибы от съедобных отличить иначе как на вкус не получается. Поэтому проблема создания сайта будет рассмотрена с нетипичной позиции - с позиции бизнесмена, организатора, а не программиста или дизайнера. Я постараюсь помочь тем, кто платит деньги, а не тем, кто их получает.

На формат этого блога новое увлечение никак не повлияет, Записки из тех. отдела как были, так и останутся отдушиной для программерской частички моей души. Баннеров на этот сайт я вешать не планирую :) Все баннеры будут на новом сайте, равно как и львиная доля самопиара.

Кстати, если кто-то так же хочет присоединиться к эксперименту - заходите на сайт Сергея и регистрируйтесь.

Мой первый проект Open Source

Опубликовано 24.08.2007

Четыре года назад я ненавидел сообщество open source разработчиков, считая их идиотами-филантропами, отбирающими хлеб у честных девелоперов, продающих деяния рук своих за реальное бабло. С тех пор утекло много воды, я многое понял. В частности, я понял, что одна голова хорошо, а многосотенное коммунити - круче. Применять чужие готовые патчи в сто раз приятнее, чем писать их самому. И вот к чему это привело…

Самому не верится, но факт - прямо сейчас заливаю на Google Code свой первый opensource-проект! До официального релиза еще далеко, но сам факт уже радует :)

Надеюсь, Google Code оправдает мое доверие в плане надежности хранения исходников. Или есть какие-то другие варианты? Проект на Ruby on Rails, в качестве системы контроля версий будет Subversion

Теперь мы просто друзья

Опубликовано 29.06.2007

Интересно, хорошо это или плохо - переворачивать столь объемные страницы в своей жизни в пятницу вечером? Я думаю, что особой разницы нет, я не верю в приметы.

То, о чем я задумывался больше года, свершилось. Я сложил бумаги в коробочку, пожал всем руки и покинул дизайн-студию “Отражение”. Я полностью выхожу из состава учередителей, передаю все свои полномочия заместителю и отстраняюсь от работы студии. Теперь мы будем просто хорошими друзьями :)

Подводя черту под этими двумя с половиною годами, я могу сказать что я ни о чем не жалею. Ни о том, что взялся за этот проект поздней осенью 2004 года, ни о том, что покидаю его теперь. Было много интересных моментов - радостных и не очень. Много клиентов - адекватных и не очень. Много открытий. Я уяснил для себя, что же такое современный российский бизнес, как изнутри, так и снаружи. Я понял, чего я по-настоящему хочу от компании, которую я мечтаю построить. От людей, которые должны мне помочь в этом. И от продукта, который эта компания должна создавать. В этом отношении Отражение стало для меня настоящей школой.

Если говорить о причинах ухода, то тут я бы выделил, в первую очередь, стремление создать что-то на 100% своё, личное. Самому выковать свой меч и свой щит. Все остальное - это шелуха, возникшая как следствие невозможности решить проблему номер один. Веб-студия такого уровня, как Отражение, требует полной отдачи от своих создателей, не оставляя времени на эксперименты и личные проекты. Поэтому я посчитал более разумным тихонько покинуть этот корабль, доверив нынешней команде дальнейшее управление. Я уверен, ребята знают что делают и вполне могут справиться без меня. Я же, взяв в руки бутыль рома и компАс, спокойно погребу туда, куда меня тянет любопытство.

Что касается дальнейших планов, то тут я пока могу сказать следующее: я собираюсь уделять гораздо больше внимания собственным проектам (об одном из них я писал ранее). Кроме того, я присоединяюсь к динамичной команде веб-разработчиков, вместе с которыми мы будем создавать весьма интересный продукт на базе платформы Ruby on Rails. Этому направлению я буду посвящать примерно половину своего рабочего времени. Ну и конечно, я смогу больше времени уделять семье и развитию себя как личности.

Став более свободным от работы с клиентами студии, я смогу заниматься проектами, которые покажутся интересными мне лично. Если у вас есть интересные идеи - милости просим в ICQ: 2406125 или Skype: rene-dekart.

Я это делал, делаю и буду делать

Опубликовано 26.06.2007

И никто меня не остановит! А именно, я буду и дальше создавать всякие разные проекты, которые могут быть полезны человечеству в целом и, в частности, мне. Постоянное создание новых проектов можно считать частью моей стратегии по диверсификации источников дохода. Хорошую статью на эту тему можно почитать у Парабеллума, он хорошо излагает основную мысль. Причем почитать и предпринять действия лучше сейчас, чтобы не напороться на этот айсберг, как я, всем брюхом на полном ходу.

Сегодня я вам хочу рассказать о моем новом проекте, которым я занимаюсь с середины мая. Проект называется Дома 2.0. Это бесплатная доска объявлений о продаже загородной недвижимости - коттеджей, дач, вилл, замков, бастоинов и т.д. :)

Основная идея состоит в том, чтобы дать людям возможность быстро и удобно найти себе жилье подальше от городской суеты и бетонных клеток, именуемых “новостройки”. Современные технологии уже вполне позволяют работать откуда угодно - достаточно провести интернет. Собственно, это и есть моя мечта - обзавестись домом, сидеть на веранде, работать на ноутбуке и глядеть на то, как жена играет с детишками во дворе. Вот так вот все прозаично :) Для тех, кто готов променять пентхаус в душном мегаполисе на загородный коттедж, и предназначен мой проект.

Из интересного на этом сайте можно выделить использование меток (тэгов) в качестве средства для географической привязки домов - указание стран, регионов, городов. Реализованы метки с помощью acts_as_taggable_on_steroids с некоторыми небольшими доработками. Кроме того, для загрузки картинок использовался не стандартный file_column или acts_as_attachment, а козырный attachment-fu. Обсчет похожих домов делается по хитрой схеме через rake. Везде используется REST, сайт завязан на Edge Rails.

Смотрите, пользуйтесь, пишите ваши замечания :)