I came across this question hoping to find an answer as the default rails scaffold generator is pretty crippled if you want to:
- Refactor your scaffold views or make use of partials
- Use controller and view inheritance
- Support additional controller actions and their views
- Support a mix of template engines, erb, haml, slim, jbuilder, prawn etc
Alas, I rolled up my sleeves and figured out how to make rails scaffold generator support the above requirements which I make use of on my current project.
If you want full control over your scaffold templates when you type rails g scaffold Foo ...
then read on!
The Problem
The default rails scaffold generator is template engine specific AND hard codes a fixed set of view files that it looks for.
The Solution
Use a custom generator and wire it up to the scaffold template generation.
I have included a generator below that looks in lib/templates/scaffold
and will generate scaffold views for ALL files found there including templates, partials and sub-directories regardless of the template engine.
IMO this should be the default rails behaviour instead of us having to jump through hoops like this..
Implementation
Do the following:
- Put whatever templates or partials you want created when scaffolding into
lib/templates/scaffold
. Notice there is no erb
subdirectory !!
- Configure the generator template engine for your project as shown below
- Add my custom view generator (included below)
Rails 4 generator configuration:
# config/initializers/generators.rb
Rails.application.config.generators do |g|
# ...
g.template_engine :all
g.fallbacks[:all] = :erb # or haml/slim etc
end
Rails 3 generator configuration:
# config/application.rb
config.generators do |g|
# ...
g.template_engine :all
g.fallbacks[:all] = :erb # or haml/slim etc
end
The custom scaffold generator:
# lib/generators/all/scaffold/scaffold_generator.rb
require 'rails/generators/named_base'
require 'rails/generators/resource_helpers'
module All # :nodoc:
module Generators # :nodoc:
class ScaffoldGenerator < Rails::Generators::NamedBase # :nodoc:
include Rails::Generators::ResourceHelpers
source_root File.join(Rails.root, 'lib', 'templates', 'scaffold', File::SEPARATOR)
argument :attributes, type: :array, default: [], banner: "field:type field:type"
def create_root_folder
empty_directory File.join("app/views", controller_file_path)
end
def copy_view_files
available_views.each do |view|
template view, File.join("app/views", controller_file_path, view)
end
end
protected
def available_views
# use all template files contained in source_root ie 'lib/templates/scaffold/**/*'
base = self.class.source_root
base_len = base.length
Dir[File.join(base, '**', '*')].select { |f| File.file?(f) }.map{|f| f[base_len..-1]}
end
end
end
end
Caveats
No warranty offered :)
I hope this helps others who want to refactor their scaffold views with partials and support multiple template engines.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…