Наверное каждый в начале работы с ROR был впечатлен возможностью Scaffolding'а, который позволяет одной командой создавать migrations, controllers, models и views.
Но что делать если в своем проекте вы используете не стандартные Rails утилиты: erb, Test::Unit, fixturies, а сторонние инструменты: Haml, Rspec, Cucumber, Factory Girl и более того, хотите добавить собственные шаблоны?
Интересно? GOTO next line.
Исходные данные:
Ruby on Rails; Rspec; will-paginate; Haml; Factory-girl
Задача:
% rails generate scaffold post post:string
Генерирует:
- contoller's с поддержкой will_paginate, русскоязычными сообщениями
- model's с поддержкой will_paginate
- view's с заданным нами содержимым и в формате haml
- Rspec тесты, вместо Test::Unit
- Factory Girl factories вместо стандартных fixtures
Для начала коротко о Scaffold. Scaffold — это встроенный генератор, сам по себе он ничего не генерирует, но запускает другие генераторы.
Текущие настройки scaffold можно проверить с помощью:
% rails g scaffold --help
Генераторы настраиваются с помощью файла RAILS_ROOT/config/application.rb, внутри которого можно задавать параметры с помощью такой конструкции:
config.generators do |g|
# настройки генераторов
end
CUSTOM CONTROLLERS
Начнём с того, что заменим стандартный шаблон контроллеров на свой.
Необходимо скопировать шаблон из гема используемого в проекте в сам проект.
Путь до гемов вашего проекта можно узнать таким способом:
RAILS_ROOT% rails console
puts $LOAD_PATH
...
...
... тут следует список всех гемов с полными путями
Скопируем шаблон controller.rb из GEMS_PATH/railties[version]/lib/rails/generators/rails/scaffold_controller/templates в RAILS_ROOT/lib/templates/rails/scaffold_controller/controller.rb
#Вот так выглядит исходный шаблон контроллера controller.rb
class <%= controller_class_name %>Controller < ApplicationController
# GET <%= route_url %>
# GET <%= route_url %>.xml
def index
@<%= plural_table_name %> = <%= orm_class.all(class_name) %>
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @<%= plural_table_name %> }
end
end
...
Немного кастомиризуем его, добавив поддержку русского языка, паджинацию и обрезав лишний текст
# encoding: UTF-8
class <%= controller_class_name %>Controller < ApplicationController
# GET <%= route_url %>
def index
@<%= plural_table_name %> = <%= class_name %>.paginate :page => params[:page], :order => 'id DESC'
end
...
После работы scaffold мы получим такой миловидный код
# encoding: UTF-8
class PostsController < ApplicationController
# GET /posts
def index
@posts = Post.paginate :page => params[:page], :order => 'id DESC'
end
...
CUSTOM MODELS
Скопируем файл шаблона model.rb с GEMS_PATH/activerecord[version]/lib/rails/generators/active_record/model/templates в RAILS_ROOT/lib/templates/active_record/model/model.rb
#Исходный код шаблона model.rb
class <%= class_name %> < <%= parent_class_name.classify %>
<% attributes.select {|attr| attr.reference? }.each do |attribute| -%>
belongs_to :<%= attribute.name %>
<% end -%>
end
Добавим поддержку русского языка и 2 параметра для will_paginate
# encoding: UTF-8
class <%= class_name %> < <%= parent_class_name.classify %>
cattr_reader :per_page
@@per_page = 20
<% attributes.select {|attr| attr.reference? }.each do |attribute| -%>
belongs_to :<%= attribute.name %>
<% end -%>
end
На выходе получаем:
# encoding: UTF-8
class Post < ActiveRecord::Base
cattr_reader :per_page
@@per_page = 20
end
CUSTOM VIEWS
В нашем примере мы используем HAML вместо .erb. Как заставить Rails генерировать не erb, a haml view's?
Очень просто, достаточно установить gem «haml-rails».
Дописываем в Gemfile
gem 'haml-rails'
И запускаем bundle install
Готово! Теперь рельсогенератор делает file_name.html.haml файлы для нас
Перейдём к нашим шаблонам. Скопируем 5 файлов (edit.html.haml, _form.html.haml, index.html.haml, new.html.haml, show.html.haml) из GEMS_PATH/haml-rails[version]/lib/generators/haml/scaffold/templates в уже полюбившуюся нам RAILS_ROOT/lib/templates/haml/scaffold
Не буду приводить здесь кода, его можно посмотреть по ссылкам ниже
Исходные шаблоны — haml-rails
Шаблон после редактирования — ссылка
Результат — ссылка
RSPEC
Как и в случае с haml, для замены стандартных тестов RSpec'овскими достаточно установить gem «rspec-rails».
По умолчанию scaffold будет создавать rspec файлы для тестирования моделей, контроллеров, хелперов, вьюх, роутинга и запросов.
Наверняка вам как и мне не нужно столько rspec файлов, к счастью ROR позволяет нам настроить этот пункт.
#RAILS_ROOT/config/application.rb
config.generators do |g|
#Здесь я отключил генерацию rspec файлов для вьюх, хелперов, роутинга и запросов
#т.о. оставив лишь генерацию spec's для моделей и контроллеров
g.test_framework :rspec, :view_specs => false, :helper_specs => false,
:routing_specs => false, :request_specs => false
end
FACTORY GIRL
Для добавления scaffolding для FG, установим gem «rails3-generators»
И добавим в конфиг следующую строчку
#RAILS_ROOT/config/application.rb
config.generators do |g|
g.test_framework :rspec, :view_specs => false, :helper_specs => false,
:routing_specs => false, :request_specs => false
g.fixture_replacement :factory_girl, :dir => "spec/factories"
end
Помимо factory_girls гем «rails3-generators» добавляет генераторы для DataMapper, Authlogic, Mongomapper, Shoulda, Formtastic и SimpleForm
Что же у нас получилось?
% rails g scaffold final final:string
invoke active_record create db/migrate/20110713193843_create_finals.rb create app/models/final.rb invoke rspec create spec/models/final_spec.rb invoke factory_girl create spec/factories/finals.rb route resources :finals invoke scaffold_controller create app/controllers/finals_controller.rb invoke haml create app/views/finals create app/views/finals/index.html.haml create app/views/finals/edit.html.haml create app/views/finals/show.html.haml create app/views/finals/new.html.haml create app/views/finals/_form.html.haml invoke rspec create spec/controllers/finals_controller_spec.rb invoke helper invoke rspec invoke helper create app/helpers/finals_helper.rb invoke rspec invoke stylesheets identical public/stylesheets/scaffold.css
Собственные шаблоны для MVC; haml view's; factory_girl factories; RSpec's для моделей и контроллеров; встроенная паджинация.
Всё как мы хотели. Наслаждайтесь))
Посмотреть полный код
Github
Почитать
Generators manual
Paul's Barry Article: Customizing generators in rails 3
Rspec generators detail
Подкаст про генераторы
rails3-generators gem
haml-rails gem