aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib/rails_generator/generators
diff options
context:
space:
mode:
Diffstat (limited to 'railties/lib/rails_generator/generators')
-rw-r--r--railties/lib/rails_generator/generators/applications/app/USAGE16
-rw-r--r--railties/lib/rails_generator/generators/applications/app/app_generator.rb118
-rw-r--r--railties/lib/rails_generator/generators/components/controller/USAGE30
-rw-r--r--railties/lib/rails_generator/generators/components/controller/controller_generator.rb34
-rw-r--r--railties/lib/rails_generator/generators/components/controller/templates/controller.rb10
-rw-r--r--railties/lib/rails_generator/generators/components/controller/templates/functional_test.rb17
-rw-r--r--railties/lib/rails_generator/generators/components/controller/templates/helper.rb2
-rw-r--r--railties/lib/rails_generator/generators/components/controller/templates/view.rhtml2
-rw-r--r--railties/lib/rails_generator/generators/components/mailer/USAGE19
-rw-r--r--railties/lib/rails_generator/generators/components/mailer/mailer_generator.rb26
-rw-r--r--railties/lib/rails_generator/generators/components/mailer/templates/fixture.rhtml3
-rw-r--r--railties/lib/rails_generator/generators/components/mailer/templates/mailer.rb13
-rw-r--r--railties/lib/rails_generator/generators/components/mailer/templates/unit_test.rb29
-rw-r--r--railties/lib/rails_generator/generators/components/mailer/templates/view.rhtml3
-rw-r--r--railties/lib/rails_generator/generators/components/model/USAGE17
-rw-r--r--railties/lib/rails_generator/generators/components/model/model_generator.rb13
-rw-r--r--railties/lib/rails_generator/generators/components/model/templates/fixtures.yml10
-rw-r--r--railties/lib/rails_generator/generators/components/model/templates/model.rb2
-rw-r--r--railties/lib/rails_generator/generators/components/model/templates/unit_test.rb14
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/USAGE32
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb161
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/controller.rb55
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/form.rhtml5
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb80
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/layout.rhtml11
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/style.css53
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/view_edit.rhtml7
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml24
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/view_new.rhtml6
-rw-r--r--railties/lib/rails_generator/generators/components/scaffold/templates/view_show.rhtml8
30 files changed, 820 insertions, 0 deletions
diff --git a/railties/lib/rails_generator/generators/applications/app/USAGE b/railties/lib/rails_generator/generators/applications/app/USAGE
new file mode 100644
index 0000000000..3bb55113fa
--- /dev/null
+++ b/railties/lib/rails_generator/generators/applications/app/USAGE
@@ -0,0 +1,16 @@
+Description:
+ The 'rails' command creates a new Rails application with a default
+ directory structure and configuration at the path you specify.
+
+Example:
+ rails ~/Code/Ruby/weblog
+
+ This generates a skeletal Rails installation in ~/Code/Ruby/weblog.
+ See the README in the newly created application to get going.
+
+WARNING:
+ Only specify --without-gems if you did not use gems to install Rails.
+ Your application will expect to find activerecord, actionpack, and
+ actionmailer directories in the vendor directory. A popular way to track
+ the bleeding edge of Rails development is to checkout from source control
+ directly to the vendor directory. See http://dev.rubyonrails.com
diff --git a/railties/lib/rails_generator/generators/applications/app/app_generator.rb b/railties/lib/rails_generator/generators/applications/app/app_generator.rb
new file mode 100644
index 0000000000..0beb11b237
--- /dev/null
+++ b/railties/lib/rails_generator/generators/applications/app/app_generator.rb
@@ -0,0 +1,118 @@
+class AppGenerator < Rails::Generator::Base
+ DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'],
+ Config::CONFIG['ruby_install_name'])
+
+ default_options :gem => true, :shebang => DEFAULT_SHEBANG
+ mandatory_options :source => "#{File.dirname(__FILE__)}/../.."
+
+ def initialize(runtime_args, runtime_options = {})
+ super
+ usage if args.empty?
+ @destination_root = args.shift
+ puts "eek! #{destination_root.inspect}"
+ end
+
+ def manifest
+ script_options = { :chmod => 0755, :shebang => options[:shebang] }
+
+ record do |m|
+ # Root directory and all subdirectories.
+ m.directory ''
+ BASEDIRS.each { |path| m.directory path }
+
+ # Root
+ m.file "fresh_rakefile", "Rakefile"
+ m.file "README", "README"
+ m.file "CHANGELOG", "CHANGELOG"
+
+ # Application
+ m.template "helpers/application.rb", "app/controllers/application.rb"
+ m.template "helpers/application_helper.rb", "app/helpers/application_helper.rb"
+ m.template "helpers/test_helper.rb", "test/test_helper.rb"
+
+ # database.yml and .htaccess
+ m.template "configs/database.yml", "config/database.yml"
+ m.template "configs/apache.conf", "public/.htaccess"
+
+ # Environments
+ if options[:gem]
+ m.file "environments/shared_for_gem.rb", "config/environment.rb"
+ else
+ m.file "environments/shared.rb", "config/environment.rb"
+ end
+ m.file "environments/production.rb", "config/environments/production.rb"
+ m.file "environments/development.rb", "config/environments/development.rb"
+ m.file "environments/test.rb", "config/environments/test.rb"
+
+ # Scripts
+ %w(console destroy generate server).each do |file|
+ m.file "bin/#{file}", "script/#{file}", script_options
+ end
+ if options[:gem]
+ m.file "bin/breakpointer_for_gem", "script/breakpointer", script_options
+ else
+ m.file "bin/breakpointer", "script/breakpointer", script_options
+ end
+
+ # Dispatches
+ m.file "dispatches/dispatch.rb", "public/dispatch.rb", script_options
+ m.file "dispatches/dispatch.rb", "public/dispatch.cgi", script_options
+ m.file "dispatches/dispatch.fcgi", "public/dispatch.fcgi", script_options
+
+ # HTML files
+ %w(404 500 index).each do |file|
+ m.template "html/#{file}.html", "public/#{file}.html"
+ end
+
+ # Docs
+ m.template "doc/index.html", "public/_doc/index.html"
+ m.file "doc/README_FOR_APP", "doc/README_FOR_APP"
+
+ # Logs
+ %w(apache production development test).each { |file|
+ m.file "configs/empty.log", "log/#{file}.log", :chmod => 0666
+ }
+ end
+ end
+
+ protected
+ def banner
+ "Usage: #{$0} /path/to/your/app [options]"
+ end
+
+ def add_options!(opt)
+ opt.separator ''
+ opt.separator 'Options:'
+ opt.on("--ruby [#{DEFAULT_SHEBANG}]",
+ "Path to the Ruby binary of your choice.") { |options[:shebang]| }
+ opt.on("--without-gems",
+ "Don't use the Rails gems for your app.",
+ "WARNING: see note below.") { |options[:gem]| }
+ end
+
+
+ # Installation skeleton. Intermediate directories are automatically
+ # created so don't sweat their absence here.
+ BASEDIRS = %w(
+ app/controllers
+ app/helpers
+ app/models
+ app/views/layouts
+ config/environments
+ db
+ doc
+ lib
+ log
+ public/_doc
+ public/images
+ public/javascripts
+ public/stylesheets
+ script
+ test/fixtures
+ test/functional
+ test/mocks/development
+ test/mocks/testing
+ test/unit
+ vendor
+ )
+end
diff --git a/railties/lib/rails_generator/generators/components/controller/USAGE b/railties/lib/rails_generator/generators/components/controller/USAGE
new file mode 100644
index 0000000000..ec64209135
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/controller/USAGE
@@ -0,0 +1,30 @@
+Description:
+ The controller generator creates stubs for a new controller and its views.
+
+ The generator takes a controller name and a list of views as arguments.
+ The controller name may be given in CamelCase or under_score and should
+ not be suffixed with 'Controller'. To create a controller within a
+ module, specify the controller name as 'module/controller'.
+
+ The generator creates a controller class in app/controllers with view
+ templates in app/views/controller_name, a helper class in app/helpers,
+ and a functional test suite in test/functional.
+
+Example:
+ ./script/generate controller CreditCard open debit credit close
+
+ Credit card controller with URLs like /credit_card/debit.
+ Controller: app/controllers/credit_card_controller.rb
+ Views: app/views/credit_card/debit.rhtml [...]
+ Helper: app/helpers/credit_card_helper.rb
+ Test: test/functional/credit_card_controller_test.rb
+
+Modules Example:
+ ./script/generate controller 'admin/credit_card' suspend late_fee
+
+ Credit card admin controller with URLs /admin/credit_card/suspend.
+ Controller: app/controllers/admin/credit_card_controller.rb
+ Views: app/views/admin/credit_card/debit.rhtml [...]
+ Helper: app/helpers/admin/credit_card_helper.rb
+ Test: test/functional/admin/credit_card_controller_test.rb
+
diff --git a/railties/lib/rails_generator/generators/components/controller/controller_generator.rb b/railties/lib/rails_generator/generators/components/controller/controller_generator.rb
new file mode 100644
index 0000000000..1f7e69d124
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/controller/controller_generator.rb
@@ -0,0 +1,34 @@
+class ControllerGenerator < Rails::Generator::NamedBase
+ def manifest
+ record do |m|
+ # Check for class naming collisions.
+ m.class_collisions "#{class_name}Controller", "#{class_name}ControllerTest", "#{class_name}Helper"
+
+ # Views directory even if there are no actions.
+ m.directory File.join('app/views', class_path, file_name)
+
+ # Controller class, functional test, and helper class.
+ m.template 'controller.rb',
+ File.join('app/controllers',
+ class_path,
+ "#{file_name}_controller.rb")
+
+ m.template 'functional_test.rb',
+ File.join('test/functional',
+ class_path,
+ "#{file_name}_controller_test.rb")
+
+ m.template 'helper.rb',
+ File.join('app/helpers',
+ class_path,
+ "#{file_name}_helper.rb")
+
+ # View template for each action.
+ actions.each do |action|
+ m.template 'view.rhtml',
+ File.join('app/views', class_path, file_name, "#{action}.rhtml"),
+ :assigns => { :action => action }
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails_generator/generators/components/controller/templates/controller.rb b/railties/lib/rails_generator/generators/components/controller/templates/controller.rb
new file mode 100644
index 0000000000..da71b5f057
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/controller/templates/controller.rb
@@ -0,0 +1,10 @@
+class <%= class_name %>Controller < ApplicationController
+<% if options[:scaffold] -%>
+ scaffold :<%= singular_name %>
+<% end -%>
+<% for action in actions -%>
+
+ def <%= action %>
+ end
+<% end -%>
+end
diff --git a/railties/lib/rails_generator/generators/components/controller/templates/functional_test.rb b/railties/lib/rails_generator/generators/components/controller/templates/functional_test.rb
new file mode 100644
index 0000000000..c975cb3ce3
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/controller/templates/functional_test.rb
@@ -0,0 +1,17 @@
+require File.dirname(__FILE__) + '/../test_helper'
+require '<%= file_name %>_controller'
+
+# Re-raise errors caught by the controller.
+class <%= class_name %>Controller; def rescue_action(e) raise e end; end
+
+class <%= class_name %>ControllerTest < Test::Unit::TestCase
+ def setup
+ @controller = <%= class_name %>Controller.new
+ @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
+ end
+
+ # Replace this with your real tests.
+ def test_truth
+ assert true
+ end
+end
diff --git a/railties/lib/rails_generator/generators/components/controller/templates/helper.rb b/railties/lib/rails_generator/generators/components/controller/templates/helper.rb
new file mode 100644
index 0000000000..3fe2ecdc74
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/controller/templates/helper.rb
@@ -0,0 +1,2 @@
+module <%= class_name %>Helper
+end
diff --git a/railties/lib/rails_generator/generators/components/controller/templates/view.rhtml b/railties/lib/rails_generator/generators/components/controller/templates/view.rhtml
new file mode 100644
index 0000000000..7e7a7d53ce
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/controller/templates/view.rhtml
@@ -0,0 +1,2 @@
+<h1><%= class_name %>#<%= action %></h1>
+<p>Find me in app/views/<%= file_name %>/<%= action %>.rhtml</p>
diff --git a/railties/lib/rails_generator/generators/components/mailer/USAGE b/railties/lib/rails_generator/generators/components/mailer/USAGE
new file mode 100644
index 0000000000..50d3de19de
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/mailer/USAGE
@@ -0,0 +1,19 @@
+Description:
+ The mailer generator creates stubs for a new mailer and its views.
+
+ The generator takes a mailer name and a list of views as arguments.
+ The mailer name may be given in CamelCase or under_score and should
+ not be suffixed with 'Mailer'.
+
+ The generator creates a mailer class in app/models with view templates
+ in app/views/mailer_name, and a test suite with fixtures in test/unit.
+
+Example:
+ ./script/generate mailer Notifications signup forgot_password invoice
+
+ This will create a NotificationsMailer:
+ Mailer: app/models/notifications.rb
+ Views: app/views/notifications/signup.rhtml [...]
+ Test: test/unit/credit_card_controller_test.rb
+ Fixtures: test/fixtures/notifications/signup [...]
+
diff --git a/railties/lib/rails_generator/generators/components/mailer/mailer_generator.rb b/railties/lib/rails_generator/generators/components/mailer/mailer_generator.rb
new file mode 100644
index 0000000000..81d4599f7f
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/mailer/mailer_generator.rb
@@ -0,0 +1,26 @@
+class MailerGenerator < Rails::Generator::NamedBase
+ def manifest
+ record do |m|
+ # Check for class naming collisions.
+ m.class_collisions class_name, "#{class_name}Test"
+
+ # Mailer class and unit test.
+ m.template "mailer.rb", "app/models/#{file_name}.rb"
+ m.template "unit_test.rb", "test/unit/#{file_name}_test.rb"
+
+ # Views and fixtures directories.
+ m.directory "app/views/#{file_name}"
+ m.directory "test/fixtures/#{table_name}"
+
+ # View template and fixture for each action.
+ actions.each do |action|
+ m.template "view.rhtml",
+ "app/views/#{file_name}/#{action}.rhtml",
+ :assigns => { :action => action }
+ m.template "fixture.rhtml",
+ "test/fixtures/#{table_name}/#{action}",
+ :assigns => { :action => action }
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails_generator/generators/components/mailer/templates/fixture.rhtml b/railties/lib/rails_generator/generators/components/mailer/templates/fixture.rhtml
new file mode 100644
index 0000000000..b481906829
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/mailer/templates/fixture.rhtml
@@ -0,0 +1,3 @@
+<%= class_name %>#<%= action %>
+
+Find me in app/views/<%= file_name %>/<%= action %>.rhtml
diff --git a/railties/lib/rails_generator/generators/components/mailer/templates/mailer.rb b/railties/lib/rails_generator/generators/components/mailer/templates/mailer.rb
new file mode 100644
index 0000000000..81c19fa76d
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/mailer/templates/mailer.rb
@@ -0,0 +1,13 @@
+class <%= class_name %> < ActionMailer::Base
+<% for action in actions -%>
+
+ def <%= action %>(sent_on = Time.now)
+ @subject = '<%= class_name %>#<%= action %>'
+ @body = {}
+ @recipients = ''
+ @from = ''
+ @sent_on = sent_on
+ @headers = {}
+ end
+<% end -%>
+end
diff --git a/railties/lib/rails_generator/generators/components/mailer/templates/unit_test.rb b/railties/lib/rails_generator/generators/components/mailer/templates/unit_test.rb
new file mode 100644
index 0000000000..70fd3afe37
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/mailer/templates/unit_test.rb
@@ -0,0 +1,29 @@
+require File.dirname(__FILE__) + '/../test_helper'
+require '<%= file_name %>'
+
+class <%= class_name %>Test < Test::Unit::TestCase
+ FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures'
+
+ def setup
+ ActionMailer::Base.delivery_method = :test
+ ActionMailer::Base.perform_deliveries = true
+ ActionMailer::Base.deliveries = []
+
+ @expected = TMail::Mail.new
+ end
+
+<% for action in actions -%>
+ def test_<%= action %>
+ @expected.subject = '<%= class_name %>#<%= action %>'
+ @expected.body = read_fixture('<%= action %>')
+ @expected.date = Time.now
+
+ assert_equal @expected.encoded, <%= class_name %>.create_<%= action %>(@expected.date).encoded
+ end
+
+<% end -%>
+ private
+ def read_fixture(action)
+ IO.readlines("#{FIXTURES_PATH}/<%= file_name %>/#{action}")
+ end
+end
diff --git a/railties/lib/rails_generator/generators/components/mailer/templates/view.rhtml b/railties/lib/rails_generator/generators/components/mailer/templates/view.rhtml
new file mode 100644
index 0000000000..b481906829
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/mailer/templates/view.rhtml
@@ -0,0 +1,3 @@
+<%= class_name %>#<%= action %>
+
+Find me in app/views/<%= file_name %>/<%= action %>.rhtml
diff --git a/railties/lib/rails_generator/generators/components/model/USAGE b/railties/lib/rails_generator/generators/components/model/USAGE
new file mode 100644
index 0000000000..f0669104fe
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/model/USAGE
@@ -0,0 +1,17 @@
+Description:
+ The model generator creates stubs for a new model.
+
+ The generator takes a model name as its argument. The model name may be
+ given in CamelCase or under_score and should not be suffixed with 'Model'.
+
+ The generator creates a model class in app/models, a test suite in
+ test/unit, and test fixtures in test/fixtures/model_name.yml.
+
+Example:
+ ./script/generate model Account
+
+ This will create an Account model:
+ Model: app/models/account.rb
+ Test: test/unit/account_test.rb
+ Fixtures: test/fixtures/accounts.yml
+
diff --git a/railties/lib/rails_generator/generators/components/model/model_generator.rb b/railties/lib/rails_generator/generators/components/model/model_generator.rb
new file mode 100644
index 0000000000..32577d08a3
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/model/model_generator.rb
@@ -0,0 +1,13 @@
+class ModelGenerator < Rails::Generator::NamedBase
+ def manifest
+ record do |m|
+ # Check for class naming collisions.
+ m.class_collisions class_name, "#{class_name}Test"
+
+ # Model class, unit test, and fixtures.
+ m.template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
+ m.template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb")
+ m.template 'fixtures.yml', File.join('test/fixtures', class_path, "#{table_name}.yml")
+ end
+ end
+end
diff --git a/railties/lib/rails_generator/generators/components/model/templates/fixtures.yml b/railties/lib/rails_generator/generators/components/model/templates/fixtures.yml
new file mode 100644
index 0000000000..fc3185dc46
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/model/templates/fixtures.yml
@@ -0,0 +1,10 @@
+# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
+# Set the $base_id variable in the setup method of your tests.
+# It's used to ensure that ids don't clash in some databases.
+<%% $base_id ||= 100000 %>
+
+first_<%= singular_name %>:
+ id: <%%= $base_id %>
+
+another_<%= singular_name %>:
+ id: <%%= $base_id + 1 %>
diff --git a/railties/lib/rails_generator/generators/components/model/templates/model.rb b/railties/lib/rails_generator/generators/components/model/templates/model.rb
new file mode 100644
index 0000000000..8d4c89e912
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/model/templates/model.rb
@@ -0,0 +1,2 @@
+class <%= class_name %> < ActiveRecord::Base
+end
diff --git a/railties/lib/rails_generator/generators/components/model/templates/unit_test.rb b/railties/lib/rails_generator/generators/components/model/templates/unit_test.rb
new file mode 100644
index 0000000000..db0fbf5d33
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/model/templates/unit_test.rb
@@ -0,0 +1,14 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class <%= class_name %>Test < Test::Unit::TestCase
+ fixtures :<%= table_name %>
+
+ def setup
+ $base_id = 1000001
+ end
+
+ # Replace this with your real tests.
+ def test_truth
+ assert true
+ end
+end
diff --git a/railties/lib/rails_generator/generators/components/scaffold/USAGE b/railties/lib/rails_generator/generators/components/scaffold/USAGE
new file mode 100644
index 0000000000..d1f29ad63c
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/scaffold/USAGE
@@ -0,0 +1,32 @@
+Description:
+ The scaffold generator creates a controller to interact with a model.
+ If the model does not exist, it creates the model as well. The generated
+ code is equivalent to the "scaffold :model" declaration, making it easy
+ to migrate when you wish to customize your controller and views.
+
+ The generator takes a model name, an optional controller name, and a
+ list of views as arguments. Scaffolded actions and views are created
+ automatically. Any views left over generate empty stubs.
+
+ The scaffolded actions and views are:
+ index, list, show, new, create, edit, update, destroy
+
+ If a controller name is not given, the plural form of the model name
+ will be used. The model and controller names may be given in CamelCase
+ or under_score and should not be suffixed with 'Model' or 'Controller'.
+ Both model and controller names may be prefixed with a module like a
+ file path; see the Modules Example for usage.
+
+Example:
+ ./script/generate scaffold Account Bank debit credit
+
+ This will generate an Account model and BankController with a full test
+ suite and a basic user interface. Now create the accounts table in your
+ database and browse to http://localhost/bank/ -- voila, you're on Rails!
+
+Modules Example:
+ ./script/generate controller 'admin/credit_card' suspend late_fee
+
+ This will generate a CreditCard model and CreditCardController controller
+ in the admin module.
+
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
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/controller.rb b/railties/lib/rails_generator/generators/components/scaffold/templates/controller.rb
new file mode 100644
index 0000000000..c409284cb1
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/controller.rb
@@ -0,0 +1,55 @@
+class <%= controller_class_name %>Controller < ApplicationController
+<% unless suffix -%>
+
+ def index
+ list
+ render_action 'list'
+ end
+<% end -%>
+
+<% for action in unscaffolded_actions -%>
+ def <%= action %><%= suffix %>
+ end
+
+<% end -%>
+ def list<%= suffix %>
+ @<%= plural_name %> = <%= class_name %>.find_all
+ end
+
+ def show<%= suffix %>
+ @<%= singular_name %> = <%= class_name %>.find(@params['id'])
+ end
+
+ def new<%= suffix %>
+ @<%= singular_name %> = <%= class_name %>.new
+ end
+
+ def create<%= suffix %>
+ @<%= singular_name %> = <%= class_name %>.new(@params['<%= singular_name %>'])
+ if @<%= singular_name %>.save
+ flash['notice'] = '<%= class_name %> was successfully created.'
+ redirect_to :action => 'list<%= suffix %>'
+ else
+ render_action 'new<%= suffix %>'
+ end
+ end
+
+ def edit<%= suffix %>
+ @<%= singular_name %> = <%= class_name %>.find(@params['id'])
+ end
+
+ def update
+ @<%= singular_name %> = <%= class_name %>.find(@params['<%= singular_name %>']['id'])
+ if @<%= singular_name %>.update_attributes(@params['<%= singular_name %>'])
+ flash['notice'] = '<%= class_name %> was successfully updated.'
+ redirect_to :action => 'show<%= suffix %>', :id => @<%= singular_name %>.id
+ else
+ render_action 'edit<%= suffix %>'
+ end
+ end
+
+ def destroy<%= suffix %>
+ <%= class_name %>.find(@params['id']).destroy
+ redirect_to :action => 'list<%= suffix %>'
+ end
+end
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/form.rhtml b/railties/lib/rails_generator/generators/components/scaffold/templates/form.rhtml
new file mode 100644
index 0000000000..d314c5f6b5
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/form.rhtml
@@ -0,0 +1,5 @@
+<%%= start_form_tag :action => '<%= @form_action %><%= @suffix %>' %>
+<%%= hidden_field '<%= @singular_name %>', 'id' %>
+<%= all_input_tags(@model_instance, @singular_name, {}) %>
+<input type="submit" value="<%= @form_action.to_s.capitalize %>" />
+<%%= end_form_tag %>
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb b/railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb
new file mode 100644
index 0000000000..ea9c8e4e94
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb
@@ -0,0 +1,80 @@
+require File.dirname(__FILE__) + '/../test_helper'
+require '<%= controller_file_name %>_controller'
+
+# Re-raise errors caught by the controller.
+class <%= controller_class_name %>Controller; def rescue_action(e) raise e end; end
+
+class <%= controller_class_name %>ControllerTest < Test::Unit::TestCase
+ fixtures :<%= table_name %>
+
+ def setup
+ $base_id = 1000001
+ @controller = <%= controller_class_name %>Controller.new
+ @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
+ end
+
+<% for action in unscaffolded_actions -%>
+ def test_<%= action %>
+ process :<%= action %>
+ assert_rendered_file '<%= action %>'
+ end
+
+<% end -%>
+<% unless suffix -%>
+ def test_index
+ process :index
+ assert_rendered_file 'list'
+ end
+
+<% end -%>
+ def test_list<%= suffix %>
+ process :list<%= suffix %>
+ assert_rendered_file 'list<%= suffix %>'
+ assert_template_has '<%= plural_name %>'
+ end
+
+ def test_show<%= suffix %>
+ process :show<%= suffix %>, 'id' => $base_id
+ assert_rendered_file 'show'
+ assert_template_has '<%= singular_name %>'
+ assert_valid_record '<%= singular_name %>'
+ end
+
+ def test_new<%= suffix %>
+ process :new<%= suffix %>
+ assert_rendered_file 'new<%= suffix %>'
+ assert_template_has '<%= singular_name %>'
+ end
+
+ def test_create
+ num_<%= plural_name %> = <%= class_name %>.find_all.size
+
+ process :create<%= suffix %>, '<%= singular_name %>' => { }
+ assert_redirected_to :action => 'list<%= suffix %>'
+
+ assert_equal num_<%= plural_name %> + 1, <%= class_name %>.find_all.size
+ end
+
+ def test_edit<%= suffix %>
+ process :edit<%= suffix %>, 'id' => $base_id
+ assert_rendered_file 'edit<%= suffix %>'
+ assert_template_has '<%= singular_name %>'
+ assert_valid_record '<%= singular_name %>'
+ end
+
+ def test_update<%= suffix %>
+ process :update<%= suffix %>, '<%= singular_name %>' => { 'id' => $base_id }
+ assert_redirected_to :action => 'show<%= suffix %>', :id => $base_id
+ end
+
+ def test_destroy<%= suffix %>
+ assert_not_nil <%= class_name %>.find($base_id)
+
+ process :destroy, 'id' => $base_id
+ assert_redirected_to :action => 'list<%= suffix %>'
+
+ assert_raise(ActiveRecord::RecordNotFound) {
+ <%= singular_name %> = <%= class_name %>.find($base_id)
+ }
+ end
+end
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/layout.rhtml b/railties/lib/rails_generator/generators/components/scaffold/templates/layout.rhtml
new file mode 100644
index 0000000000..c4815bd0a3
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/layout.rhtml
@@ -0,0 +1,11 @@
+<html>
+<head>
+ <title><%= controller_class_name %>: <%%= controller.action_name %></title>
+ <link href="/stylesheets/scaffold.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+
+<%%= @content_for_layout %>
+
+</body>
+</html>
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/style.css b/railties/lib/rails_generator/generators/components/scaffold/templates/style.css
new file mode 100644
index 0000000000..95a3c4668c
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/style.css
@@ -0,0 +1,53 @@
+body { background-color: #fff; color: #333; }
+
+body, p, ol, ul, td {
+ font-family: verdana, arial, helvetica, sans-serif;
+ font-size: 13px;
+ line-height: 18px;
+}
+
+pre {
+ background-color: #eee;
+ padding: 10px;
+ font-size: 11px;
+}
+
+a { color: #000; }
+a:visited { color: #666; }
+a:hover { color: #fff; background-color:#000; }
+
+.fieldWithErrors {
+ padding: 2px;
+ background-color: red;
+ display: table;
+}
+
+#ErrorExplanation {
+ width: 400px;
+ border: 2px solid #red;
+ padding: 7px;
+ padding-bottom: 12px;
+ margin-bottom: 20px;
+ background-color: #f0f0f0;
+}
+
+#ErrorExplanation h2 {
+ text-align: left;
+ font-weight: bold;
+ padding: 5px 5px 5px 15px;
+ font-size: 12px;
+ margin: -7px;
+ background-color: #c00;
+ color: #fff;
+}
+
+#ErrorExplanation p {
+ color: #333;
+ margin-bottom: 0;
+ padding: 5px;
+}
+
+#ErrorExplanation ul li {
+ font-size: 12px;
+ list-style: square;
+}
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/view_edit.rhtml b/railties/lib/rails_generator/generators/components/scaffold/templates/view_edit.rhtml
new file mode 100644
index 0000000000..4ad70f537a
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/view_edit.rhtml
@@ -0,0 +1,7 @@
+<h1>Editing <%= singular_name %></h1>
+
+<%%= error_messages_for '<%= singular_name %>' %>
+<%= template_for_inclusion %>
+
+<%%= link_to 'Show', :action => 'show<%= suffix %>', :id => @<%= singular_name %>.id %> |
+<%%= link_to 'Back', :action => 'list<%= suffix %>' %>
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml b/railties/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml
new file mode 100644
index 0000000000..068fd67472
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml
@@ -0,0 +1,24 @@
+<h1>Listing <%= plural_name %></h1>
+
+<table>
+ <tr>
+<%% for column in <%= class_name %>.content_columns %>
+ <th><%%= column.human_name %></th>
+<%% end %>
+ </tr>
+
+<%% for <%= singular_name %> in @<%= plural_name %> %>
+ <tr>
+ <%% for column in <%= class_name %>.content_columns %>
+ <td><%%=h <%= singular_name %>[column.name] %></td>
+ <%% end %>
+ <td><%%= link_to 'Show', :action => 'show<%= suffix %>', :id => <%= singular_name %>.id %></td>
+ <td><%%= link_to 'Edit', :action => 'edit<%= suffix %>', :id => <%= singular_name %>.id %></td>
+ <td><%%= link_to 'Destroy', :action => 'destroy<%= suffix %>', :id => <%= singular_name %>.id %></td>
+ </tr>
+<%% end %>
+</table>
+
+<br />
+
+<%%= link_to 'New <%= singular_name %>', :action => 'new<%= suffix %>' %>
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/view_new.rhtml b/railties/lib/rails_generator/generators/components/scaffold/templates/view_new.rhtml
new file mode 100644
index 0000000000..fcf5a3c54b
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/view_new.rhtml
@@ -0,0 +1,6 @@
+<h1>New <%= @singular_name %></h1>
+
+<%%= error_messages_for '<%= singular_name %>' %>
+<%= template_for_inclusion %>
+
+<%%= link_to 'Back', :action => 'list<%= suffix %>' %>
diff --git a/railties/lib/rails_generator/generators/components/scaffold/templates/view_show.rhtml b/railties/lib/rails_generator/generators/components/scaffold/templates/view_show.rhtml
new file mode 100644
index 0000000000..ba8f3616dd
--- /dev/null
+++ b/railties/lib/rails_generator/generators/components/scaffold/templates/view_show.rhtml
@@ -0,0 +1,8 @@
+<%% for column in <%= class_name %>.content_columns %>
+<p>
+ <b><%%= column.human_name %>:</b> <%%= @<%= singular_name %>.send(column.name) %>
+</p>
+<%% end %>
+
+<%%= link_to 'Edit', :action => 'edit<%= suffix %>', :id => @<%= singular_name %>.id %> |
+<%%= link_to 'Back', :action => 'list<%= suffix %>' %>