Журнал LinuxFormat - перейти на главную

LXF89:Нестандартное программирование

Материал из Linuxformat
(Различия между версиями)
Перейти к: навигация, поиск
(Новая: == Ruby без Rails == ''Вы слыхали о Ruby on Rails – а сейчас '''Майк Сондерс''' расскажет вам о его основе, Ruby, ярком при...)
 
м (Мысли напоследок)
 
(не показана 1 промежуточная версия 1 участника)
Строка 1: Строка 1:
 
== Ruby без Rails ==
 
== Ruby без Rails ==
''Вы слыхали о Ruby on Rails – а сейчас '''Майк Сондерс''' расскажет вам о его основе, Ruby, ярком примере современного языка высокого уровня…''
+
''Вы слыхали о Ruby on Rails — а сейчас '''Майк Сондерс''' расскажет вам о его основе, Ruby, ярком примере современного языка высокого уровня…''
  
 
'''Вот и еще одна статья из цикла об «экзотических» языках программирования. Язык Tcl, с которым мы познакомились месяц назад, очень подходит для разработки оконных приложений с графическим интерфейсом, а сейчас мы займемся Ruby, предназначенным для создания серверных и сетевых приложений. Заскучали? Напрасно. Сейчас объясним, почему.'''
 
'''Вот и еще одна статья из цикла об «экзотических» языках программирования. Язык Tcl, с которым мы познакомились месяц назад, очень подходит для разработки оконных приложений с графическим интерфейсом, а сейчас мы займемся Ruby, предназначенным для создания серверных и сетевых приложений. Заскучали? Напрасно. Сейчас объясним, почему.'''
  
Мы постараемся не погрязнуть в техноязе: на то есть подробнейшая документация. Вместо этого мы начнем с основ языка, затем напишем простенькое приложение, а в завершение – полноценный web-проект. Вы уже знакомы с азами программирования? Отлично! Читайте дальше, и вы поймете, что Ruby достоин вашего внимания. Многие из нас слышали о Ruby в контексте Ruby on Rails, современного программного каркаса [framework]. На его основе сейчас разрабатываются крупные сайты (например, Basecamp, Jobster или 43 Things), и он поставляется с новой версией OS X, Leopard. На ринг Ruby вышел совсем недавно, и тем удивительнее тот факт, что его разработка ведется с 1993 года!
+
Мы постараемся не погрязнуть в техноязе: на то есть подробнейшая документация. Вместо этого мы начнем с основ языка, затем напишем простенькое приложение, а в завершение — полноценный web-проект. Вы уже знакомы с азами программирования? Отлично! Читайте дальше, и вы поймете, что Ruby достоин вашего внимания. Многие из нас слышали о Ruby в контексте Ruby on Rails, современного программного каркаса [framework]. На его основе сейчас разрабатываются крупные сайты (например, Basecamp, Jobster или 43 Things), и он поставляется с новой версией OS X, Leopard. На ринг Ruby вышел совсем недавно, и тем удивительнее тот факт, что его разработка ведется с 1993 года!
  
 
Детище Юкихиро Мацумото [Yukihiro Matsumoto] увидело свет в 1995 году. Ключевой особенностью языка стал принцип освобождения программиста от черной работы. Зачем продираться через заковыристый синтаксис, если требуется сделать что-то простое?
 
Детище Юкихиро Мацумото [Yukihiro Matsumoto] увидело свет в 1995 году. Ключевой особенностью языка стал принцип освобождения программиста от черной работы. Зачем продираться через заковыристый синтаксис, если требуется сделать что-то простое?
  
Проработав более двух лет на C++ и найдя, что он все еще сталкивается с неприятными сюрпризами, Мацумото решил создать язык, максимально оправдывающий ожидания – чтобы в нем программы делали именно то, что интуитивно предполагалось, и отсутствовали тупиковые случаи. «Прежде всего надо думать о людях», провозгласил Юкихиро, «о том, как они мыслят о программе и как представляют себе действия машин. Люди – хозяева. А машины – работники».
+
Проработав более двух лет на C++ и найдя, что он все еще сталкивается с неприятными сюрпризами, Мацумото решил создать язык, максимально оправдывающий ожидания — чтобы в нем программы делали именно то, что интуитивно предполагалось, и отсутствовали тупиковые случаи. «Прежде всего надо думать о людях», провозгласил Юкихиро, «о том, как они мыслят о программе и как представляют себе действия машин. Люди — хозяева. А машины — работники».
  
С историей – все, теперь о кодировании: Ruby называют «мультипарадигменным» [multiparadigm] языком. Это жутковатое слово означает, что язык включает и объектно ориентированный подход, и процедуры с функциями. Ruby – интерпретирующий язык, и его синтаксис близок к Python и Perl, поэтому он осваивается без труда.
+
С историей — все, теперь о кодировании: Ruby называют «мультипарадигменным» [multiparadigm] языком. Это жутковатое слово означает, что язык включает и объектно ориентированный подход, и процедуры с функциями. Ruby — интерпретирующий язык, и его синтаксис близок к Python и Perl, поэтому он осваивается без труда.
  
 
=== Освоимся ===
 
=== Освоимся ===
 
Для начала нам понадобятся интерпретатор языка Ruby и интерактивный интерпретатор ''irb'', поставляемые с большинством дистрибутивов. Последнюю версию этих программ вы найдете в разделе '''Разработка''' нашего DVD.
 
