Дело было вечером, делать было нечего и решил я написать небольшое приложение на Sinatra с Datamapper’ом. За идеей далеко ходить также не пришлось: решил написать небольшой “фильтратор” интересного для меня контента из новостей news.ycombinator.ru. Не стал изобретать велосипед на этот раз и интересными буду считать новости, названия которых содержат определенные слова. Будем отображать список прочитанных и непрочитанных новостей. Список новостей каждый час будет обновляться по cron’у – вот и вся задача.
Начнем с реализации: для этого нам понадобится:
- data_mapper с двумя адаптерами (sqlite3 для локального использование и postgresql для production’а)
- sinatra
- coffeeScript, хоть можно было и легко обойтись без него
- slim в качестве шаблонизатора
Итак, поехали:
Gemfile:
source 'https://rubygems.org'
gem 'sinatra'
gem 'data_mapper'
group :development do
gem 'dm-sqlite-adapter'
gem 'capistrano'
end
group :production do
gem 'dm-postgres-adapter'
end
gem 'slim'
gem 'coffee-script'
gem 'whenever', :require => false
gem 'nokogiri'
gem 'unicorn'
В нем нет ничего необычного, добавляем необходимые гемы для разных сред.
Теперь самое интересное: основной файл приложения, который занимает больше всего места.
./app.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
|
А теперь немного комментариев:
1-5 строки – подключаем необходимые для работы файлы
7 строка – сообщаем DataMapper’y, что длина строки (String) не 80 символов, а 400, 255 не хватает.
9-15 – конфигурируем два адаптера: один для разработки, другой для продакшна.
17-53
20,21 – объявляем интересные мне ключевые слова
23-28 – описываем все поля, которые будут в нашей модели
30-32 – метод interesting? определяет по заголовку новости интересна она мне или нет
34-40 – несколько используемых в приложении scope’ов
46-52 – метод search (из-за того, что в Postgresql like учитывает регистр букв, пришлось переписать оператор поиска на ilike, который этого не делает)
60-73 – объявляем метод, который является “сердцем” и в зависимости от параметра заполняет коллекцию определенными статьями и рендерит вьюху ./views/index.slim
76-78 – рендерим coffeeScript, которые делает следующее, если мы кликам по новости, то отправляем ajax post запрос и помечаем новость как прочитанную (read_at = Time.now)
80-84 – сам метод, который помечает новость прочитанной при post запросе
86-100 – разные коллекции (все, прочитанные, непрочитанные и т.д.)
теперь Rakefile, который будет парсить news.ycombinator.com каждый час
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
В нем всего две задачи: первая – парсит новости, вторая нужна для того, что если вдруг изменися интересные ключевые слова, то вы сможете легко обновить список инетересных вам новостей.
Файл, который отвечает за частоту выполнения определенных тасков ./config/shedule.rb
1 2 3 4 5 6 7 |
|
В первой строчке я указываю путь до файла с логами, чтобы каждый раз при запуске rake task’а в конец добавлялось время последнего обновления. В блоке с every можно очень гибко указать как часто выполняться, смотрите документацию к гему whenever.
Также я добавил несколько строк к файлу, выполняющего деплой из Разворачиваем Rails приложение вместе с Capistrano. ./config/deploy.rb
1 2 3 4 5 |
|
Теперь мы можем запустить обновления cron’а deployer’а командой cap whenever:update_crontab
После ее запуска вы можете проверить, что вышло, обновился ли cron, запустив на сервере, список cron задач: crontab -l
Без комментариев оставлю вьюхи, но текст их приведу.
./views/application.coffee
1 2 3 4 |
|
./views/layout.slim
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
И наконец, ./views/index.slim
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Получислось такое незамысловатое и некрасивое приложение :).
Вместо заключения: чтобы мозги не были напичканы только рельсами (читать как одним фреймворком), мне кажется, необходимо покидать зону комфорта и писать небольшые приложения для души на смежных технологиях. Скажу честно, для того, чтобы реализовать это несложное приложение у меня ушло масса времени на чтение мануалов к Sinatra, DataMapper’у, нежели на написание кода. Но мне понравилось, практической ценности, конечно, приложение почти не имеет, но мозги размялись однозначно. Разминай мозги, коллега :)