Поём вместе с Sinatra. Часть первая. Первое знакомство

Ruby*
Доброго времени суток!

Что такое Sinatra


Sinatra — маленький, но довольно интересный DSL (Domain-specific language) фреймворк, написанный на Ruby. В отличие от Ruby on Rails он не следует типичному паттерну MVC (Model — View — Controlller). Sinatra создавался для того, чтобы «программист смог быстро создать веб приложение, написанное на Ruby с минимальными усилиями.

Для того, чтобы воспользоваться Sinatra нам неорбходимо его установить. Сделать это можно следующей командой в RubyGems:

gem install sinatra

Также нам понадобится гем под названием Shotgun. Нужен он нам для того, чтобы лишний раз не перезагружать сервер вручную. Shotgun сделает это за нас. Давайте установим его:

gem install shotgun

Ну вот и всё! Всё необходимое для работы у нас есть. Настал момент для творчества. Приступим…


Hello, Sinatra!


А напишем мы простенькое приложение, которое приветствует само себя. Искренне надеюсь, что Фрэнк не перевернётся в гробу. Итак, вот оно, наше приложение:

require "sinatra"

get "/" do
     "Hello, Sinatra!"
end


Осталось только запустить сервер. Сделать это можно набрав следующую команду:

ruby -rubygems path_to_file\app.rb

Теперь мы можем открыть браузер. В омнибокс необходимо набрать адрес localhost:4567. Вуаля!



Поздравляю! Только что мы написали первое веб приложение с помощью Sinatra.

Разбор полётов


Несмотря на то, что это был простейший пример, не мешало бы разобраться что выполняет наш код.
С начала хотелось заметить, что при разработке веб приложений я использую Ruby версии 1.9. В случае, если вы используете версию 1.8., вам необходимо добавить ещё одну строчку в ваш код. Вот она:

require "rubygems"

Двигаемся дальше. Мы говорим нашему приложению, что если пользователь в адресной строке вбивает адрес нашего сайта, то он попадает именно на эту страницу, т.е. на главную, где мы приветствуем Фрэнка. В случае, если пользователь указывает в адресной строке, например, /about, то ему выдаётся следующая ошибка:



Давайте же обработаем ошибку Not Found. Сделать это можно следующим способом:

not_found do
     status 404
     "Something wrong! Try to type URL correctly or call to UFO."
end


Теперь наберём в адресной строке localhost:4567/about и увидим нашу с вами страничку, которая сообщает пользователю о том, что случилось что-то не то.

Hello, %username%


Пора бы вспомнить о том, что мы познакомились с Фрэнком, а он с нами нет. Не дай Бог, конечно. Но заставить наш браузер поприветствовать нас мы можем. Сделать это можно с помощью параметра name. Его обработка будет выглядеть так:

get "/hello/:name" do
     "Hello, #{params[:name]}."
end

Осталось лишь набрать localhost:4567/hello/your_name и вы увидите приветствие в ваш адрес. Вот, например:



Я там, где ты


Именно этим выражением мы можем охарактеризовать ситуацию, когда нам необходимо, например, отдавать пользователю лишь одну страничку, но вне зависимости от того, какой адрес он наберёт. Делается это путём указания звёздочки после слэша. Вот так:

get "/*" do
     "It's the main page of this site you can see right now!"
end


Теперь куда бы вы не хотели попасть, вы будете видеть одну и ту же страницу. Кстати, вот и она:






Значение параметра, заданного в URI мы можем получить с помощью аттрибута splat. Вот так вот:

get "/*" do
     "I don't know what is the #{params[:splat]}. It's what you typed."
end


Вуаля! Чтобы мы не набрали в адресной строке, а увидим набранный URI.




Заключение


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

Куда двигаться дальше


Введение в Sinatra.
Официальный сайт Sinatra.
Singing with Sinatra.
+26
20 февраля 2012, 17:34
76
krovatti 97,8

комментарии (46)

–1
eyeofhell #
Из документации не совсем понятно, как подключать безопасность к отдельным страницам (наиболее часто встречающийся кейс). На выбор даны два варианта — одной строчкой но на все страницы (на практике нафиг не нужно) либо в огромное количество строчек вручную для нужных страниц.
0
qwertysx #
Вы сейчас о чем говорите?
0
eyeofhell #
О подключении безопасности к приложению. Одностроковый способ:

use Rack::Auth::Basic do |name, pass| name == 'a' and pass == '1' end