Для начала нам понадобятся интерпретатор языка Ruby и интерактивный интерпретатор ''irb'', поставляемые с большинством дистрибутивов. Последнюю версию этих программ вы найдете в разделе '''Разработка''' нашего DVD.
  
Вызовем интерпретатор, набрав '''irb''' в командной строке. На экране появится строка приглашения – можно с ходу вводить операторы языка. По традиции полагалось бы вывести “Hello world” – «Здравствуй, мир», но это старо как мир... Будем оригинальны:
+
Вызовем интерпретатор, набрав '''irb''' в командной строке. На экране появится строка приглашения — можно с ходу вводить операторы языка. По традиции полагалось бы вывести «Hello world» — «Здравствуй, мир», но это старо как мир… Будем оригинальны:
  
 
<source lang="ruby">
 
<source lang="ruby">
puts “Goodbye moon!
+
puts "Goodbye moon!"
 
</source>
 
</source>
  
Вроде все ясно: команда '''puts''' просто выводит на экран текстовую строку. Но в Ruby абсолютно все, даже строковые константы, это объекты. Может, оно и странно, зато позволяет делать штуки вроде
+
Вроде все ясно: команда '''puts''' просто выводит на экран текстовую строку. Но в Ruby абсолютно все, даже строковые константы, — это объекты. Может, оно и странно, зато позволяет делать штуки вроде
  
 
<source lang="ruby">
 
<source lang="ruby">
“BlaBlaBlaa”.length
+
"BlaBlaBlaa".length
 
</source>
 
</source>
  
С виду чушь, а на выходе печатается '''10''' вполне настоящая длина строки. Или, например,
+
С виду чушь, а на выходе печатается '''10''' — вполне настоящая длина строки. Или, например,
  
 
<source lang="ruby">
 
<source lang="ruby">
“Mmm, donuts”.index(“d”)
+
"Mmm, donuts".index("d")
 
</source>
 
</source>
  
 
возвращает '''5''', позицию символа '''d''' в заданной строке. (Учтите, нумерация в Ruby начинается с нуля, а не с единицы.)
 
возвращает '''5''', позицию символа '''d''' в заданной строке. (Учтите, нумерация в Ruby начинается с нуля, а не с единицы.)
  
Итак, Ruby – страна объектов, где программировать значительно проще. Вдобавок, это еще и язык с динамической типизацией: переменные не нужно объявлять до их использования. Вот пример:
+
Итак, Ruby — страна объектов, где программировать значительно проще. Вдобавок, это еще и язык с динамической типизацией: переменные не нужно объявлять до их использования. Вот пример:
  
 
<source lang="ruby">
 
<source lang="ruby">
puts “Do you love Ruby yet?
+
puts "Do you love Ruby yet?"
 
answer = gets
 
answer = gets
puts “You answered + answer
+
puts "You answered " + answer
 
</source>
 
</source>
  
На экран выводится вопрос, потом объявляется переменная '''answer''', и в нее тут же записывается результат команды '''gets''' (ввод строки с клавиатуры). Наш ответ затем выводится на экран.  
+
На экран выводится вопрос, потом объявляется переменная '''answer''', и в нее тут же записывается результат команды '''gets''' (ввод строки с клавиатуры). Наш ответ затем выводится на экран.
  
 
Заодно продемонстрирована операция над переменными: строки можно складывать ('''+''') и даже умножать:
 
Заодно продемонстрирована операция над переменными: строки можно складывать ('''+''') и даже умножать:
  
 
<source lang="ruby">
 
<source lang="ruby">
mystring = “Some” + “text”
+
mystring = "Some" + "text"
 
puts mystring
 
puts mystring
anotherstring = “Wowzers” * 10
+
anotherstring = "Wowzers" * 10
 
puts anotherstring
 
puts anotherstring
 
</source>
 
</source>
  
Сначала две строки объединяются, и результат выводится на экран. Затем строка '''anotherstring''' заполняется десятью копиями строки '''Wowzers''', и результат также выводится на экран. Именно эффективные функции обработки текста обеспечили Ruby место под солнцем в мире разработчиков сайтов. Неплохо знать и метод '''chomp''' (вы могли встретить его в Perl): он убирает из строки последний символ, перевод строки ('''\n'''), который автоматически добавляется командой '''gets''' при вводе. Метод понадобится в тех случаях, когда нужно преобразовать введенную строку в число, т.е. в «голые цифры»:
+
Сначала две строки объединяются, и результат выводится на экран. Затем строка '''anotherstring''' заполняется десятью копиями строки '''Wowzers''', и результат также выводится на экран. Именно эффективные функции обработки текста обеспечили Ruby место под солнцем в мире разработчиков сайтов. Неплохо знать и метод '''chomp''' (вы могли встретить его в Perl): он убирает из строки последний символ, перевод строки ('''\n'''), который автоматически добавляется командой '''gets''' при вводе. Метод понадобится в тех случаях, когда нужно преобразовать введенную строку в число, то есть в «голые цифры»:
  
 
<source lang="ruby">
 
<source lang="ruby">
Строка 68: Строка 68:
 
</source>
 
</source>
  
