Быстрый курс Ruby [Александр Неткачев] (fb2) читать онлайн


 [Настройки текста]  [Cбросить фильтры]
  [Оглавление]

Александр Неткачев БЫСТРЫЙ КУРС RUBY

«Конец моим страданиям и разочарованиям»

Из песенки Вини-Пуха.

Введение

Название Ruby уже неоднократно попадалось мне на глаза на различных сайтах. К сожалению, я до сегодняшнего дня не находил времени исследовать Ruby. Почему к сожалению? Потому что это действительно замечательный язык и я это только сейчас узнал, что и стало поводом написать этот курс.

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

Особенности Ruby

Язык Ruby был задуман японским программистом Yukihiro Matsumoto в 1993 году как результат синтеза всех лучших черт языков программирования с целью максимально упростить создание программ. Результат синтеза в идеях языка изложен в документации по Ruby. Ниже представлены наиболее важные из них:

● Это интерпретируемый язык. В простейшем случае это означает, что стадия компиляции для него отсутствует. Это сокращает время, необходимое для создания программы.

● В Ruby переменная может хранить любой объект — можно сказать, что Ruby безтиповый язык, как PHP или Perl.

● Определять переменные не нужно. Для задания области видимости переменной используются приставки. Например $myVar — это глобальная переменная, а myVar — локальная.

● Garbage Collector освобождает от управления памятью. Объекты, на которыре не существует ссылок, автоматически выгружаются из памяти.

● Примитивные типы отсутствуют — любое значение является объектом.

● Поддержка основных концепций ООП.

● Чрезвычайно гибкая система итераторов.

● Части кода представлены как объекты

● Поддержка регулярных выражений и сходные с Perl методы работы с ними.

● В Ruby нет разделения на Integer, Long, Byte. Для целочисленных типов есть только один тип, в рамках которого можно проводить вычисления с произвольным количеством разрядов.

● Механизмы перехвата исключений (как в Java).

Другие особенности, которые мне особо понравились:

● Поддержка потоков

● Все операторы возвращают значения, в том числе управляющие структуры (if, case)

● return в конце функции не обязателен, возвращается значение последнего оператора. Например:

● def myFunction(a, b)

● a + b

● end

● puts myFunction(1, 2)

напечатает 3.

● Условия and и or возвращают элемент, эквивалентный true или первый элемент Например:

● puts 5 or 10 > 5

● puts 10 or nil > 10

● puts nil or 7 > 7

● puts nil and 10 > nil

Внимание программистам на C и производных: пустая строка и ноль не расцениваются как false. false — это только nil (null).

Установка Ruby

Gentoo Linux

Если у вас Gentoo Linux, то Ruby уже, скорее всего, будет установлен. Если же нет, то это досадное недоразумение исправляется очень легко.

$ emerge ruby

Далее можно переходить к установке дополнительных модулей или к первым программам на Ruby.

Установка дополнительных пакетов

Для Ruby есть большое количество различных библиотек и расширений. Доступные в Gentoo Linux можно посмотреть с помощью

$ emerge -s ruby

Кстати, если вы регулярно обновляете Portage, то, возможно, mod_ruby можно уже установить через "emerge mod_ruby". В моей версии его статус еще Masked.

mod_ruby

modruby.net — сайт Apache модуля mod_ruby. Установка крайне проста:

$ tar -xzf mod_ruby-1.0.7.tar.gz

$ cd mod_ruby-1.0.7

$./configure.rb --with-apxs=/path/to/apxs

$ make

$ make install

Затем редактируем файл настроек apache (httpd.conf или apache.conf) и добавляем в него следующее:

# загрузка модуля mod_ruby

LoadModule ruby_module /usr/lib/apache/mod_ruby.so

AddModule mod_ruby.c

# Настройка обработчиков для файлов *.rbx

<IfModule mod_ruby.c>

RubyRequire apache/ruby-run


<Location /ruby>

SetHandler ruby-object

RubyHandler Apache::RubyRun.instance

Options +ExecCGI

</Location>


<Files *.rbx>

SetHandler ruby-object

RubyHandler Apache::RubyRun.instance

Options +ExecCGI

</Files>


</IfModule>

Примечание: это немного расходится с примером, указанным в документации, но именно так у меня получилось запустить Ruby скрипты.

Для тестирования создайте в директории public_html файл hello.rbx вида

puts "Hello!"

Обращаемся к нему по ссылке (у вас может быть другая ссылка) "http://localhost/~alex/hello.rbx". Если отработало, значит все получилось. Если нет, обращайтесь, поможем, чем сможем.

Установка книги "Programming Ruby: The Pragmatic Programmers' Guide"

Авторы: Dave Thomas и Andrew Hunt

