Как известно, в Rails 3 можно использовать новый стиль кодирования, основанный на применении респондеров (Responders). То есть, форматы ответов задаются при помощи ключевого слова respond_to, а в экшенах используется respond_with.
Однако, нисмотря на то, что в таком стиле вы можете писать свои контроллеры уже сейчас, rails-генераторы (scaffold, controller и resource) все еще генерируют контроллеры на основе старого шаблона, в котором используется старый стиль кодирования. Раньше мне приходилось вручную переводить вновь сгенерированные контроллеры в новый стиль, пока я не переопределил стандартный шаблон контроллера.
В Rails 3 теперь можно удобно переопределить стандартный шаблон генератора контроллеров. Самый простой способ, это просто положить готовый шаблон (он приведен в конце статьи) в файл:
yourapp/lib/templates/rails/scaffold_controller/controller.rb
В этом случае, шаблон будет автоматически “подхватываться” при генерировании контроллера.
Второй способ может понадобиться, если нужно переопределить шаблон из гема или плагина. Для этого нужно сначала прописать в файле lib/yourgemname.rb вашего гема следующее:
require 'rails/all'
module Yourgemname
class Railtie < ::Rails::Railtie
config.generators.scaffold_controller = :yourgemname_controller
end
end
Этим мы указываем, что генератор контроллеров должен использовать наш генератор. Файл генератора должен располагаться по пути lib/generators/rails/yourgemname_controller_generator.rb Теперь давайте посмотрим, как выглядит наш собственный генератор:
require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator'
module Rails
module Generators
class YourgemnameControllerGenerator < ScaffoldControllerGenerator
source_root File.expand_path("../templates", __FILE__)
end
end
end
Здесь все просто - мы наследуемся от базового класса генератора и указываем новый путь к шаблонам. Шаблон должен располагаться по пути lib/generators/rails/templates/controller.rb. Теперь посмотрим, как выглядит сам шаблон в стиле Rails 3:
class <%= controller_class_name %>Controller < ApplicationController
<% unless options[:singleton] -%>
# GET /<%= table_name %>
# GET /<%= table_name %>.xml
def index
@<%= table_name %> = <%= orm_class.all(class_name) %>
respond_with(@<%= table_name %>)
end
<% end -%>
# GET /<%= table_name %>/1
# GET /<%= table_name %>/1.xml
def show
@<%= file_name %> = <%= orm_class.find(class_name, "params[:id]") %>
respond_with(@<%= file_name %>)
end
# GET /<%= table_name %>/new
# GET /<%= table_name %>/new.xml
def new
@<%= file_name %> = <%= orm_class.build(class_name) %>
respond_with(@<%= file_name %>)
end
# GET /<%= table_name %>/1/edit
def edit
@<%= file_name %> = <%= orm_class.find(class_name, "params[:id]") %>
end
# POST /<%= table_name %>
# POST /<%= table_name %>.xml
def create
@<%= file_name %> = <%= orm_class.build(class_name, "params[:#{file_name}]") %>
flash[:notice] = '<%= class_name %> was successfully created.' if @<%= orm_instance.save %>
respond_with(@<%= file_name %>)
end
# PUT /<%= table_name %>/1
# PUT /<%= table_name %>/1.xml
def update
@<%= file_name %> = <%= orm_class.find(class_name, "params[:id]") %>
flash[:notice] = '<%= class_name %> was successfully updated.' if @<%= orm_instance.update_attributes("params[:#{file_name}]") %>
respond_with(@<%= file_name %>)
end
# DELETE /<%= table_name %>/1
# DELETE /<%= table_name %>/1.xml
def destroy
@<%= file_name %> = <%= orm_class.find(class_name, "params[:id]") %>
@<%= orm_instance.destroy %>
respond_with(@<%= file_name %>)
end
end
Вот и все. Теперь при генерировании нового контроллера будет использоваться наш шаблон.
P.S: Хочу предупредить, что в Rails 3.1 (которая edge на момент написания статьи) это не будет работать в некоторых случаях, так как в этой версии есть небольшие изменения в шаблоне, а в приведенном мною шаблоне они не учитываются.