Это показывает, что '''x''' число, а не строка. Но мы можем немедля использовать '''x''' и как строку, если надо – благодаря динамической типизации. [Вопросительный знак является допустимым символом и часто используется в Ruby в именах методов, которые «отвечают на вопрос», прим. ред.]
+
Это показывает, что '''x''' — число, а не строка. Но мы можем немедля использовать '''x''' и как строку, если надо — благодаря динамической типизации. [Вопросительный знак является допустимым символом и часто используется в Ruby в именах методов, которые «отвечают на вопрос», — прим. ред.]
  
 
=== Условия, циклы и функции ===
 
=== Условия, циклы и функции ===
Разобравшись с переменными и вводом/выводом строк, перейдем к управляющим конструкциям языка. Каждый из приведенных ниже примеров нужно предварительно сохранить в текстовом файле и запускать командой '''ruby <имя_файла>'''. Сохраните следующий пример в файле '''test.rb''' и запустите командой '''ruby test.rb''' он иллюстрирует использование условного оператора '''if''' и кодовых блоков:
+
Разобравшись с переменными и вводом/выводом строк, перейдем к управляющим конструкциям языка. Каждый из приведенных ниже примеров нужно предварительно сохранить в текстовом файле и запускать командой '''ruby <имя_файла>'''. Сохраните следующий пример в файле '''test.rb''' и запустите командой '''ruby test.rb''' — он иллюстрирует использование условного оператора '''if''' и кодовых блоков:
  
 
<source lang="ruby">
 
<source lang="ruby">
puts “How many kittens do you have?
+
puts "How many kittens do you have?"
 
x = gets.chomp.to_i
 
x = gets.chomp.to_i
 
if x > 0 # More than zero kittens
 
if x > 0 # More than zero kittens
     puts “You have + x.to_s + “ kittens”
+
     puts "You have " + x.to_s + " kittens"
 
else
 
else
     puts “Aww, you have no kittens!
+
     puts "Aww, you have no kittens!"
 
end
 
end
 
</source>
 
</source>
Строка 85: Строка 85:
 
Мы запрашиваем у пользователя строку, затем уже известным нам методом '''to_i''' преобразуем ее в число. Далее оператор условия '''if''' сравнивает введенное число с нулем. Если условие в операторе '''if''' истинно, число преобразуется в строку с помощью метода '''to_s''', чтоб вписать его в сообщение, и сообщение выводится его на экран.
 
Мы запрашиваем у пользователя строку, затем уже известным нам методом '''to_i''' преобразуем ее в число. Далее оператор условия '''if''' сравнивает введенное число с нулем. Если условие в операторе '''if''' истинно, число преобразуется в строку с помощью метода '''to_s''', чтоб вписать его в сообщение, и сообщение выводится его на экран.
  
Если же пользователь ввел '''0''', выполняются команды, расположенные после '''else''', то есть выводится другое сообщение. Блок кода завершается командой '''end'''. Между прочим, для лучшей читаемости текста мы применили отступы – можно их вводить клавишей табуляции, а можно и просто пробелами. Все как в других языках!
+
Если же пользователь ввел '''0''', выполняются команды, расположенные после '''else''', то есть выводится другое сообщение. Блок кода завершается командой '''end'''. Между прочим, для лучшей читаемости текста мы применили отступы — можно их вводить клавишей табуляции, а можно и просто пробелами. Все как в других языках!
  
 
Справа от оператора '''if''' помещен комментарий (в языке Ruby они предваряются символом '''#''').
 
Справа от оператора '''if''' помещен комментарий (в языке Ruby они предваряются символом '''#''').
Строка 93: Строка 93:
 
<source lang="ruby">
 
<source lang="ruby">
 
10.times do
 
10.times do
     puts “Ruby rocks”
+
     puts "Ruby rocks"
 
end
 
end
 
</source>
 
</source>
  
Все ясно – десять раз выводится строка! Оператор '''while''' ничуть не сложнее:
+
Все ясно — десять раз выводится строка! Оператор '''while''' ничуть не сложнее:
  
 
<source lang="ruby">
 
<source lang="ruby">
 
x = 0
 
x = 0
 
while x != 15
 
while x != 15
     puts “Please enter 15”
+
     puts "Please enter 15"
 
     x = gets.chomp.to_i
 
     x = gets.chomp.to_i
 
end
 
end
Строка 109: Строка 109:
 
Этот код требует у пользователя ввода строки до тех пор, пока не получит число '''15'''. Тогда он покидает блок '''while/end''' и продолжает выполнение кода (правда, в данном случае выполнять уже нечего).
 
Этот код требует у пользователя ввода строки до тех пор, пока не получит число '''15'''. Тогда он покидает блок '''while/end''' и продолжает выполнение кода (правда, в данном случае выполнять уже нечего).
  
Программирование на языке высокого уровня обязательно подразумевает модульность, так что займемся процедурами. Как мы уже говорили, Ruby – объектно-ориентированный (ОО) язык, аналогично C++, C# или Python. Но даже если вы знакомы только с обычным C, можете не бояться ОО-сложностей, по крайней мере, на начальном этапе. Рассмотрим использование функций:
+
Программирование на языке высокого уровня обязательно подразумевает модульность, так что займемся процедурами. Как мы уже говорили, Ruby — объектно-ориентированный (ОО) язык, аналогично C++, C# или Python. Но даже если вы знакомы только с обычным C, можете не бояться ОО-сложностей, по крайней мере, на начальном этапе. Рассмотрим использование функций:
  
 
<source lang="ruby">
 