$ emerge dev-ruby/programming-ruby

Примечание: новая редакция книги находится на сайте phrogz.net

MySQL расширение для Ruby

$ emerge dev-ruby/mysql-ruby

Windows

Для установки в Windows достаточно скачать один из вариантов Ruby с http://ftp.ruby-lang.org/pub/ruby/binaries/ (я выбрал mswin32/ruby-1.8.1-20040402-i386-mswin32.zip). Далее распаковать и проставить правильно пути к директориям. Можно также воспользоваться пакетом автоматической установки RubyInstaller

Определить правильность установки поможет команда

C: \>ruby --help

Инструментарий языка

Управляющие структуры

if в несколько строк

if 1 > b

#…

elsif a == 1

#…

else

#…

end

if в одну строку

if 1 > b then 1 else 2 end

case

case node.type

when node.DocumentNode then

#…

else

#…

end

Постусловие

a = 1 if a > 1

Циклы

i = 1

while i < 10

puts i += 1

end


i = 1

puts i += 1 while i < 10

Использование mini-callbacks для организации циклов

Callback — это общее название, которым обозначают механизм задание части кода, который выполняется вызываемым методом. В различных технологиях используются указатели на функции (C/C++), динамический вызов функций (PHP/Perl). В Ruby задание callback можно осуществлять с помощью блоков кода. Блок передается за методом в волнистых скобках или в виде do… end. В начале блока идет перечисление параметров, с которыми он вызывается. Например |i| обозначает, что блоку передается один параметр и внутри этого блока он присваивается переменной i.

10.times { puts "I will use Google before asking questions\n" }

1.upto(3) { |i| puts "Iteration #{i}\n" }

10.downto(1) {|i| puts i}

(1..10). each {|i| puts i}

0.step(100, 10) {|i| puts i}

['January 1', 'February 23', 'March 8'].each { |holiday| p holiday }

%w{this is a test}.each{|i| p i}

Регионы

Регион используется для организации проверок и циклов. Он определяется начальным и конечным значением.

Создать регион

0..1 # 0, 1

0…4 # 0, 1, 2, 3

'a'..'f' # 'a', 'b', 'c', 'd', 'e', 'f'

Перевести регион в массив

(0..4).to_a # Result: [0, 1, 2, 3, 4]

Определить, есть ли элемент в регионе

(0..9).include?(5) или (0..9) === 5

Минимальный элемент региона

(0..9).min

Максимальный элемент региона

(0..9).max

Строки

Задание строки

str = 'asdf #{10**5}' # без вычисления

str = "asdf #{10**5}" # с вычислением, str = 'asdf 100000'

Определить длину строки

"asdf".length

Нахождение подстроки в строке

"asdf".index("s")

Массив из строки по некоторому разделителю

"asdf g h jkl;".split(" ")

Массив значений из строки

"10 11 12".scan(/\d+/)

Замена подстроки в строке

'Ruby??'.sub(/\?/, '!') > Ruby!?

'Ruby??'.sub(/(\?)\?/, '\1!') > Ruby?!

'Ruby??'.gsub(/\?/, '!') > Ruby!!

Из строки в число

"10".to_i

Посторить несколько раз строку

'-=' * 10 # -=-=-=-=-=-=-=-=-=-=

Альтернативные способы задания строк

"asdf" = %Q/asdf/

'asdf' = %q/asdf/ (вместо / может использоваться любой символ, например ~ -> %q~asdf~)

str = <<END

Некоторый текст

END

Числа

Приятной особенностью Ruby является встроенная поддержка больших чисел в вычислениях. Благодаря чему можно легко оперировать большими целыми числами. Например, можно легко вычислить, сколько зерен должен был отдать правитель изобретателю шахмат (по легенде, изобретатель попросил правителя положить на первую клетку два зернышка, на вторую 22 и так до последней, на которой было 264 зерен):

s, t = 2, 0

(1..64). each { t += s *= 2}

puts t # Результат: 73786976294838206460

Некоторые интересные возможности:

-10.abs — модуль

0xAAFF — hex

0b10010 — binary

?z — код символа

?\C-a — код Ctrl+a (?a & 0x9f)

?\M-a — код Alt+a (?a | 0x80)

?\C-\M-a — код Ctrl+Alt+a

Float object соответствует системному double

Модификаторы переменных

без модификатора — видима в текущем блоке и в подблоках

$ — глобальная

@ — переменная класса

@@ — статическая переменная класса

Первая буква заглавная — константа или имя класса

Массивы

Нумерация массивов начинается с нулевого элемента. Отрицательный индекс — обратная нумерация. В отличие от PHP, массив — это последовательность из N элементов. Поэтому если a = [1, 2] и задается значение a[4] = 10, то в результате получаем массив [1, 2, nil, nil, 10].

