Permalink
Browse files

Added a better generator for scaffolding that actually creates the co…

…de, so it can be edited bit by bit. See "script/generate scaffold" [bitsweat]. Added a whole new approach to generators that used the shared "script/generate" command. Run with no-args to see help [bitsweat].

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@63 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
dhh committed Dec 7, 2004
1 parent 3ee4357 commit 2594581e9f5594b32918326be895b4d443ab3e9c
Showing with 706 additions and 112 deletions.
  1. +7 −1 railties/Rakefile
  2. +0 −14 railties/generators/{new_controller.rb → controller/USAGE}
  3. +22 −0 railties/generators/controller/controller_generator.rb
  4. +10 −0 railties/generators/controller/templates/controller.rb
  5. +1 −1 railties/generators/{templates/controller_test.erb → controller/templates/functional_test.rb}
  6. 0 railties/generators/{templates/helper.erb → controller/templates/helper.rb}
  7. +2 −0 railties/generators/controller/templates/view.rhtml
  8. +41 −0 railties/generators/generate.rb
  9. +0 −14 railties/generators/{new_mailer.rb → mailer/USAGE}
  10. +22 −0 railties/generators/mailer/mailer_generator.rb
  11. 0 railties/generators/{templates/mailer_fixture.rhtml → mailer/templates/fixture.rhtml}
  12. +1 −2 railties/generators/{templates/mailer.erb → mailer/templates/mailer.rb}
  13. +1 −1 railties/generators/{templates/mailer_test.erb → mailer/templates/unit_test.rb}
  14. 0 railties/generators/{templates/mailer_action.rhtml → mailer/templates/view.rhtml}
  15. +0 −14 railties/generators/{new_model.rb → model/USAGE}
  16. +10 −0 railties/generators/model/model_generator.rb
  17. +1 −0 railties/generators/model/templates/fixtures.yml
  18. 0 railties/generators/{templates/model.erb → model/templates/model.rb}
  19. +2 −2 railties/generators/{templates/model_test.erb → model/templates/unit_test.rb}
  20. +0 −34 railties/generators/new_crud.rb
  21. +18 −0 railties/generators/scaffold/USAGE
  22. +53 −0 railties/generators/scaffold/scaffold_generator.rb
  23. +58 −0 railties/generators/scaffold/templates/controller.rb
  24. +7 −0 railties/generators/scaffold/templates/fixtures.yml
  25. +109 −0 railties/generators/scaffold/templates/functional_test.rb
  26. +11 −0 railties/generators/scaffold/templates/layout.rhtml
  27. +17 −0 railties/generators/scaffold/templates/style.css
  28. +6 −0 railties/generators/scaffold/templates/view_edit.rhtml
  29. +24 −0 railties/generators/scaffold/templates/view_list.rhtml
  30. +5 −0 railties/generators/scaffold/templates/view_new.rhtml
  31. +8 −0 railties/generators/scaffold/templates/view_show.rhtml
  32. +0 −19 railties/generators/templates/controller.erb
  33. +0 −10 railties/generators/templates/controller_view.rhtml
  34. +175 −0 railties/lib/rails_generator.rb
  35. 0 railties/test/generators/missing_class/missing_class_generator.rb
  36. +95 −0 railties/test/rails_generator_test.rb