<source lang="ruby">
Строка 116: Строка 116:
 
     return value
 
     return value
 
end
 
end
puts “Enter a number”
+
puts "Enter a number"
 
x = gets.chomp.to_i
 
x = gets.chomp.to_i
 
y = doubler(x)
 
y = doubler(x)
Строка 122: Строка 122:
 
</source>
 
</source>
  
Первая половина скрипта – описание функции, она не будет исполняться при запуске. Функция '''doubler''' умножает число '''value''' (аргумент функции) на два и возвращает результат. Из кода видно, как используется функция. (Обратите внимание, что функции должны быть объявлены до их использования, иначе Ruby выдаст ошибку.)
+
Первая половина скрипта — описание функции, она не будет исполняться при запуске. Функция '''doubler''' умножает число '''value''' (аргумент функции) на два и возвращает результат. Из кода видно, как используется функция. (Обратите внимание, что функции должны быть объявлены до их использования, иначе Ruby выдаст ошибку.)
  
 
{{Врезка|
 
{{Врезка|
Строка 132: Строка 132:
 
* http://tryruby.hobix.com Онлайн-курс.|
 
* http://tryruby.hobix.com Онлайн-курс.|
 
Ширина=50%}}
 
Ширина=50%}}
Выполнение программы начинается с команды '''puts''': у пользователя запрашивают число, и оно передается в качестве параметра функции '''doubler'''. Результат, возвращаемый функцией, записывается в переменную '''y'''. Наконец, значение переменной '''y''' выводится на экран. Создание объектов в Ruby выходит за рамки данной статьи; хотите узнать больше – обратитесь на сайты, указанные во врезке «Ссылки» на этой странице.
+
Выполнение программы начинается с команды '''puts''': у пользователя запрашивают число, и оно передается в качестве параметра функции '''doubler'''. Результат, возвращаемый функцией, записывается в переменную '''y'''. Наконец, значение переменной '''y''' выводится на экран. Создание объектов в Ruby выходит за рамки данной статьи; хотите узнать больше — обратитесь на сайты, указанные во врезке «Ссылки» на этой странице.
  
 
=== Работать чисто ===
 
=== Работать чисто ===
Строка 138: Строка 138:
  
 
<source lang="ruby">
 
<source lang="ruby">
puts “Divide 5 by what?
+
puts "Divide 5 by what?"
 
x = gets.chomp.to_i
 
x = gets.chomp.to_i
 
begin
 
begin
 
     y = 10 / x
 
     y = 10 / x
 
rescue ZeroDivisionError
 
rescue ZeroDivisionError
     puts “Eeep, divide by zero!
+
     puts "Eeep, divide by zero!"
 
end
 
end
 
puts y.to_s
 
puts y.to_s
Строка 152: Строка 152:
 
А вдруг он введет ноль? Возникнет ошибка. В таких случаях происходит возврат в командную строку и вывод сообщения, над которым вы и будете ломать голову. Но мы не зря ввели обработчик исключения. Возникшая исключительная ситуация (деление на ноль) будет зафиксирована, и выполнится оператор '''puts''' внутри обработчика исключения, который выведет на экран сообщение об ошибке.
 
А вдруг он введет ноль? Возникнет ошибка. В таких случаях происходит возврат в командную строку и вывод сообщения, над которым вы и будете ломать голову. Но мы не зря ввели обработчик исключения. Возникшая исключительная ситуация (деление на ноль) будет зафиксирована, и выполнится оператор '''puts''' внутри обработчика исключения, который выведет на экран сообщение об ошибке.
  
Обработка исключений исключительно удобна: она спасает вас от ползания по коду в поисках проблемы и вставки проверок куда ни попадя. Ваш опрятный и компактный код отловит множество видов ошибок при исполнении, открытии файла и т.д.
+
Обработка исключений исключительно удобна: она спасает вас от ползания по коду в поисках проблемы и вставки проверок куда ни попадя. Ваш опрятный и компактный код отловит множество видов ошибок при исполнении, открытии файла и т. д.
  
 
=== Создаем web-сервер ===
 
=== Создаем web-сервер ===
Применим полученные знания и напишем собственный… web-сервер! Экстрим? Да нет, в Ruby это совсем несложно, благодаря библиотеке socket. Конечно, для ''Apache'' наш сервер конкурентом пока не станет, но зато продемонстрирует возможности Ruby. И вообще, зачем устанавливать и настраивать мощный сервер, если вам всего-то нужно хранить пару web-страничек для доступа к ним по локальной сети? Вы напишете собственный сервер на Ruby быстрее, чем произнесете /etc/apache/httpd.conf”!
+
Применим полученные знания и напишем собственный… web-сервер! Экстрим? Да нет, в Ruby это совсем несложно, благодаря библиотеке socket. Конечно, для ''Apache'' наш сервер конкурентом пока не станет, но зато продемонстрирует возможности Ruby. И вообще, зачем устанавливать и настраивать мощный сервер, если вам всего-то нужно хранить пару web-страничек для доступа к ним по локальной сети? Вы напишете собственный сервер на Ruby быстрее, чем произнесете «/etc/apache/httpd.conf»!
  
 
Сохраните следующий код в файле '''webserver.rb''' в вашем домашнем каталоге. (Если вам лень набирать, возьмите его из раздела '''Magazine/Ruby''' нашего DVD.) Затем создайте в этом же каталоге две HTML-странички: '''index.html''' и '''test.html''', с произвольным содержимым, лишь бы выводилось в браузере.
 