Создать массив

a = []

a = Array.new

a = ["asdf", "g", "h", "jkl;"]

Новый массив из фразы

a = %w{Ruby is a best language}

a = "Ruby is a best language".split(" ")

Выбрать часть массива

a = [1, 2, 3, 4, 5]

a[2, 2] # [3, 4]

a[1..3] # [2, 3, 4]

a[1…3] # [2, 3]

Изменить массив

a = [1, 2, 3, 4, 5]

a[1,2] = [] # a = [1, 4, 5]

a[0,1] = 3 # a = [3, 4, 5]

a[0,1] = [1, 2, 3] # a = [1, 2, 3, 4, 5]

Полезные методы

a.length # длина массива

a.shift # "вынуть" (вернуть и удалить) первый элемент

a.pop # "вынуть" последний элемент

Хеши (ассоциативные массивы)

Создать хеш

h = {'hash' => '{}', 'array' => '[]'}

h['hash'] = "{'key' => 'value'}"

Найти элемент по условию

р.find { |item| item.name == 'hash' }

Регулярные выражения

Создать выражение

r = Regexp.new('/a(b)c/')

r = /a(b)c/

r = %r{a(b)c}

Применить выражение в условии

str = "Ruby is OOP language"

puts $1 if str =~ /(OOP)/

puts str unless str!~ /OOP/

Специальные переменные

$1..$9 — найденные группы

$& — текст, найденный по шаблону

$` — текст до шаблона

$' — текст после шаблона

Использование объекта вместо специальных переменных

m = /(a)(b)(c)/.match('abcdefg')

m[0] > $&

m[1] > $1

m.pre_match > $`

m.post_match > $'

Callbacks

yield

def doSomething

 yield

end

doSomething { puts "It is a something:-)" }


def doSomethingWithParams

 yield 1

end

doSomethingWithParams do

|i| puts "It is a something with #{i}:-)"

end

Определить, что методу передан callback

if block_given?

 yield

end

Блоки кода как объекты

def doSomething(&callback)

 callback.call

end

doSomething { print "This is a something" }


def doSomething(callback)

 callback.call

end

doSomething proc { print "This is a something" }

Разименовать блок кода для yield-применения

p = proc {|i| print i}

(1..10).each &p

Ввод/Вывод

puts — выводит строку

print — выводит строку без \n в конце

printf — аналогичен C printf

gets — помещает результат ввода строки данных в переменную $_ и возвращает строку

Методы

Значение по умолчанию для параметра

def myMethod(value = "Default")

Все или часть параметров поместить в массив

def myMethod(*args)

Во время вызова метода использовать разбиение массива на параметры

myMethod(*[1, 2])

Вызов метода с использованием именованых параметров

myMethod('param2' => 1, 'param1' => 2)

Классы

конструктор

def initialize

Создание объекта

MyClass.new

Клонирование объекта

myClass.dup

"Заморозка" (нельзя изменять не "разморозив") объекта

myClass.freeze

dump объекта

myClass.inspect

Cтроковый идентификатор объекта

myClass.to_s

Вызов аналогичного метода parent класса

super

Задание readonly свойств/аттрибутов

attr_reader: documentUri

Задание writeonly свойств

def documentUri=(documentUri)

 @documentUri = documentUri

end

Задание static переменной класса

@@users

Задание static метода класса

class Page

 def Page.addHit

  @@hit += 1

 end

end

Модификаторы области видимости

[public|protected|private]

def…

def…

или

private: myMethod1,myMethod2

Модификатор области видимости для унаследованного метода

private_class_method: new

Переопределение операций

class NodeList

 def +(newNode)

  #…

 end

end

Исключения

begin

 #…

rescue ExceptionClass

 #…

rescue ExceptionClass => e

 #…

ensure

 #…

end

аналогичен Java коду:

try {

//…

} catch (ExceptionClass) {

//…

} catch (ExceptionClass e) {

//…

} finaly {

//…

}

Получить Exception объект в секции rescure

$!

Вызывать исключение

raise

Повторно вызвать begin.. end блок

retry

Прерывание выполнения

catch (:exit) do

 1..10.each do |i|

  1..10.each do |j|

   throw: exit if a[i, j] = 0

  end

 end

end

Модули

Определить модуль

module MyFunctions

 def…

end

Добавить описания из модуля в класс

class MyClass

 include MyFunctions

end

Прочее

Взаимодействие с shell

`date`

Альясы операторов

class Fixnum

 alias oldPlus +

 def +(value)

  oldPlus(value)

  puts 'Plus called'

 end

end

Параллельное присвоение

a, b = b, a

Небольшой пример программы на Ruby

