From daee6fd92ac16878f6806c3382a9e74592aa9656 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 7 Feb 2005 13:14:05 +0000 Subject: Added new generator framework that informs about its doings on generation and enables updating and destruction of generated artifacts. See the new script/destroy and script/update for more details #487 [bitsweat] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@518 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- .../components/scaffold/scaffold_generator.rb | 161 +++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb (limited to 'railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb') diff --git a/railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb b/railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb new file mode 100644 index 0000000000..4445995b46 --- /dev/null +++ b/railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb @@ -0,0 +1,161 @@ +class ScaffoldingSandbox + include ActionView::Helpers::ActiveRecordHelper + + attr_accessor :form_action, :singular_name, :suffix, :model_instance + + def sandbox_binding + binding + end +end + +class ActionView::Helpers::InstanceTag + def to_input_field_tag(field_type, options={}) + field_meth = "#{field_type}_field" + "<%= #{field_meth} '#{@object_name}', '#{@method_name}' #{options.empty? ? '' : ', '+options.inspect} %>" + end + + def to_text_area_tag(options = {}) + "<%= text_area '#{@object_name}', '#{@method_name}' #{options.empty? ? '' : ', '+ options.inspect} %>" + end + + def to_date_select_tag(options = {}) + "<%= date_select '#{@object_name}', '#{@method_name}' #{options.empty? ? '' : ', '+ options.inspect} %>" + end + + def to_datetime_select_tag(options = {}) + "<%= datetime_select '#{@object_name}', '#{@method_name}' #{options.empty? ? '' : ', '+ options.inspect} %>" + end +end + +class ScaffoldGenerator < Rails::Generator::NamedBase + attr_reader :controller_name, + :controller_class_path, + :controller_class_nesting, + :controller_class_name, + :controller_singular_name, + :controller_plural_name + alias_method :controller_file_name, :controller_singular_name + alias_method :controller_table_name, :controller_plural_name + + def initialize(runtime_args, runtime_options = {}) + super + @controller_name = args.shift || @name.pluralize + base_name, @controller_class_path, @controller_class_nesting = extract_modules(@controller_name) + @controller_class_name, @controller_singular_name, @controller_plural_name = inflect_names(base_name) + end + + def manifest + record do |m| + # Depend on model generator but skip if the model exists. + m.dependency 'model', [@name], :collision => :skip + + # Check for class naming collisions. + m.class_collisions "#{controller_class_name}Controller", "#{controller_class_name}ControllerTest", "#{controller_class_name}Helper" + + # Views directory. + m.directory File.join('app/views', controller_class_path, controller_file_name) + + # Controller class, functional test, helper, and views. + m.template 'controller.rb', + File.join('app/controllers', + controller_class_path, + "#{controller_file_name}_controller.rb") + + m.template 'functional_test.rb', + File.join('test/functional', + controller_class_path, + "#{controller_file_name}_controller_test.rb") + + m.template 'controller:helper.rb', + File.join('app/helpers', + controller_class_path, + "#{controller_file_name}_helper.rb") + + # Layout and stylesheet. + m.template 'layout.rhtml', "app/views/layouts/#{controller_file_name}.rhtml" + m.template 'style.css', 'public/stylesheets/scaffold.css' + + # Scaffolded views. + scaffold_views.each do |action| + m.template "view_#{action}.rhtml", + File.join('app/views', + controller_class_path, controller_file_name, + "#{action}.rhtml"), + :assigns => { :action => action } + end + + # Scaffolded forms. + scaffold_forms.each do |action| + m.complex_template "view_#{action}.rhtml", + File.join('app/views', + controller_class_path, + controller_file_name, + "#{action}.rhtml"), + :assigns => { :action => action }, + :insert => 'form.rhtml', + :sandbox => lambda { create_sandbox(action) }, + :begin_mark => 'form', + :end_mark => 'eoform', + :mark_id => singular_name + end + + # Unscaffolded views. + unscaffolded_actions.each do |action| + m.template "controller:view.rhtml", + File.join('app/views', + controller_class_path, controller_file_name, + "#{action}.rhtml"), + :assigns => { :action => action } + end + end + end + + protected + # Override with your own usage banner. + def banner + "Usage: #{$0} scaffold ModelName [ControllerName] [action, ...]" + end + + def scaffold_views + %w(list show) + end + + def scaffold_forms + %w(new edit) + end + + def scaffold_actions + scaffold_views + %w(index create update destroy) + end + + def unscaffolded_actions + args - scaffold_actions + end + + def suffix + "_#{singular_name}" if options[:suffix] + end + + def create_sandbox(action) + sandbox = ScaffoldingSandbox.new + action = if action == 'edit' then 'update' else 'create' end + sandbox.form_action = action + sandbox.singular_name = singular_name + begin + sandbox.model_instance = model_instance + sandbox.instance_variable_set("@#{singular_name}", sandbox.model_instance) + rescue ActiveRecord::StatementInvalid => e + logger.error "Before updating scaffolding from new DB schema, try creating a table for your model (#{class_name})" + raise SystemExit + end + sandbox.suffix = suffix + sandbox + end + + def model_instance + unless Object.const_defined?(class_name) + Object.const_set(class_name, Class.new(ActiveRecord::Base)) + end + Object.const_get(class_name).new + end +end -- cgit v1.2.3