Пользователь
0,0
рейтинг
6 января 2011 в 17:16

Rake Tutorial из песочницы

Rake — инструмент для автоматизации сборки программного кода, написаный на Ruby, подобен таким инструментам как make, Ant или Phing. Хотя между ними существует огромная разница. В отличие от других инструментов, Rake не обеспечивает внешний DSL (например, XML-файл сборки в Ant). Вместо этого, все задачи описываются на чистом Ruby. Таким образом вы получаете полную гибкость и можете пользоваться полезными фичами Ruby.

Что такое инструменты сборки?

Если вы когда-либо пробовали инсталлировать программное обеспечение из исходных кодов в системе Linux или Unix, существует высокая вероятность, что вам приходилось иметь дело с make. Процесс установки обычно выглядит одинаково. Сперва вы переходите в директорию с уже распаковаными исходными кодами, затем вводите следующие команды:

./configure
make
make install


Вторая и третья линии — просто вызов программы make. В первую очередь при запуске make ищет файл Makefile. В нем содержится информация о исходниках и зависимостях между ними. make сортирует топологические зависимости и пытается решить их в надлежащем порядке. Это выглядит следующим образом: сначала разработчик указывает зависимости, а инструмент сборки отвечает за их обработку. make также позволяет сэкономить время. Если исходный код не изменился с последней компиляции, он не будет обработано снова, поскольку это будет чистой потерей времени. Инструменты сборки могут быть использованы не только для компиляции кода, хотя это и есть их основная задача. В общем, инструменты сборки используются для автоматизации утомительных и повторяющихся задач.

Отличия между Rake и остальными инструментами сборки.

Как я уже говорил, есть одно существенное различие между Rake и другими инструментами для сборки. Вместо того чтобы писать Makefile для make и build.xml для Ant и Phing, вы просто пишете код на Ruby. Вам не прийдется осваивать синтаксис новых инструментов сборки, если решите заменить один инструмент на другой.
Но теории недостаточно, давайте перейдем к практике.

Установка Rake

Установка rake достаточно легка, при условии, что у вас на компьюторе присудствуют Ruby gems. Для установки rake, введите следующие команды:

gem install rake


В большинстве случаев вам могут понадобиться права администратора, поэтому либо перейдите аод администратора, либо используйте приставку sudo.

sudo gem install rake


После того как rake gem установлен, мы можем написать наш первый пример.

Первый пример Rake

Наипростейший путь определить задачу Rake — написать следующий код на Ruby:

task :default do
puts "Hello World!"
end


Rake задачи должны всегда находиться в файле с именем Rakefile, Rakefile, rakefile.rb или Rakefile.rb. Первые две формы используются чаще всего. После того как Rakefile сохранен, нужно перейти в папку с этим файлом и выполнить следующую команду:

$ rake
(in /home/lukasz/ruby/rake_examples)
Hello World!


Первая rake задача работает отлично.

Итак, что же произошло на самом деле? Получая наш Rakefile, Rake ищет в нем задачи, которые являются просто вызовами метода task. В одном Rakefile может быть много задач. При запуске файла вы можете передать имя задачи, которую хотите выполнить. Если же задача не передается, rake ищет default задачу. Вот почему наш Rake вызов сделал свою работу без запросов каких-либо дополнительных параметров.

Давайте попробуем добавить много задач в один Rakefile:

task :ring do
puts "Bell is ringing."
end

task :enter do
puts "Entering home!"
end


Если мы попробуем запустить команду rake без каких-либо параметров, то получим ошибку:

$ rake
(in /home/lukasz/ruby/rake_examples)
rake aborted!
Don't know how to build task 'default'

(See full trace by running task with --trace)


В этом файле не указано задание по умолчанию, поэтому мы должны явно передать им имя задачи:

$ rake enter
(in /home/lukasz/rake_examples)
Entering home!
$ rake ring
(in /home/lukasz/rake_examples)
Bell is ringing.


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

Добавление зависимостей

Давайте немного модифицируем наш файл:

task :ring do
puts "Bell is ringing."
end

task :enter => :ring do
puts "Entering home!"
end


Теперь, когда вы захотите зайти в дом, сначала произойдет звонок в дверь:

$ rake enter
(in /home/lukasz/ruby/rake_examples)
Bell is ringing.
Entering home!


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