Сохраните следующий код в файле '''webserver.rb''' в вашем домашнем каталоге. (Если вам лень набирать, возьмите его из раздела '''Magazine/Ruby''' нашего DVD.) Затем создайте в этом же каталоге две HTML-странички: '''index.html''' и '''test.html''', с произвольным содержимым, лишь бы выводилось в браузере.
  
 
<source lang="ruby">
 
<source lang="ruby">
require ‘socket’
+
require 'socket'
webserver = TCPServer.new(‘127.0.0.1’, 7125)
+
webserver = TCPServer.new('127.0.0.1', 7125)
 
while (session = webserver.accept)
 
while (session = webserver.accept)
     session.print “HTTP/1.1 200/OK\r\nContent-type:text/html\r\n\r\n”
+
     session.print "HTTP/1.1 200/OK\r\nContent-type:text/html\r\n\r\n"
 
     request = session.gets
 
     request = session.gets
     trimmedrequest = request.gsub(/GET\ \//, ‘’).gsub(/\ HTTP.*/, ‘’)
+
     trimmedrequest = request.gsub(/GET\ \//, '').gsub(/\ HTTP.*/, '')
 
     filename = trimmedrequest.chomp
 
     filename = trimmedrequest.chomp
     if filename == “”
+
     if filename == ""
         filename = “index.html”
+
         filename = "index.html"
 
     end
 
     end
 
     begin
 
     begin
         displayfile = File.open(filename, ‘r’)
+
         displayfile = File.open(filename, 'r')
 
         content = displayfile.read()
 
         content = displayfile.read()
 
         session.print content
 
         session.print content
 
     rescue Errno::ENOENT
 
     rescue Errno::ENOENT
         session.print “File not found”
+
         session.print "File not found"
 
     end
 
     end
 
     session.close
 
     session.close
Строка 190: Строка 190:
 
Дополнительные модули можно загрузить через систему RubyGems, аналогичную CPAN для Perl. Разработаны модули для взаимодействия с базой данных MySQL, разработки приложений для Gnome и KDE и т.д. Похоже, недолго ждать времени, когда на Ruby можно будет сделать почти любое приложение рабочего стола. За дополнительной информацией обращайтесь на сайт [http://rubyforge.org RubyForge] (см. врезку «Ссылки»).|
 
Дополнительные модули можно загрузить через систему RubyGems, аналогичную CPAN для Perl. Разработаны модули для взаимодействия с базой данных MySQL, разработки приложений для Gnome и KDE и т.д. Похоже, недолго ждать времени, когда на Ruby можно будет сделать почти любое приложение рабочего стола. За дополнительной информацией обращайтесь на сайт [http://rubyforge.org RubyForge] (см. врезку «Ссылки»).|
 
Ширина=40%}}
 
Ширина=40%}}
Начинается код с команды '''require''', подключающей внешние библиотеки. В данном случае мы используем библиотеку '''socket''' это набор процедур, сильно упрощающий сетевое программирование (см. врезку «Модные модули» справа). Следующая строка создает объект сервера на локальном IP-адресе '''127.0.0.1''' и порте '''7125'''. Номер порта может быть любым, но для использования портов до тысячного (например, '''80''') потребуются права администратора системы.
+
Начинается код с команды '''require''', подключающей внешние библиотеки. В данном случае мы используем библиотеку '''socket''' — это набор процедур, сильно упрощающий сетевое программирование (см. врезку «Модные модули» справа). Следующая строка создает объект сервера на локальном IP-адресе '''127.0.0.1''' и порте '''7125'''. Номер порта может быть любым, но для использования портов до тысячного (например, '''80''') потребуются права администратора системы.
  
 
У нас получился сервер локальной сети; а мы хотим, чтоб с ним могли работать web-браузеры. Цикл '''while''' обрабатывает запросы к серверу, пока в окне терминала не нажать клавиши '''Ctrl+C'''. Внутри этого цикла сервер принимает запрос клиента и посылает браузеру стандартный ответ из двух строк: сообщение, что запрос принят, и HTML-заголовок. Символы '''\r''' и '''\n''' означают «возврат каретки» и «перевод строки» соответственно.
 
У нас получился сервер локальной сети; а мы хотим, чтоб с ним могли работать web-браузеры. Цикл '''while''' обрабатывает запросы к серверу, пока в окне терминала не нажать клавиши '''Ctrl+C'''. Внутри этого цикла сервер принимает запрос клиента и посылает браузеру стандартный ответ из двух строк: сообщение, что запрос принят, и HTML-заголовок. Символы '''\r''' и '''\n''' означают «возврат каретки» и «перевод строки» соответственно.
  
