# TODO: tests
class GeoScaffoldGenerator < Rails::Generator::NamedBase
include SpatialAdapter
default_options :skip_timestamps => false, :skip_migration => false
attr_reader :controller_name,
:controller_class_path,
:controller_file_path,
:controller_class_nesting,
:controller_class_nesting_depth,
:controller_class_name,
:controller_underscore_name,
:controller_singular_name,
:controller_plural_name
alias_method :controller_file_name, :controller_underscore_name
alias_method :controller_table_name, :controller_plural_name
def initialize(runtime_args, runtime_options = {})
super
@controller_name = @name.pluralize
base_name, @controller_class_path, @controller_file_path, @controller_class_nesting, @controller_class_nesting_depth = extract_modules(@controller_name)
@controller_class_name_without_nesting, @controller_underscore_name, @controller_plural_name = inflect_names(base_name)
@controller_singular_name=base_name.singularize
if @controller_class_nesting.empty?
@controller_class_name = @controller_class_name_without_nesting
else
@controller_class_name = "#{@controller_class_nesting}::#{@controller_class_name_without_nesting}"
end
end
def manifest
spatial_attributes = []
geom_data_types = SpatialAdapter.geometry_data_types.keys.map{|x|x.to_s}
for attribute in attributes
if geom_data_types.include?(attribute.type.to_s.downcase)
spatial_attributes << attribute
end
end
if spatial_attributes.length > 1
puts "Sorry, currently only one spatial data type is supported"; exit
end
if spatial_attributes.length == 0
puts "you didn't specify a geometry data type; creating a default attribute 'geom' of type 'point' "
attributes << Rails::Generator::GeneratedAttribute.new("geom", "point")
spatial_attributes << attributes .last
end
if spatial_attributes.first.type.to_s != "point"
puts "Sorry currently only one 'point' data type is supported"; exit
end
record do |m|
# Check for class naming collisions.
m.class_collisions(controller_class_path, "#{controller_class_name}Controller", "#{controller_class_name}Helper")
m.class_collisions(class_path, "#{class_name}")
# Controller, helper, views, and test directories.
m.directory(File.join('app/models', class_path))
m.directory(File.join('app/controllers', controller_class_path))
m.directory(File.join('app/helpers', controller_class_path))
m.directory(File.join('app/views', controller_class_path, controller_file_name))
m.directory(File.join('app/views/layouts', controller_class_path))
m.directory(File.join('test/functional', controller_class_path))
m.directory(File.join('test/unit', class_path))
# crud views
for action in scaffold_views
m.template(
"view_#{action}.html.erb",
File.join('app/views', controller_class_path, controller_file_name, "#{action}.html.erb"),
:assigns => { :spatial_attributes => spatial_attributes })
end
# spatial mime-type views
%w{index show}.each do |action|
%w{kml georss}.each do |mime|
m.template( "view_#{action}.#{mime}.erb",
File.join('app/views', controller_class_path, controller_file_name, "#{action}.#{mime}.builder"),
:assigns => { :spatial_attributes => spatial_attributes })
end
end
# Layout and stylesheet.
m.template('layout.html.erb', File.join('app/views/layouts', controller_class_path, "#{controller_file_name}.html.erb"))
m.template('style2.css', 'public/stylesheets/geo_scaffold.css')
# icons
m.file 'google_earth16x16.gif', 'public/images/google_earth16x16.gif'
m.file 'google_earth32x32.gif', 'public/images/google_earth32x32.gif'
m.file 'feed-icon16x16.png', 'public/images/feed-icon16x16.png'
m.file 'feed-icon32x32.png', 'public/images/feed-icon32x32.png'
m.file 'kml_icon16x16.png', 'public/images/kml_icon16x16.png'
m.file 'feed-icon16x16.gif', 'public/images/feed-icon16x16.gif'
m.file 'bullet.gif', 'public/images/bullet.gif'
m.file 'header_backdrop.png', 'public/images/header_backdrop.png'
m.file 'Globe2.png', 'public/images/Globe2.png'
# javascript helper
m.template 'javascript_helper.js', 'public/javascripts/geo_scaffold.js'
# controller
m.template(
'controller.rb', File.join('app/controllers', controller_class_path, "#{controller_file_name}_controller.rb"),
:assigns => { :spatial_attributes => spatial_attributes }
)
#m.template('functional_test.rb', File.join('test/functional', controller_class_path, "#{controller_file_name}_controller_test.rb"))
m.template('helper.rb', File.join('app/helpers', controller_class_path, "#{controller_file_name}_helper.rb"),
:assigns => { :spatial_attributes => spatial_attributes })
m.route_resources controller_file_name
m.dependency 'geo_model', [name] + @args #, :collision => :skip
add_mime_types
check_dependencies
end
end
protected
# create new mime-types
# TODO: refactor this so that mime-types are accessable externally
def add_mime_types
mime_types = []
mime_types << [/^Mime::Type.register \"application\/vnd.google-earth\.kml\+xml\", :kml$/, 'Mime::Type.register "application/vnd.google-earth.kml+xml", :kml']
mime_types << [/^Mime::Type.register \"application\/rss\+xml\", :georss$/, 'Mime::Type.register "application/rss+xml", :georss']
path = 'config/initializers/mime_types.rb'
mime_types.each do |m|
content = File.read(path).gsub!(m[0], m[1])
if content.nil? # mime not found in file
File.open(path, 'a') { |file| file << "\n" << m[1] << "\n" } #open file and append mime-type
logger.mime_types m[1]
end
end
end
def check_dependencies
unless File.exist?(RAILS_ROOT+'/vendor/plugin/ym4r_gm')
STDOUT.puts " MISSING DEPENDENCY: ym4r_gm (http://ym4r.rubyforge.org). To install please do:"
STDOUT.puts " ruby script/plugin install svn://rubyforge.org/var/svn/ym4r/Plugins/GM/trunk/ym4r_gm"
end
end
# Override with your own usage banner.
def banner
"Usage: #{$0} scaffold ModelName [field:type, field:type]"
end
def add_options!(opt)
opt.separator ''
opt.separator 'Options:'
opt.on("--skip-timestamps",
"Don't add timestamps to the migration file for this model") { |v| options[:skip_timestamps] = v }
opt.on("--skip-migration",
"Don't generate a migration file for this model") { |v| options[:skip_migration] = v }
end
def scaffold_views
%w[ index show new edit ]
end
def model_name
class_name.demodulize
end
end