Estou trabalhando numa nova aplicação em Rails, ela é dividida em área administrativa e uma área vísivel a todos os visitantes da aplicação.
Inicialmente eu comecei com os controladores admin_controller.erb, home_controller.erb e o controlador padrão application_controller.erb, que é herdado pelos dois primeiros controladores.
application_controller.erb
1 2 3 4 5 6 7 8 9 10 | # Filters added to this controller apply to all controllers in the application. # Likewise, all the methods added will be available for all controllers. class ApplicationController < ActionController::Base helper :all # include all helpers, all the time protect_from_forgery # See ActionController::RequestForgeryProtection for details # Scrub sensitive parameters from your log # filter_parameter_logging :password end |
admin_controller.erb
1 2 3 4 5 6 | class AdminController < ApplicationController def index end end |
home_controller.erb
1 2 3 4 5 6 | class HomeController < ApplicationController def index end end |
Mas eu quero deixar a minha aplicação mais simples e inteligente, a minha área administrativa vai ser grande, bem como o meu frontend.
Vão existir uma série de filtros e helpers que vão ser usados em comum por todos os diversos controladores da área administrativa e do frontend, do jeito que está hoje eu teria que colocar muito código no application_controller.erb, bem como no helper padrão application_helper.erb.
Desta forma eu decidi criar dois novos controladores backend_controller.erb e frontend_controller.erb, a minha ideia é fazer todos os controladores da área administrativa herdarem o backend_controller.erb, e todos os controladores do meu frontend herdarem o controlador frontend_controller.erb. Por sua vez os controladores backend_controller.erb e frontend_controller.erb herdarão o application_controller.erb, o que garante que a minha aplicação vai continuar funcionando corretamente.
Fazendo isso eu ganho um grau maior de componentização dos controladores, quando eu adicionar um filtro, método ou helper no backend_controller.erb ou frontend_controller.erb todos os controladores filhos deles já terão essa funcionalidade disponível.
Seguindo essa ideia eu fiz algumas alterações para implementar esse recurso:
Criei dois novos controladores:
backend_controller.erb
1 2 3 4 5 | # Filtros adicionados nesse controlador serão aplicados em todos os controladores filhos # De igual modo, todos os métodos adicionados estarão disponíveis para todos os controladores filhos class BackendController < ApplicationController end |
frontend_controller.erb
1 2 3 4 5 | # Filtros adicionados nesse controlador serão aplicados em todos os controladores filhos # De igual modo, todos os métodos adicionados estarão disponíveis para todos os controladores filhos class FrontendController < ApplicationController end |
Alterei os controladores abaixo, para herdarem os controladores criados acimas:
admin_controller.erb
1 2 3 4 5 6 | class AdminController < BackendController def index end end |
home_controller.erb
1 2 3 4 5 6 | class HomeController < FrontendController def index end end |
Fazendo isso eu consigo ganhar uma componentização muito grande, se eu adicionar alguma coisa no controlador application_controller.erb, ele está disponível tanto no admin como no frontend.
Adicionando algo no frontend_controller.erb estará disponível em todo o frontend e adicionando algo no backend_controller.erb estará disponível em todo o admin.
É possível melhorar mais ainda, vamos criar dois novos helpers:
backend_helper.rb
1 2 | module BackendHelper end |
frontend_helper.rb
1 2 | module FrontendHelper end |
Vou colocar esses helpers para serem carregados em todos os controladores que herdam backend_controller.rb e frontend_controller.erb:
backend_controller.rb
1 2 3 4 5 6 7 | # Filtros adicionados nesse controlador serão aplicados em todos os controladores filhos # De igual modo, todos os métodos adicionados estarão disponíveis para todos os controladores filhos class BackendController < ApplicationController layout "admin" helper :backend end |
Acima eu aproveitei e adicionei o layout “admin.html.erb”, que será usado por todos as views da área administrativa.
frontend_controller.rb
1 2 3 4 5 6 | # Filtros adicionados nesse controlador serão aplicados em todos os controladores filhos # De igual modo, todos os métodos adicionados estarão disponíveis para todos os controladores filhos class FrontendController < ApplicationController helper :frontend end |
Agora no application_controller.erb, comente a linha helper :all, para não carregar todos os helpers, só os que você precisa.
1 2 3 4 5 6 7 8 9 10 | # Filters added to this controller apply to all controllers in the application. # Likewise, all the methods added will be available for all controllers. class ApplicationController < ActionController::Base # helper :all # include all helpers, all the time protect_from_forgery # See ActionController::RequestForgeryProtection for details # Scrub sensitive parameters from your log # filter_parameter_logging :password end |
Pronto! ;-)
Se você gostou desse texto e acha que ajudou você, me recomende:
.

acho que outra ideia legal seria usar o Rails Engines para criar o backend como uma aplicação separada, e o front-end iria se aproveitar apenas dos modelos para exibição das coisas
esse esquema é legal pois assim fica mais fácil para aproveitar o backend em futuras aplicações ;)
Legal, não conheço Rails Engines. Vou estudar e ver como funciona.
Valeu pela dica.
Abraço.
Legal Patrick,
gostei bastante desse modelo de separação, muito interessante…
Também a idéia do Wilker utilizando os Engines deve facilitar a modularização..
Pelo Post do Akita: http://www.akitaonrails.com/2009/03/14/rails-2-3-amanha
Rails Engines não parece ser uma boa agora, talvez no Rails 3.
“No atual estado, esse suporte ainda é incompleto. Por exemplo, o Rails 2.3 ainda não suportará Engines com migrations, ainda não suporta bem assets públicos (imagens, javascript, etc dentro do plugin). Mas de fato este é um passo na direção correta. Eu espero que na próxima versão isso se complete.”
Mas veja também o screencast do Ryan Bates: http://railscasts.com/episodes/149-rails-engines
ele além de mostrar como funciona, ainda mostra como “suprir” esses problemas de arquivos de public/migrations utilizando sincronizacao de diretorio ;)
Cara muito massa Rails Engines, vai cair muito bem em diversas coisas que eu quero fazer.
Valeu!
Obrigado.