Работает на все приложение (на все route/страницы) что не есть хорошо. Для установки безопасности на одну страницу (route) нужно очень много строк кода.
Вот интересуюсь, может кто знает с чего такая несправедливость.
0
GearHead #
> Работает на все приложение (на все route/страницы) что не есть хорошо.
и почему это не хорошо?
0
VolCh #
Потому что могут быть страницы доступные публично, а могут быть закрытые. Простой пример — админка.
0
GearHead #
и вам что, не нужна CSRF защита в админке?
0
GearHead #
я уже молчу про XSS
0
GearHead #
поясню свой комментарий: господин eyeofhell использует rack-protection для HTTP AUTH. сам rack-protection был сделан, чтобы сделать защиту от целого спектра атак на веб-приложения. а HTTP Auth обычно реализовывают немного по-другому.
0
eyeofhell #
Если расскажете как в Rack+Sinatra в не очень большое количество строк кода защитить только админку — буду благодарен.
+1
GearHead #
как вам написали ниже, это делается через хелперы. нельзя просто так прописать тот же самый Rack::Auth::Basic для отдельных запросов, потому что это middleware. делайте, как описано в faq.
www.sinatrarb.com/faq.html#auth
+1
VolCh #
А откуда вы взяли про rack-protection? Я на rack.rubyforge.org/doc/Rack/Auth/Basic.html никакого упоминания не вижу.
+1
GearHead #
точно. почему-то был уверен, что Rack::Auth вынесен в github.com/rkh/rack-protection, а он, оказывается, в core. тем не менее, всё равно это делается только через хелперы
0
peanut #
Вы просто запихните авторизация в хелпер и защищайте лишь тебе роуты, которые нужны, вызывая его.
0
eyeofhell #
Это тот самый второй способ — много строчек кода. Или есть способ как-то кратко это записать?
+2
qwertysx #
много это во сколько? 10 строк это много?
0
eyeofhell #
Для DSL — да. Смысл DSL как раз в том, что описывающие конструкции немногословны, описывают саму суть и зрят в корень. Понятно что ручками можно все реализовать. Но ведь весь профит теряется :). Что немного огорчает. Ну раз через хелперы — то через хелперы, мне в принципе все равно.
+1
GearHead #
есть Sinatra, который DSL, а есть Rack, функциональность которого вы используете. зачем мешать одно в другое?
0
eyeofhell #
Как уже говорилось, я надеялся, что эту функциональность добрые авторы Sinatra вынесли в DSL как часто используемую. Ну не вынесли и не вынесли, что ж поделаешь :).
+1
GearHead #
часто используемую кем? сейчас люди для авторизации обычно пользуются сессией и красивенькой формой входа. HTTP Auth это как бы прошлый век.

и вообще, не путайте DSL и boilerplate. целью DSL не является описать всю самую используемую функциональность.
0
Source #
Если бы в Sinatra добавили часто используемые фичи, то это был бы не DSL, а фреймворк…
А так есть DSL и есть куча надстроек над ним, начиная от sinatra-basic-auth и до Padrino — фреймворка поверх Sinatra.
+1
peanut #
Ну вот как раз по ссылке в комментарие выше приведен пример с методом «protected!», он конечно длиннее одной строчки, но всего один раз надо записать
0
eyeofhell #
Я надеялся, что в синатре его уже написали. Ну нет так нет, отсутствие информации — это тоже ценная информация :).
+1
VolCh #
helpers do

  def protected!
    unless authorized?
      response['WWW-Authenticate'] = %(Basic realm="Restricted Area")
      throw(:halt, [401, "Not authorized\n"])
    end
  end

  def authorized?
    @auth ||=  Rack::Auth::Basic::Request.new(request.env)
    @auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == ['admin', 'admin']
  end

end

["/foo", "/bar", "/baz"].each do |path|
  get path do
    protected!
    "You've reached me at #{request.path_info}"
  end
end


По идее должно работать :)
0
Chesnovich #
Для php Есть F3-фреймворк, для node.js — expressJS в таком стиле… очень удобно для небольших проектов… а так в основном пользуюсь Yii, RoR
0
VolCh #
Для PHP аналог скорее Silex
0
qwertysx #
Для клиентского js есть sammy
0
xabaz #
Так же для PHP мне приглянулся fitzgerald
0
Chesnovich #
В этом случае лучше yii использовать
0
Barttos #
+1
rsludge #
лучше бы вы сделали перевод той статьи(точнее серии статей), у которой вы сперли название
+1
krovatti #
Я вытащил материал оттуда некоторый и расставил его по следующим частям. Всё будет ;)
+1
GearHead #
> gem install shotgun