Затем обрабатывается запрос, полученный от браузера. Обычно он выглядит примерно так: '''GET /filename.html HTTP/1.1'''. Нам нужно определить в нем имя запрошенного файла. Сохраним строку запроса в переменной '''request''' и извлечем оттуда имя файла методом '''gsub''': он отделит от строки части GET и HTTP/1.1 при помощи регулярных выражений. '''Gsub''' напоминает командную утилиту '''sed''' быстрый способ заместить или отделить части строковой переменной.
+
Затем обрабатывается запрос, полученный от браузера. Обычно он выглядит примерно так: '''GET /filename.html HTTP/1.1'''. Нам нужно определить в нем имя запрошенного файла. Сохраним строку запроса в переменной '''request''' и извлечем оттуда имя файла методом '''gsub''': он отделит от строки части GET и HTTP/1.1 при помощи регулярных выражений. '''Gsub''' напоминает командную утилиту '''sed''' — быстрый способ заместить или отделить части строковой переменной.
  
 
От полученного имени файла с помощью метода '''chomp''' отделяется последний символ перевода строки, после чего результат сохраняется в переменной '''filename'''.
 
От полученного имени файла с помощью метода '''chomp''' отделяется последний символ перевода строки, после чего результат сохраняется в переменной '''filename'''.
Строка 203: Строка 203:
  
 
=== Мысли напоследок ===
 
=== Мысли напоследок ===
Вот сервер и готов. Удивительно просто, правда? Конечно, пока он обрабатывает только HTML-файлы – но были бы кости, мясо нарастет. Главное, что это пример применения Ruby в реальной задаче, и по нему видно, что код получается чудесно-простой и легко читаемый.
+
Вот сервер и готов. Удивительно просто, правда? Конечно, пока он обрабатывает только HTML-файлы — но были бы кости, мясо нарастет. Главное, что это пример применения Ruby в реальной задаче, и по нему видно, что код получается чудесно-простой и легко читаемый.
  
В Ruby еще много чего можно исследовать, и так как Ruby on Rails продолжает набирать популярность, вы об этом языке, несомненно, еще услышите. Ясный и разумный синтаксис Ruby лучше всех прочих поможет разобраться с объектно-ориентированным программированием тем, кто привык к С или Basic. Внизу слева находится врезка «Ссылки», там вы найдете и учебники, и прочую информацию. А напишете нечто крутое – сообщите нам на форум http://www.linuxforum.ru. Как знать, может, вашей будущей программы не хватает на нашем DVD...
+
В Ruby еще много чего можно исследовать, и так как Ruby on Rails продолжает набирать популярность, вы об этом языке, несомненно, еще услышите. Ясный и разумный синтаксис Ruby лучше всех прочих поможет разобраться с объектно-ориентированным программированием тем, кто привык к С или Basic. Внизу слева находится врезка «Ссылки», там вы найдете и учебники, и прочую информацию. А напишете нечто крутое — сообщите нам на форум http://unixforum.org/. Как знать, может, вашей будущей программы не хватает на нашем DVD…

Текущая версия на 17:40, 1 марта 2010

Содержание

[править] Ruby без Rails

Вы слыхали о Ruby on Rails — а сейчас Майк Сондерс расскажет вам о его основе, Ruby, ярком примере современного языка высокого уровня…

Вот и еще одна статья из цикла об «экзотических» языках программирования. Язык Tcl, с которым мы познакомились месяц назад, очень подходит для разработки оконных приложений с графическим интерфейсом, а сейчас мы займемся Ruby, предназначенным для создания серверных и сетевых приложений. Заскучали? Напрасно. Сейчас объясним, почему.

Мы постараемся не погрязнуть в техноязе: на то есть подробнейшая документация. Вместо этого мы начнем с основ языка, затем напишем простенькое приложение, а в завершение — полноценный web-проект. Вы уже знакомы с азами программирования? Отлично! Читайте дальше, и вы поймете, что Ruby достоин вашего внимания. Многие из нас слышали о Ruby в контексте Ruby on Rails, современного программного каркаса [framework]. На его основе сейчас разрабатываются крупные сайты (например, Basecamp, Jobster или 43 Things), и он поставляется с новой версией OS X, Leopard. На ринг Ruby вышел совсем недавно, и тем удивительнее тот факт, что его разработка ведется с 1993 года!

Детище Юкихиро Мацумото [Yukihiro Matsumoto] увидело свет в 1995 году. Ключевой особенностью языка стал принцип освобождения программиста от черной работы. Зачем продираться через заковыристый синтаксис, если требуется сделать что-то простое?

Проработав более двух лет на C++ и найдя, что он все еще сталкивается с неприятными сюрпризами, Мацумото решил создать язык, максимально оправдывающий ожидания — чтобы в нем программы делали именно то, что интуитивно предполагалось, и отсутствовали тупиковые случаи. «Прежде всего надо думать о людях», провозгласил Юкихиро, «о том, как они мыслят о программе и как представляют себе действия машин. Люди — хозяева. А машины — работники».

С историей — все, теперь о кодировании: Ruby называют «мультипарадигменным» [multiparadigm] языком. Это жутковатое слово означает, что язык включает и объектно ориентированный подход, и процедуры с функциями. Ruby — интерпретирующий язык, и его синтаксис близок к Python и Perl, поэтому он осваивается без труда.

[править] Освоимся

Для начала нам понадобятся интерпретатор языка Ruby и интерактивный интерпретатор irb, поставляемые с большинством дистрибутивов. Последнюю версию этих программ вы найдете в разделе Разработка нашего DVD.

Вызовем интерпретатор, набрав irb в командной строке. На экране появится строка приглашения — можно с ходу вводить операторы языка. По традиции полагалось бы вывести «Hello world» — «Здравствуй, мир», но это старо как мир… Будем оригинальны:

