提交 2594581e 编写于 作者: D David Heinemeier Hansson

Added a better generator for scaffolding that actually creates the code, so it...

Added a better generator for scaffolding that actually creates the code, 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
上级 3ee4357b
......@@ -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
......
#!/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
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
class <%= class_name %>Controller < AbstractApplicationController
helper :<%= file_name %>
<% if options[:scaffold] -%>
model :<%= file_name %>
scaffold :<%= options[:scaffold] %>
<%- for action in actions -%>
#def <%= action %>
#end
scaffold :<%= singular_name %>
<% end -%>
<% for action in actions -%>
<%- end -%>
<% else -%>
<%- for action in actions -%>
def <%= action %>
end
<%- 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
......
<h1><%= class_name %>#<%= action %></h1>
<p>Find me in app/views/<%= file_name %>/<%= action %>.rhtml</p>
#!/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
#!/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
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
require 'action_mailer'
class <%= class_name %> < ActionMailer::Base
<% for action in actions -%>
def <%= action %>(sent_on = Time.now)
@recipients = ''
@from = ''
......@@ -10,6 +10,5 @@ def <%= action %>(sent_on = Time.now)
@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
......
#!/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
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
# 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
\ No newline at end of file
end
#!/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
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!
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
class <%= class_name %>Controller < AbstractApplicationController
model :<%= singular_name %>
layout 'scaffold'
<% 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'])
@<%= singular_name %>.attributes = @params['<%= singular_name %>']
if @<%= singular_name %>.save
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
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
first_<%= singular_name %>:
id: 1
another_<%= singular_name %>:
id: 2
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
fixtures :<%= table_name %>
def setup
@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_success
assert_rendered_file '<%= action %>'
end
<% end -%>
<% unless suffix -%>
def test_index
process :index
assert_success
assert_rendered_file 'list'
end
<% end -%>
def test_list<%= suffix %>
process :list<%= suffix %>
assert_success
assert_rendered_file 'list<%= suffix %>'
assert_template_has '<%= plural_name %>'
end
def test_show<%= suffix %>
process :show<%= suffix %>, 'id' => 1
assert_success
assert_rendered_file 'show'
assert_template_has '<%= singular_name %>'
assert_valid_record '<%= singular_name %>'
end
def test_show_missing_<%= suffix || 'record' %>
process :show<%= suffix %>
assert_success
assert_rendered_file 'error'
end
def test_new<%= suffix %>
process :new<%= suffix %>
assert_success
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' => 1
assert_success
assert_rendered_file 'edit<%= suffix %>'
assert_template_has '<%= singular_name %>'
assert_valid_record '<%= singular_name %>'
end
def test_edit_missing_<%= suffix || 'record' %>
process :edit<%= suffix %>
assert_success
assert_rendered_file 'error'
end
def test_update<%= suffix %>
process :update<%= suffix %>, 'id' => 1
assert_redirected_to :action => 'show<%= suffix %>', :id => 1
end
def test_update_missing_<%= suffix || 'record' %>
process :update<%= suffix %>, '<%= singular_name %>' => {}
assert_success
assert_rendered_file 'error'
end
def test_destroy<%= suffix %>
assert_not_nil <%= class_name %>.find(1)
process :destroy, 'id' => 1
assert_redirected_to :action => 'list<%= suffix %>'
assert_raise(ActiveRecord::RecordNotFound) {
<%= singular_name %> = <%= class_name %>.find(1)
}
end
def test_destroy_missing_<%= suffix || 'record' %>
process :destroy<%= suffix %>
assert_success
assert_rendered_file 'error'
end
end
<html>
<head>
<title>Scaffolding: <%%= controller.controller_name %>#<%%= controller.action_name %></title>
<link href="/stylesheets/scaffold.css" rel="stylesheet" type="text/css" />
</head>
<body>
<%%= @content_for_layout %>
</body>
</html>
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; }
<h1>Editing <%= singular_name %></h1>
<%%= form '<%= singular_name %>', :action => 'update<%= suffix %>' %>
<%%= link_to 'Show', :action => 'show<%= suffix %>', :id => @<%= singular_name %>.id %> |
<%%= link_to 'Back', :action => 'list<%= suffix %>' %>
<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 %>' %>
<h1>New <%= @singular_name %></h1>
<%%= form '<%= singular_name %>', :action => 'create<%= suffix %>' %>
<%%= link_to 'Back', :action => 'list<%= suffix %>' %>
<%% for column in <%= class_name %>.content_columns %>
<p>
<b><%%= column.human_name %>:</b> <%%= @<%= singular_name %>[column.name] %>
</p>
<%% end %>
<%%= link_to 'Edit', :action => 'edit<%= suffix %>', :id => @<%= singular_name %>.id %> |
<%%= link_to 'Back', :action => 'list<%= suffix %>' %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title><%= class_name %>#<%= action %></title>
</head>
<body>
<h1><%= class_name %>#<%= action %></h1>
<p>Find me in app/views/<%= file_name %>/<%= action %>.rhtml</p>
</body>
</html>
require 'fileutils'
module Rails
module Generator
class GeneratorError < StandardError; end
class UsageError < GeneratorError; end
CONTRIB_ROOT = "#{RAILS_ROOT}/script/generators"
BUILTIN_ROOT = "#{File.dirname(__FILE__)}/../generators"
DEFAULT_SEARCH_PATHS = [CONTRIB_ROOT, BUILTIN_ROOT]
class << self
def instance(name, args = [], search_paths = DEFAULT_SEARCH_PATHS)
# RAILS_ROOT constant must be set.
unless Object.const_get(:RAILS_ROOT)
raise GeneratorError, "RAILS_ROOT must be set. Did you require 'config/environment'?"
end
# Force canonical name.
name = Inflector.underscore(name.downcase)
# Search for filesystem path to requested generator.
unless path = find_generator_path(name, search_paths)
raise GeneratorError, "#{name} generator not found."
end
# Check for templates directory.
template_root = "#{path}/templates"
unless File.directory?(template_root)
raise GeneratorError, "missing template directory #{template_root}"
end
# Require class file according to naming convention.
require "#{path}/#{name}_generator.rb"
# Find class according to naming convention. Allow Nesting::In::Modules.
class_name = Inflector.classify("#{name}_generator")
unless klass = find_generator_class(name)
raise GeneratorError, "no #{class_name} class defined in #{path}/#{name}_generator.rb"
end
# Instantiate and return generator.
klass.new(template_root, RAILS_ROOT, search_paths, args)
end
def builtin_generators
generators([BUILTIN_ROOT])
end
def contrib_generators
generators([CONTRIB_ROOT])
end
def generators(search_paths)
generator_paths(search_paths).keys.uniq.sort
end
# Find all generator paths.
def generator_paths(search_paths)
@paths ||= {}
unless @paths[search_paths]
paths = Hash.new { |h,k| h[k] = [] }
search_paths.each do |path|
Dir["#{path}/[a-z]*"].each do |dir|
paths[File.basename(dir)] << dir if File.directory?(dir)
end
end
@paths[search_paths] = paths
end
@paths[search_paths]
end
def find_generator_path(name, search_paths)
generator_paths(search_paths)[name].first
end
# Find all generator classes.
def generator_classes
classes = Hash.new { |h,k| h[k] = [] }
class_re = /([^:]+)Generator$/
ObjectSpace.each_object(Class) do |object|
if md = class_re.match(object.name) and object < Rails::Generator::Base
classes[Inflector.underscore(md.captures.first)] << object
end
end
classes
end
def find_generator_class(name)
generator_classes[name].first
end
end
# Talk about generators.
class Base
attr_reader :template_root, :destination_root, :args, :options,
:class_name, :singular_name, :plural_name
alias_method :file_name, :singular_name
alias_method :table_name, :plural_name
def self.generator_name
Inflector.underscore(name.gsub('Generator', ''))
end
def initialize(template_root, destination_root, search_paths, args)
@template_root, @destination_root = template_root, destination_root
usage if args.empty?
@search_paths, @original_args = search_paths, args.dup
@class_name, @singular_name, @plural_name = inflect_names(args.shift)
@options = extract_options!(args)
@args = args
end
protected
# Look up another generator with the same arguments.
def generator(name)
Rails::Generator.instance(name, @original_args, @search_paths)
end
# Generate a file for a Rails application using an ERuby template.
# Looks up and evalutes a template by name and writes the result
# to a file relative to +destination_root+. The template
# is evaluated in the context of the optional eval_binding argument.
#
# The ERB template uses explicit trim mode to best control the
# proliferation of whitespace in generated code. <%- trims leading
# whitespace; -%> trims trailing whitespace including one newline.
def template(template_name, destination_path, eval_binding = nil)
# Determine full paths for source and destination files.
template_path = find_template_path(template_name)
destination_path = File.join(destination_root, destination_path)
# Create destination directories.
FileUtils.mkdir_p(File.dirname(destination_path))
# Render template and write result.
eval_binding ||= binding
contents = ERB.new(File.read(template_path), nil, '-').result(eval_binding)
File.open(destination_path, 'w') { |file| file.write(contents) }
end
def usage
raise UsageError.new, File.read(usage_path)
end
private
def find_template_path(template_name)
name, path = template_name.split('/', 2)
if path.nil?
File.join(template_root, name)
elsif generator_path = Rails::Generator.find_generator_path(name, @search_paths)
File.join(generator_path, 'templates', path)
end
end
def inflect_names(name)
camel = Inflector.camelize(Inflector.underscore(name))
under = Inflector.underscore(camel)
plural = Inflector.pluralize(under)
[camel, under, plural]
end
def extract_options!(args)
if args.last.is_a?(Hash) then args.pop else {} end
end
def usage_path
"#{template_root}/../USAGE"
end
end
end
end
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
RAILS_ROOT = File.dirname(__FILE__)
require File.dirname(__FILE__) + '/../../activerecord/lib/active_record/support/inflector'
require 'rails_generator'
require 'test/unit'
class RailsGeneratorTest < Test::Unit::TestCase
BUILTINS = %w(controller mailer model scaffold)
def test_instance_builtins
BUILTINS.each do |name|
object = nil
assert_nothing_raised { object = Rails::Generator.instance(name, ['foo']) }
assert_not_nil object
assert_match /#{name.capitalize}Generator/, object.class.name
assert_respond_to object, :generate
end
end
def test_instance_without_rails_root
old_verbose, $VERBOSE = $VERBOSE, nil
old_rails_root = Object.const_get(:RAILS_ROOT)
begin
Object.const_set(:RAILS_ROOT, nil)
assert_raise(Rails::Generator::GeneratorError) {
Rails::Generator.instance('model', ['name'])
}
ensure
Object.const_set(:RAILS_ROOT, old_rails_root)
$VERBOSE = old_verbose
end
end
def test_instance_not_found
assert_raise(Rails::Generator::GeneratorError) {
Rails::Generator.instance('foobar')
}
end
def test_instance_missing_templates
assert_raise(Rails::Generator::GeneratorError) {
Rails::Generator.instance('missing_templates')
}
end
def test_instance_missing_generator
assert_raise(LoadError) {
Rails::Generator.instance('missing_generator')
}
end
def test_instance_missing_class
assert_raise(Rails::Generator::GeneratorError) {
Rails::Generator.instance('missing_class')
}
end
def test_builtin_generators
assert_nothing_raised {
assert_equal [], Rails::Generator.builtin_generators - BUILTINS
}
end
def test_generator_name
assert_equal 'model', Rails::Generator.instance('model', ['name']).class.generator_name
end
def test_generator_usage
assert_raise(Rails::Generator::UsageError) {
assert_equal 'model', Rails::Generator.instance('model')
}
end
def test_generator_vars
model = Rails::Generator.instance('model', ['model'])
assert_equal "#{Rails::Generator::BUILTIN_ROOT}/model/templates", model.template_root
assert_equal RAILS_ROOT, model.destination_root
assert_equal 'Model', model.class_name
assert_equal 'model', model.singular_name
assert_equal 'models', model.plural_name
assert_equal model.singular_name, model.file_name
assert_equal model.plural_name, model.table_name
assert_equal [], model.args
end
def test_generator_generator
assert_nothing_raised {
model = Rails::Generator.instance('model', ['name'])
mailer = model.send(:generator, 'mailer')
assert_equal 'mailer', mailer.class.generator_name
}
end
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册