вы подключили гем, и при этом не используете его. к вашему сведению, кстати, thin (который по дефолту подхватывается, если установлен) сам перезагружает среду.
0
krovatti #
Я знаю. Он будет в следующей части. Не знаю, правда, почему, но будет.
0
ka8725 #
Хотелось бы знать насколько просто написать приложение на Sinatra с вложенным формами, кучей связей между моделями, наследованием контроллеров и т.д. ну в общем достаточно сложное приложение. В каких целях лучше применять Sinatra вместо Ruby On Rails? Преимущества Sinatra перед другими Ruby фреймворками для web в чем?
0
krovatti #
В вашем случае нужно использовать рельсы. Синатра не следует паттерну Модель — Вьюха — Контроллёр. Он является DSL фреймворком. Он не обременён лишним мусором, а предоставляет самое необходимое. Рельсы же, как по мне, монструозны. Сразу оговорюсь, что это лично мое мнение дабы не разжигать спор. Как пример, LinkedIn и Github используют именно Синатру.
0
GearHead #
Github не юзает синатру. просто многие у них её пилили. а LinkedIn вообще по большей части на Java и Scala.
0
VolCh #
Насколько я понимаю, Синатра реализует контроллер из триады MVC. Следовать ей в остальном или нет — выбор разработчика. Но по опыту разработки без использования фреймворков для многих задач архитектура как-то сама сводится к MVC. Собственно лет 5 назад я с удивлением узнал, что использую MVC уже лет 5 :)
0
AlexeiZhuravlev #
Использую Sinatra в нескольких проектов со средней нагрузкой (Более миллиона просмотров страниц в сутки). Доволен как слон. Знакомство с ruby, как и все начинал с Rails, но потом осознал, что он слишком монструозен. Зачем мне куча функций в проекте, которыми я не пользуюсь.

Синатра в этом плане идеальный вариант. Подключил необходимые гемы, написал все лаконично благодаря DSL, настроил кластер веб-серверов в связе с nginx. Как результат — все быстро и отлично работает.

Думаю, что слишком много внимания уделяется Rails в руби-сообществе. Синатра хоть и не обладает куче наворотов, но всегда можно подключить необходимый функционал и получить бешеную производительность. И все это при меньшем пороге вхождения в фреймворк и более четкой структурой работы.
0
krovatti #
Прошу прощения. Промахнулся с ответом. Ниже ответ вам.
0
VolCh #
Думаю, что слишком много внимания уделяется Rails в руби-сообществе.

С другой стороны, это плюс руби перед самым-популярным-в-вебе-языком-сами-знаете-каком. Поверьте на слово, разобщенность сообщества по десятку-другому плюс-минус одинаково популярным фреймворкам играет не на пользу сообщества. Пока есть мэйнстрим, все хотя бы говорят на одном более-менее общем языке, даже если мэйнстримом не пользуются. Опять же перед новичками не стоит проблема выбора. Про меркантильные преимущества даже заикаться не буду.
0
Source #
> В каких целях лучше применять Sinatra вместо Ruby On Rails?

Sinatra хорошо подходит для написания веб-сервисов, когда у вас нет фронтенда в виде веб-интерфейса… Ну самый распространённый пример — флеш-игра в какой-нибудь соц.сети.
Для не слишком больших веб-приложений также имеет смысл присмотреться к Padrino.

Хотя сейчас границы применимости всё больше смешиваются, в том же RoR можно использовать и Rack-вызовы напрямую, и убрать все модули, ненужные для конкретного случая, из контроллера. Т.е. по сути в большинстве случаев это уже дело вкуса… исходя из того, что вам ближе: выпиливание или допиливание, убирать ненужные модули или искать и добавлять нужные.

P.S. Любителям легковесных контроллеров стоит присмотреться к Cells, которые с недавних пор можно использовать и для внешних вызовов.
0
krovatti #
Вот именно. Sinatra предоставляет необходимый минимум для того, чтобы постороить на нём неплохое приложение. Также импонирует то, что это DSL фреймворк, предоставляющий гибкую и легковесную платформу для создания веб приложений. Он не является избыточным, как рельсы.
0
makaroni4 #
А где использовался шотган? Я так понимаю, что нужно было:

shotgun -p 4567 my_simple_app.rb
0
zim32 #
А есть возможность именовать маршруты. Например как генерировать url имя такую запись
get "/*" do

end
0
vazilla #
Вот здесь документация на русском по Sinatra обновляется быстрее, чем на официальном сайте (sinatrarb.com)
0
Chikey #
очередная статья которой лучше было бы не быть
1) под виндой? lol u mad?
2) 3-5 скринов а толка на 5 строчек текста.
хватит писать типы для домохозяек, пишите нормальные статьи на полезные и глубокие темы.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.