Шаблоны приложения Rails

Шаблоны приложений - это простые Ruby файлы, содержащие DSL для добавления гемов, инициализаторов и т.п. в ваш только что созданный или существующий Rails проект.

После прочтения данного руководства, вы узнаете:

  • Как использовать шаблоны для создания/настройки Rails приложений.
  • Как написать свои собственные шаблоны, которые можно будет использовать повторно, используя Rails API для шаблонов.

1. Использование

Чтобы применить шаблон, вам необходимо запустить генератор Rails с расположением шаблона, который вы хотите применить, используя опцию -m. Это может быть путь к файлу или URL.

$ rails new blog -m ~/template.rb
$ rails new blog -m http://example.com/template.rb

Вы можете использовать команду rails app:template чтобы применить шаблоны к существующему Rails приложению. Место расположения шаблона должно быть передано с помощью переменной среды LOCATION. Опять же, это может быть путь к файлу или URL.

$ bin/rails app:template LOCATION=~/template.rb
$ bin/rails app:template LOCATION=http://example.com/template.rb

2. API для шаблонов

Rails API для шаблонов легок для понимания. Ниже пример типичного шаблона Rails:

# template.rb
generate(:scaffold, "person name:string")
route "root to: 'people#index'"
rails_command("db:migrate")

after_bundle do
  git :init
  git add: "."
  git commit: %Q{ -m 'Initial commit' }
end

В следующих разделах рассматриваются основные методы, предоставленные API:

2.1. gem(*args)

Добавляет запись gem для предоставляемого гема в генерируемый для приложения Gemfile.

Например, если ваше приложение зависит от гемов bj и nokogiri:

gem "bj"
gem "nokogiri"

Пожалуйста, отметьте, что это не установит гемы и вы должны будете запустить bundle install для этого.

$ bundle install

2.2. gem_group(*names, &block)

Оборачивает записи гемов внутрь группы.

Например, если вы хотите загружать rspec-rails только в группах development и test:

gem_group :development, :test do
  gem "rspec-rails"
end

2.3. add_source(source, options={}, &block)

Добавляет переданный источник в генерируемый для приложения Gemfile.

Например, если вам необходим источник гема "http://gems.github.com":

add_source "http://gems.github.com"

Если передан блок, то записи гемов в блоке будут обернуты в группу с источником.

add_source "http://gems.github.com/" do
  gem "rspec-rails"
end

2.4. environment/application(data=nil, options={}, &block)

Добавляет строчку внутрь класса Application в config/application.rb.

Если указана options[:env], строчка добавляется в соответствующий файл в config/environments.

environment 'config.action_mailer.default_url_options = {host: "http://yourwebsite.example.com"}', env: 'production'

Блок может использоваться вместо аргумента data.

2.5. vendor/lib/file/initializer(filename, data = nil, &block)

Добавляет инициализатор в папку config/initializers генерируемого приложения.

Допустим, вам нравится использовать Object#not_nil? и Object#not_blank?:

initializer 'bloatlol.rb', <<-CODE
  class Object
    def not_nil?
      !nil?
    end

    def not_blank?
      !blank?
    end
  end
CODE

Аналогично, lib() создает файл в папке lib/, и vendor() создает файл в папке vendor/.

Есть даже file(), который принимает относительный путь от Rails.root и создает все необходимые папки/файлы:

file 'app/components/foo.rb', <<-CODE
  class Foo
  end
CODE

Это создаст папку app/components и поместит в нее foo.rb.

2.6. rakefile(filename, data = nil, &block)

Создает новый rake файл в lib/tasks с предоставленной задачей:

rakefile("bootstrap.rake") do
  <<-TASK
    namespace :boot do
      task :strap do
        puts "i like boots!"
      end
    end
  TASK
end

Код выше создаст lib/tasks/bootstrap.rake с rake задачей boot:strap.

2.7. generate(what, *args)

Запускает предоставленный генератор rails с переданными аргументами.

generate(:scaffold, "person", "name:string", "address:text", "age:number")

2.8. run(command)

Выполняет произвольную команду, как открывающая кавычка. Допустим, вы хотите удалить файл README.rdoc:

run "rm README.rdoc"

2.9. rails_command(command, options = {})

Запускает предоставленную команду в Rails приложении. Допустим, вы хотите запустить миграции базы данных:

rails_command "db:migrate"

Вы также можете запустить команды с разными Rails окружениями:

rails_command "db:migrate", env: 'production'

Вы также можете запустить команды как супер-пользователь:

rails_command "log:clear", sudo: true

Также можно запустить команды, которые должны прервать генерацию приложения в случае неудачи:

rails_command "db:migrate", abort_on_failure: true

2.10. route(routing_code)

Добавляет запись маршрутизации в файл config/routes.rb. В шагах выше мы сгенерировали скаффолд для person и также удалили README.rdoc. Сейчас, сделаем для приложения PeopleController#index страницей по умолчанию:

route "root to: 'person#index'"

2.11. inside(dir)

Позволяет вам запускать команды из данного каталога. Например, если у вас есть копия крайних rails, и вы хотите сделать ссылку из вашего нового приложения, вы можете сделать:

inside('vendor') do
  run "ln -s ~/commit-rails/rails rails"
end

2.12. ask(question)

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

lib_name = ask("What do you want to call the shiny library ?")
lib_name << ".rb" unless lib_name.index(".rb")

lib lib_name, <<-CODE
  class Shiny
  end
CODE

2.13. yes?(question) or no?(question)

Эти методы позволяют вам задать вопросы из ваших шаблонов и принять решение в процессе в зависимости от ответа пользователя. Допустим, вы хотите спросить пользователя, запускать ли миграции:

rails_command("db:migrate") if yes?("Run database migrations?")
# no?(question) работает наоборот.

2.14. git(:command)

Шаблоны Rails позволяют вам запускать любую команду git:

git :init
git add: "."
git commit: "-a -m 'Initial commit'"

2.15. after_bundle(&block)

Регистрирует колбэк, который будет выполняться после того, как гемы были упакованы и бинстабы сгенерированы. Полезно для добавления генерируемых файлов в систему контроля версий:

after_bundle do
  git :init
  git add: '.'
  git commit: "-a -m 'Initial commit'"
end

Колбэки выполняется, даже если был передан --skip-bundle.

3. Продвинутое использование

Шаблон приложения вычисляется в контексте экземпляра Rails::Generators::AppGenerator. Используется экшн apply, предоставленный Thor.

Это означает, что вы можете расширить и изменить экземпляр в соответствии с вашими потребностями.

Например, переписать метод source_paths, чтобы он содержал место расположения шаблона. Сейчас методы, такие как copy_file, будут принимать относительные пути по отношению к месту расположения шаблону.

def source_paths
  [__dir__]
end