puts "Goodbye moon!"

Вроде все ясно: команда puts просто выводит на экран текстовую строку. Но в Ruby абсолютно все, даже строковые константы, — это объекты. Может, оно и странно, зато позволяет делать штуки вроде

"BlaBlaBlaa".length

С виду чушь, а на выходе печатается 10 — вполне настоящая длина строки. Или, например,

"Mmm, donuts".index("d")

возвращает 5, позицию символа d в заданной строке. (Учтите, нумерация в Ruby начинается с нуля, а не с единицы.)

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

puts "Do you love Ruby yet?"
answer = gets
puts "You answered " + answer

На экран выводится вопрос, потом объявляется переменная answer, и в нее тут же записывается результат команды gets (ввод строки с клавиатуры). Наш ответ затем выводится на экран.

Заодно продемонстрирована операция над переменными: строки можно складывать (+) и даже умножать:

mystring = "Some" + "text"
puts mystring
anotherstring = "Wowzers" * 10
puts anotherstring

Сначала две строки объединяются, и результат выводится на экран. Затем строка anotherstring заполняется десятью копиями строки Wowzers, и результат также выводится на экран. Именно эффективные функции обработки текста обеспечили Ruby место под солнцем в мире разработчиков сайтов. Неплохо знать и метод chomp (вы могли встретить его в Perl): он убирает из строки последний символ, перевод строки (\n), который автоматически добавляется командой gets при вводе. Метод понадобится в тех случаях, когда нужно преобразовать введенную строку в число, то есть в «голые цифры»:

x = gets.chomp.to_i

Мы создали переменную x, ввели строку командой gets, откинули у нее символ перевода строки с помощью chomp и методом to_i преобразовали ее в числовое значение, которое затем присвоили x. Тип переменной x можно проверить:

x = gets.chomp.to_i
x.is_a?(Integer)
x.is_a?(String)

Это показывает, что x — число, а не строка. Но мы можем немедля использовать x и как строку, если надо — благодаря динамической типизации. [Вопросительный знак является допустимым символом и часто используется в Ruby в именах методов, которые «отвечают на вопрос», — прим. ред.]

[править] Условия, циклы и функции

Разобравшись с переменными и вводом/выводом строк, перейдем к управляющим конструкциям языка. Каждый из приведенных ниже примеров нужно предварительно сохранить в текстовом файле и запускать командой ruby <имя_файла>. Сохраните следующий пример в файле test.rb и запустите командой ruby test.rb — он иллюстрирует использование условного оператора if и кодовых блоков:

puts "How many kittens do you have?"
x = gets.chomp.to_i
if x > 0 # More than zero kittens
    puts "You have " + x.to_s + " kittens"
else
    puts "Aww, you have no kittens!"
end

Мы запрашиваем у пользователя строку, затем уже известным нам методом to_i преобразуем ее в число. Далее оператор условия if сравнивает введенное число с нулем. Если условие в операторе if истинно, число преобразуется в строку с помощью метода to_s, чтоб вписать его в сообщение, и сообщение выводится его на экран.

Если же пользователь ввел 0, выполняются команды, расположенные после else, то есть выводится другое сообщение. Блок кода завершается командой end. Между прочим, для лучшей читаемости текста мы применили отступы — можно их вводить клавишей табуляции, а можно и просто пробелами. Все как в других языках!