Написав этот мини курс я попробовал составить к нему оглавление. Примерно оценив количество заголовков я пришел к выводу, что вручную это будет очень непродуктивно — проще написать небольшую программу на Ruby, которая составляет оглавление из заголовков и заменяет строку CREATE_TOC на созданное оглавление

File: createToc.rb

#!/usr/bin/ruby — w


# createToc.rb

# Программа составляет оглавление, выводит его вместо CREATE_TOC

# и добавляет якоря вида <a name="sN"></a> к заголовкам


# задаем строковую переменную — идентификатор оглавления

tocToken = 'CREATE_TOC'


# определяем массив, в котором будет строиться оглавление

toc = []


# результат

output = ''


# для всех строк входного потока

ARGF.each do |line|


 # если строка содержит заголовок 3го, 4го или 5го уровня

 if line =~ %r{<h([3–5])>([^<]+)</h[3–5]>}


  # определить номер якоря

  anchorId = toc.length.to_s


  # и добавить в массив toc пункт оглавления

  toc << (' ' * ($1.to_i - 3) * 2) + "<a href=\"#a#{anchorId}\">#{$2}</a><br>\n"


  # к строке output добавить заголовок с добавленым якорем

  output << line.sub('>', "><a name=\"a#{anchorId}\"></a>")

 else

  output << line

 end

end


# выводим результат, в котором tocToken заменяется на оглавление

puts output.sub(tocToken, '<div class="TOC">' + toc.join + '</div>')

К сожалению, эта программа не учитывает, что оглавление и якоря могут уже быть добавлены. Если добавите такую возможность к программе, присылайте патч.

Использование программы:

$ createToc.rb < article.html > new_article.html

Продолжение следует…

В продолжении планируется:

● Ruby и XML (готово)

● многопоточность Ruby

● сравнение скорости программ на Ruby и PHP

● Ruby и MySQL

Статья взята с сайта OpenNet.

10.05.2004

Оглавление

  • Введение
  • Особенности Ruby
  • Установка Ruby
  •   Gentoo Linux
  •     Установка дополнительных пакетов
  •   Windows
  • Инструментарий языка
  •   Управляющие структуры
  •     if в несколько строк
  •     if в одну строку
  •     case
  •     Постусловие
  •     Циклы
  •     Использование mini-callbacks для организации циклов
  •   Регионы
  •     Создать регион
  •     Перевести регион в массив
  •     Определить, есть ли элемент в регионе
  •     Минимальный элемент региона
  •     Максимальный элемент региона
  •   Строки
  •     Задание строки
  •     Определить длину строки
  •     Нахождение подстроки в строке
  •     Массив из строки по некоторому разделителю
  •     Массив значений из строки
  •     Замена подстроки в строке
  •     Из строки в число
  •     Посторить несколько раз строку
  •     Альтернативные способы задания строк
  •   Числа
  •   Модификаторы переменных
  •   Массивы
  •     Создать массив
  •     Новый массив из фразы
  •     Выбрать часть массива
  •     Изменить массив
  •     Полезные методы
  •   Хеши (ассоциативные массивы)
  •     Создать хеш
  •     Найти элемент по условию
  •   Регулярные выражения
  •     Создать выражение
  •     Применить выражение в условии
  •     Специальные переменные
  •     Использование объекта вместо специальных переменных
  •   Callbacks
  •     yield
  •     Определить, что методу передан callback
  •     Блоки кода как объекты
  •     Разименовать блок кода для yield-применения
  •   Ввод/Вывод
  •   Методы
  •     Значение по умолчанию для параметра
  •     Все или часть параметров поместить в массив
  •     Во время вызова метода использовать разбиение массива на параметры
  •     Вызов метода с использованием именованых параметров
  •   Классы
  •     Создание объекта
  •     Клонирование объекта
  •     "Заморозка" (нельзя изменять не "разморозив") объекта
  •     dump объекта
  •     Cтроковый идентификатор объекта
  •     Вызов аналогичного метода parent класса
  •     Задание readonly свойств/аттрибутов
  •     Задание writeonly свойств
  •     Задание static переменной класса
  •     Задание static метода класса
  •     Модификаторы области видимости
  •     Модификатор области видимости для унаследованного метода
  •     Переопределение операций
  •   Исключения
  •     Получить Exception объект в секции rescure
  •     Вызывать исключение
  •     Повторно вызвать begin.. end блок
  •     Прерывание выполнения
  •   Модули
  •     Определить модуль
  •     Добавить описания из модуля в класс
  •   Прочее
  •     Взаимодействие с shell
  •     Альясы операторов
  •     Параллельное присвоение
  • Небольшой пример программы на Ruby
  • Продолжение следует…