View
@@ -21,7 +21,8 @@ TEST_DIRS = %w( fixtures unit functional mocks mocks/development mocks/testing
LOG_FILES = %w( apache.log development.log test.log production.log )
HTML_FILES = %w( 404.html 500.html index.html )
-SCRIPT_FILES = %w( new_controller new_model new_mailer new_crud )
+SCRIPT_FILES = %w( generate )
+GENERATORS = %w( controller mailer model scaffold )
VENDOR_LIBS = %w( actionpack activerecord actionmailer railties )
@@ -136,11 +137,16 @@ task :copy_configs do
end
task :copy_generators do
+ mkdir_p File.join(PKG_DESTINATION, 'script')
SCRIPT_FILES.each do |file|
dest_file = File.join(PKG_DESTINATION, 'script', file)
cp File.join('generators', "#{file}.rb"), dest_file
chmod 0755, dest_file
end
+
+ GENERATORS.each do |dir|
+ cp_r File.join('generators', dir), File.join(PKG_DESTINATION, 'script', dir)
+ end
end
task :copy_rootfiles do
@@ -1,15 +1,3 @@
-#!/usr/local/bin/ruby
-require File.dirname(__FILE__) + '/../config/environment'
-require 'generator'
-
-unless ARGV.empty?
- rails_root = File.dirname(__FILE__) + '/..'
- name = ARGV.shift
- actions = ARGV
- Generator::Controller.new(rails_root, name, actions).generate
-else
- puts <<-END_HELP
-
NAME
new_controller - create controller and view stub files
@@ -39,5 +27,3 @@
The BlogController class will have the following methods: list, display, new, edit.
Each will default to render the associated template file.
-END_HELP
-end
@@ -0,0 +1,22 @@
+require 'rails_generator'
+
+class ControllerGenerator < Rails::Generator::Base
+ attr_reader :actions
+
+ def generate
+ @actions = args
+
+ # Controller class, functional test, and helper class.
+ template "controller.rb", "app/controllers/#{file_name}_controller.rb"
+ template "functional_test.rb", "test/functional/#{file_name}_controller_test.rb"
+ template "helper.rb", "app/helpers/#{file_name}_helper.rb"
+
+ # Create the views directory even if there are no actions.
+ FileUtils.mkdir_p "app/views/#{file_name}"
+
+ # Create a view for each action.
+ actions.each do |action|
+ template "view.rhtml", "app/views/#{file_name}/#{action}.rhtml", binding
+ end
+ end
+end
@@ -0,0 +1,10 @@
+class <%= class_name %>Controller < AbstractApplicationController
+<% if options[:scaffold] -%>
+ scaffold :<%= singular_name %>
+<% end -%>
+<% for action in actions -%>
+
+ def <%= action %>
+ end
+<% end -%>
+end
@@ -10,7 +10,7 @@ def setup
@request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
end
- # Replace this with your real tests
+ # Replace this with your real tests.
def test_truth
assert true
end
@@ -0,0 +1,2 @@
+<h1><%= class_name %>#<%= action %></h1>
+<p>Find me in app/views/<%= file_name %>/<%= action %>.rhtml</p>
@@ -0,0 +1,41 @@
+#!/usr/local/bin/ruby
+require File.dirname(__FILE__) + '/../config/environment'
+require 'rails_generator'
+
+unless ARGV.empty?
+ begin
+ name = ARGV.shift
+ Rails::Generator.instance(name, ARGV).generate
+ rescue Rails::Generator::UsageError => e
+ puts e.message
+ end
+else
+ builtin_generators = Rails::Generator.builtin_generators.join(', ')
+ contrib_generators = Rails::Generator.contrib_generators.join(', ')
+
+ $stderr.puts <<end_usage
+ #{$0} generator [args]
+
+ Rails comes with #{builtin_generators} generators.
+ #{$0} controller Login login logout
+ #{$0} model Account
+ #{$0} mailer AccountMailer
+ #{$0} scaffold Account action another_action
+
+end_usage
+
+ unless contrib_generators.empty?
+ $stderr.puts " Installed generators (in #{RAILS_ROOT}/generators):"
+ $stderr.puts " #{contrib_generators}"
+ $stderr.puts
+ end
+
+ $stderr.puts <<end_usage
+ More generators are available at http://rubyonrails.org
+ 1. Download, for example, auth_controller.zip
+ 2. Unzip to directory #{RAILS_ROOT}/generators/auth_controller
+ 3. Generate without args for usage information
+ #{$0} auth_controller
+end_usage
+ exit 0
+end
@@ -1,15 +1,3 @@
-#!/usr/local/bin/ruby
-require File.dirname(__FILE__) + '/../config/environment'
-require 'generator'
-
-unless ARGV.empty?
- rails_root = File.dirname(__FILE__) + '/..'
- name = ARGV.shift
- actions = ARGV
- Generator::Mailer.new(rails_root, name, actions).generate
-else
- puts <<-END_HELP
-
NAME
new_mailer - create mailer and view stub files
@@ -39,5 +27,3 @@
The Notifications class will have the following methods: signup,
forgot_password, and invoice.
-END_HELP
-end
@@ -0,0 +1,22 @@
+require 'rails_generator'
+
+class MailerGenerator < Rails::Generator::Base
+ attr_reader :actions
+
+ def generate
+ @actions = args
+
+ # Mailer class and unit test.
+ template "mailer.rb", "app/models/#{file_name}.rb"
+ template "unit_test.rb", "test/unit/#{file_name}_test.rb"
+
+ # Test fixtures directory.
+ FileUtils.mkdir_p "test/fixtures/#{table_name}"
+
+ # View template and fixture for each action.
+ args.each do |action|
+ template "view.rhtml", "app/views/#{file_name}/#{action}.rhtml", binding
+ template "fixture.rhtml", "test/fixtures/#{table_name}/#{action}", binding
+ end
+ end
+end
@@ -1,15 +1,14 @@
require 'action_mailer'
class <%= class_name %> < ActionMailer::Base
-
<% for action in actions -%>
+
def <%= action %>(sent_on = Time.now)
@recipients = ''
@from = ''
@subject = ''
@body = {}
@sent_on = sent_on
end
-
<% end -%>
end
@@ -12,11 +12,11 @@ def setup
@expected = TMail::Mail.new
@expected.to = 'test@localhost'
@expected.from = 'test@localhost'
- @expected.subject = '<%= class_name %> test mail'
end
<% for action in actions -%>
def test_<%= action %>
+ @expected.subject = '<%= class_name %>#<%= action %> test mail'
@expected.body = read_fixture('<%= action %>')
@expected.date = Time.now
@@ -1,14 +1,3 @@
-#!/usr/local/bin/ruby
-require File.dirname(__FILE__) + '/../config/environment'
-require 'generator'
-
-if ARGV.size == 1
- rails_root = File.dirname(__FILE__) + '/..'
- name = ARGV.shift
- Generator::Model.new(rails_root, name).generate
-else
- puts <<-HELP
-
NAME
new_model - create model stub files
@@ -26,6 +15,3 @@
This will generate an Account class in app/models/account.rb, an
AccountTest in test/unit/account_test.rb, and the directory
test/fixtures/account.
-
-HELP
-end
@@ -0,0 +1,10 @@
+require 'rails_generator'
+
+class ModelGenerator < Rails::Generator::Base
+ def generate
+ # Model class, unit test, and fixtures.
+ template "model.rb", "app/models/#{file_name}.rb"
+ template "unit_test.rb", "test/unit/#{file_name}_test.rb"
+ template "fixtures.yml", "test/fixtures/#{table_name}.yml"
+ end
+end
@@ -0,0 +1 @@
+# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
@@ -4,8 +4,8 @@
class <%= class_name %>Test < Test::Unit::TestCase
fixtures :<%= table_name %>
- # Replace this with your real tests
+ # Replace this with your real tests.
def test_truth
assert true
end
-end
+end
@@ -1,34 +0,0 @@
-#!/usr/local/bin/ruby
-require File.dirname(__FILE__) + '/../config/environment'
-require 'generator'
-
-unless ARGV.empty?
- rails_root = File.dirname(__FILE__) + '/..'
- name = ARGV.shift
- actions = ARGV
- Generator::Model.new(rails_root, name).generate
- Generator::Controller.new(rails_root, name, actions, :scaffold => true).generate
-else
- puts <<-END_HELP
-
-NAME
- new_crud - create a model and a controller scaffold
-
-SYNOPSIS
- new_crud ModelName [action ...]
-
-DESCRIPTION
- The new_crud generator takes the name of the new model as the
- first argument and an optional list of controller actions as the
- subsequent arguments. All actions may be omitted since the controller
- will have scaffolding automatically set up for this model.
-
-EXAMPLE
- new_crud Account
-
- This will generate an Account model and controller with scaffolding.
- Now create the accounts table in your database and browse to
- http://localhost/account/ -- voila, you're on Rails!
-
-END_HELP
-end
@@ -0,0 +1,18 @@
+NAME
+ new_scaffold - create a model and a skeleton controller
+
+SYNOPSIS
+ new_scaffold ModelName [action ...]
+
+DESCRIPTION
+ The new_scaffold generator takes the name of the new model as the
+ first argument and an optional list of controller actions as the
+ subsequent arguments. Any actions with scaffolding code available
+ will be generated in your controller; others will be left as stubs.
+
+EXAMPLE
+ new_scaffold Account
+
+ This will generate an Account model and controller.
+ Now create the accounts table in your database and browse to
+ http://localhost/account/ -- voila, you're on Rails!
@@ -0,0 +1,53 @@
+require 'rails_generator'
+
+class ScaffoldGenerator < Rails::Generator::Base
+ def generate
+ # Model.
+ generator('model').generate
+
+ # Fixtures.
+ template "fixtures.yml", "test/fixtures/#{table_name}.yml"
+
+ # Controller class, functional test, helper, and views.
+ template "controller.rb", "app/controllers/#{file_name}_controller.rb"
+ template "functional_test.rb", "test/functional/#{file_name}_controller_test.rb"
+ template "controller/helper.rb", "app/helpers/#{file_name}_helper.rb"
+
+ # Layout and stylesheet.
+ unless File.file?("app/views/layouts/scaffold.rhtml")
+ template "layout.rhtml", "app/views/layouts/scaffold.rhtml"
+ end
+ unless File.file?("public/stylesheets/scaffold.css")
+ template "style.css", "public/stylesheets/scaffold.css"
+ end
+
+ # Scaffolded views.
+ scaffold_views.each do |action|
+ template "view_#{action}.rhtml", "app/views/#{file_name}/#{action}.rhtml"
+ end
+
+ # Unscaffolded views.
+ unscaffolded_actions.each do |action|
+ template "controller/view.rhtml",
+ "app/views/#{file_name}/#{action}.rhtml",
+ binding
+ end
+ end
+
+ protected
+ def scaffold_views
+ %w(list show 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
+end
Oops, something went wrong.

0 comments on commit 2594581

Please sign in to comment.