Хорошей новостью является то, что зависимость может быть указана не только при определении задачи, но и позже, в зависимости от выполнения условий времени. В конце концов, мы пишем задачи в языке программирования Ruby, а не статический файл XML, помните?

Для достижения того же эффекта со звонком в дверь, мы можем написать:

task :ring do
puts "Bell is ringing."
end

task :enter do
puts "Entering home!"
end

task :enter => :ring


И эффект будет таким же.

Описание задачи.

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

desc 'Ring the bell'
task :ring do
puts "Bell is ringing."
end

desc 'Enter home'
task :enter => :ring do
puts "Entering home!"
end


Чтобы увидеть список доступных задач, запустите rake с параметром -Т или --tasks:

$ rake -T
(in /home/lukasz/ruby/rake_examples)
rake enter # Enter home
rake ring # Ring the bell


Как я уже сказал, инструменты сборки были сделаны с целью упрощения компиляции проекта. Есть много
зависимостей между отдельными файлами и Rake, так же как и многие инструменты сборки, поддерживает это. Это позволяет определить особый тип задач -a file task:

file 'products.sql' => 'products.xml' do
# build SQL INSERT clause and save it in products.sql file,
# basing on products.xml datafile
end


Файл задача — в общем — не отличается от регулярных задач. Дело в том, что он не будет работать, если входной файл (products.xml в данном случае) не существует. Он также не будет работать, если файл-результат (products.sql) не старше входного файла. Если вам не подходит данное поведение, тоесть вам нужно перезаписывать выходной файл каждый раз при запуске задачи, используйте регулярные задачи.

FileUtils


Rake включает в себя модуль Fileutil, который обеспечивает множество Unix-подобных методов, включая mkdir, rmdir, cp, chmod и touch.
Поскольку модуль Fileutils уже включен, вы можете вызывать эти методы непосредственно, без использования рамок операторов.

task :manipulate_files do
mkdir 'new_dir'
mv 'new_dir', 'lukasz'
chmod 0777, 'lukasz'
touch 'lukasz/wrobel.txt'
rm_rf 'lukasz'
end


Если вы знакомы с командной оболочкой Linux / Unix вы освоите этот модуль в очень краткие сроки.
Кстати, помните поводение файлов-задач? Если выходной файл не старше входного файла, файл задача не будет работать. В случае, если вы хотите выполнить такую проверку в регулярных задачах, вы можете использовать метод Fileutils, который называется uptodate.

task :check do
# ...

unless uptodate?(output_file, input_file)
# regenerate output_file
end
end


FileList

Представьте себе файл задачи, где объединены много входных файлов, чтобы получить один выходной файл. Наиболее очевидным способом определения зависимостей между файлами будет:

one_file_to_rule_them_all = 'database.sql'
tables_sql = ['orders.sql', 'payments.sql', 'categories.sql']

file one_file_to_rule_them_all => tables_sql


Это будет работать, но что если мы создадим еще один входной SQL файл? Мы должны помнить о том, что его нужно добавить в наш список.

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

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

one_file_to_rule_them_all = 'database.sql'

FileList['*.sql'].each {|table| file one_file_to_rule_them_all => table}


Забудьте о добавлении каждого отдельного SQL файла в список. Rake сделает это за вас.

Аннотация

Существует огромное количество функций Rake, которые небыли охвачены в данном пояснении, например clean, clobber, rdoc и gem tasks, pathmap, rules и namespaces. У вас будет шанс узнать о них позже.
Я надеюсь что эта статья станет хорошей отправной точкой, чтобы получить представление о Rake. Rake доказал свою ценность и в настоящее время он широко используется в мире Ruby, так что написание Rake задач является обязательным навыком. Удачи в ваших собственных экспериментах с Rake.

P.S. Оригинал статьи можно прочитать тут.
Igor Duzhik @Lass_ua
карма
2,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое

Комментарии (4)

  • 0
    Rake мощный и приятный инструмент.
    Jim Weirich, tnx!
    • +3
      … У которого есть еще более приятный аналог — Thor.
      Yehuda Katz, tnx!

      =)
  • 0
    Я бы еще добавил как вызвать одну задачу из другой: Rake::Task['task_name'].execute
  • –3
    — «Вам не прийдется осваивать синтаксис новых инструментов сборки»

    Вам придётся освоить орфографию языка наполнения контента Хабра.

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