Справа от оператора if помещен комментарий (в языке Ruby они предваряются символом #).

С циклами тоже проблем нет:

10.times do
    puts "Ruby rocks"
end

Все ясно — десять раз выводится строка! Оператор while ничуть не сложнее:

x = 0
while x != 15
    puts "Please enter 15"
    x = gets.chomp.to_i
end

Этот код требует у пользователя ввода строки до тех пор, пока не получит число 15. Тогда он покидает блок while/end и продолжает выполнение кода (правда, в данном случае выполнять уже нечего).

Программирование на языке высокого уровня обязательно подразумевает модульность, так что займемся процедурами. Как мы уже говорили, Ruby — объектно-ориентированный (ОО) язык, аналогично C++, C# или Python. Но даже если вы знакомы только с обычным C, можете не бояться ОО-сложностей, по крайней мере, на начальном этапе. Рассмотрим использование функций:

def doubler(value)
    value = value * 2
    return value
end
puts "Enter a number"
x = gets.chomp.to_i
y = doubler(x)
puts y.to_s

Первая половина скрипта — описание функции, она не будет исполняться при запуске. Функция doubler умножает число value (аргумент функции) на два и возвращает результат. Из кода видно, как используется функция. (Обратите внимание, что функции должны быть объявлены до их использования, иначе Ruby выдаст ошибку.)


Выполнение программы начинается с команды puts: у пользователя запрашивают число, и оно передается в качестве параметра функции doubler. Результат, возвращаемый функцией, записывается в переменную y. Наконец, значение переменной y выводится на экран. Создание объектов в Ruby выходит за рамки данной статьи; хотите узнать больше — обратитесь на сайты, указанные во врезке «Ссылки» на этой странице.

[править] Работать чисто

Обработка исключительных ситуаций в Ruby блаженно проста, например:

puts "Divide 5 by what?"
x = gets.chomp.to_i
begin
    y = 10 / x
rescue ZeroDivisionError
    puts "Eeep, divide by zero!"
end
puts y.to_s

Мы берем у пользователя число, потом входим в блок begin/end с разделом rescue внутри. Если пользователь, допустим, введет 5, в переменную y записывается частное от деления 10 на 5 и результат выводится на экран.

А вдруг он введет ноль? Возникнет ошибка. В таких случаях происходит возврат в командную строку и вывод сообщения, над которым вы и будете ломать голову. Но мы не зря ввели обработчик исключения. Возникшая исключительная ситуация (деление на ноль) будет зафиксирована, и выполнится оператор puts внутри обработчика исключения, который выведет на экран сообщение об ошибке.

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

[править] Создаем web-сервер

Применим полученные знания и напишем собственный… web-сервер! Экстрим? Да нет, в Ruby это совсем несложно, благодаря библиотеке socket. Конечно, для Apache наш сервер конкурентом пока не станет, но зато продемонстрирует возможности Ruby. И вообще, зачем устанавливать и настраивать мощный сервер, если вам всего-то нужно хранить пару web-страничек для доступа к ним по локальной сети? Вы напишете собственный сервер на Ruby быстрее, чем произнесете «/etc/apache/httpd.conf»!

Сохраните следующий код в файле webserver.rb в вашем домашнем каталоге. (Если вам лень набирать, возьмите его из раздела Magazine/Ruby нашего DVD.) Затем создайте в этом же каталоге две HTML-странички: index.html и test.html, с произвольным содержимым, лишь бы выводилось в браузере.

require 'socket'
webserver = TCPServer.new('127.0.0.1', 7125)
while (session = webserver.accept)
    session.print "HTTP/1.1 200/OK\r\nContent-type:text/html\r\n\r\n"
    request = session.gets
    trimmedrequest = request.gsub(/GET\ \//, '').gsub(/\ HTTP.*/, '')
    filename = trimmedrequest.chomp
    if filename == ""
        filename = "index.html"
    end
    begin
        displayfile = File.open(filename, 'r')
        content = displayfile.read()
        session.print content
    rescue Errno::ENOENT
        session.print "File not found"
    end
    session.close
end

Запустите программу командой ruby webserver.rb и проверьте, как она работает. Для этого в адресной строке браузера введите http://127.0.0.1:7125. Если все нормально, вы должны увидеть содержимое странички index.html! Соответственно, набрав http://127.0.0.1:7125/test.html, вы увидите содержимое странички test.html. Код говорит сам за себя, но мы все равно разберем его подробно.


Начинается код с команды require, подключающей внешние библиотеки. В данном случае мы используем библиотеку socket — это набор процедур, сильно упрощающий сетевое программирование (см. врезку «Модные модули» справа). Следующая строка создает объект сервера на локальном IP-адресе 127.0.0.1 и порте 7125. Номер порта может быть любым, но для использования портов до тысячного (например, 80) потребуются права администратора системы.

У нас получился сервер локальной сети; а мы хотим, чтоб с ним могли работать web-браузеры. Цикл while обрабатывает запросы к серверу, пока в окне терминала не нажать клавиши Ctrl+C. Внутри этого цикла сервер принимает запрос клиента и посылает браузеру стандартный ответ из двух строк: сообщение, что запрос принят, и HTML-заголовок. Символы \r и \n означают «возврат каретки» и «перевод строки» соответственно.

Затем обрабатывается запрос, полученный от браузера. Обычно он выглядит примерно так: GET /filename.html HTTP/1.1. Нам нужно определить в нем имя запрошенного файла. Сохраним строку запроса в переменной request и извлечем оттуда имя файла методом gsub: он отделит от строки части GET и HTTP/1.1 при помощи регулярных выражений. Gsub напоминает командную утилиту sed — быстрый способ заместить или отделить части строковой переменной.

От полученного имени файла с помощью метода chomp отделяется последний символ перевода строки, после чего результат сохраняется в переменной filename.

Большинство web-серверов, если имя файла не указано, по умолчанию загружают index.html. Блок if так и делает: если строка с именем файла пуста, переменной filename присваивается index.html. Можно, конечно, использовать и другой файл.

После этого (внутри блока begin/end) мы открываем полученный файл на чтение и записываем в переменную content его содержимое, прочитанное с помощью функции read(). Содержимое файла отсылается браузеру, методом session.print. А вдруг такого файла не найдется? Тогда rescue отправит браузеру сообщение об ошибке.

[править] Мысли напоследок

Вот сервер и готов. Удивительно просто, правда? Конечно, пока он обрабатывает только HTML-файлы — но были бы кости, мясо нарастет. Главное, что это пример применения Ruby в реальной задаче, и по нему видно, что код получается чудесно-простой и легко читаемый.

В Ruby еще много чего можно исследовать, и так как Ruby on Rails продолжает набирать популярность, вы об этом языке, несомненно, еще услышите. Ясный и разумный синтаксис Ruby лучше всех прочих поможет разобраться с объектно-ориентированным программированием тем, кто привык к С или Basic. Внизу слева находится врезка «Ссылки», там вы найдете и учебники, и прочую информацию. А напишете нечто крутое — сообщите нам на форум http://unixforum.org/. Как знать, может, вашей будущей программы не хватает на нашем DVD…

Персональные инструменты
купить
подписаться
Яндекс.Метрика