提交 ea0b0c82 编写于 作者: J José Valim

rm -rf rails_generator/generators

上级 c972b25d
Description:
Stubs out a new controller and its views. Pass the controller name, either
CamelCased or under_scored, and a list of views as arguments.
To create a controller within a module, specify the controller name as a
path like 'parent_module/controller_name'.
This generates a controller class in app/controllers, view templates in
app/views/controller_name, a helper class in app/helpers, a functional
test suite in test/functional and a helper test suite in test/unit/helpers.
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
Functional Test: test/functional/credit_card_controller_test.rb
Views: app/views/credit_card/debit.html.erb [...]
Helper: app/helpers/credit_card_helper.rb
Helper Test: test/unit/helpers/credit_card_helper_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
Functional Test: test/functional/admin/credit_card_controller_test.rb
Views: app/views/admin/credit_card/debit.html.erb [...]
Helper: app/helpers/admin/credit_card_helper.rb
Helper Test: test/unit/helpers/admin/credit_card_helper_test.rb
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", "#{class_name}HelperTest"
# Controller, helper, views, and test directories.
m.directory File.join('app/controllers', class_path)
m.directory File.join('app/helpers', class_path)
m.directory File.join('app/views', class_path, file_name)
m.directory File.join('test/functional', class_path)
m.directory File.join('test/unit/helpers', class_path)
# 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")
m.template 'helper_test.rb',
File.join('test/unit/helpers',
class_path,
"#{file_name}_helper_test.rb")
# View template for each action.
actions.each do |action|
path = File.join('app/views', class_path, file_name, "#{action}.html.erb")
m.template 'view.html.erb', path,
:assigns => { :action => action, :path => path }
end
end
end
end
class <%= class_name %>Controller < ApplicationController
<% for action in actions -%>
def <%= action %>
end
<% end -%>
end
require 'test_helper'
class <%= class_name %>ControllerTest < ActionController::TestCase
# Replace this with your real tests.
test "the truth" do
assert true
end
end
require 'test_helper'
class <%= class_name %>HelperTest < ActionView::TestCase
end
<h1><%= class_name %>#<%= action %></h1>
<p>Find me in <%= path %></p>
Description:
Stubs out a new helper. Pass the helper name, either
CamelCased or under_scored.
To create a helper within a module, specify the helper name as a
path like 'parent_module/helper_name'.
This generates a helper class in app/helpers and a helper test
suite in test/unit/helpers.
Example:
`./script/generate helper CreditCard`
Credit card helper.
Helper: app/helpers/credit_card_helper.rb
Test: test/unit/helpers/credit_card_helper_test.rb
Modules Example:
`./script/generate helper 'admin/credit_card'`
Credit card admin helper.
Helper: app/helpers/admin/credit_card_helper.rb
Test: test/unit/helpers/admin/credit_card_helper_test.rb
class HelperGenerator < Rails::Generator::NamedBase
def manifest
record do |m|
# Check for class naming collisions.
m.class_collisions class_path, "#{class_name}Helper", "#{class_name}HelperTest"
# Helper and helper test directories.
m.directory File.join('app/helpers', class_path)
m.directory File.join('test/unit/helpers', class_path)
# Helper and helper test class.
m.template 'helper.rb',
File.join('app/helpers',
class_path,
"#{file_name}_helper.rb")
m.template 'helper_test.rb',
File.join('test/unit/helpers',
class_path,
"#{file_name}_helper_test.rb")
end
end
end
require 'test_helper'
class <%= class_name %>HelperTest < ActionView::TestCase
end
Description:
Stubs out a new integration test. Pass the name of the test, either
CamelCased or under_scored, as an argument. The new test class is
generated in test/integration/testname_test.rb
Example:
`./script/generate integration_test GeneralStories` creates a GeneralStories
integration test in test/integration/general_stories_test.rb
class IntegrationTestGenerator < Rails::Generator::NamedBase
default_options :skip_migration => false
def manifest
record do |m|
# Check for class naming collisions.
m.class_collisions class_name, "#{class_name}Test"
# integration test directory
m.directory File.join('test/integration', class_path)
# integration test stub
m.template 'integration_test.rb', File.join('test/integration', class_path, "#{file_name}_test.rb")
end
end
end
require 'test_helper'
class <%= class_name %>Test < ActionController::IntegrationTest
fixtures :all
# Replace this with your real tests.
test "the truth" do
assert true
end
end
Description:
Stubs out a new mailer and its views. Pass the mailer name, either
CamelCased or under_scored, and an optional list of emails as arguments.
This generates a mailer class in app/models, view templates in
app/views/mailer_name, a unit test in test/unit, and fixtures in
test/fixtures.
Example:
`./script/generate mailer Notifications signup forgot_password invoice`
creates a Notifications mailer class, views, test, and fixtures:
Mailer: app/models/notifications.rb
Views: app/views/notifications/signup.erb [...]
Test: test/unit/test/unit/notifications_test.rb
Fixtures: test/fixtures/notifications/signup [...]
class MailerGenerator < Rails::Generator::NamedBase
def manifest
record do |m|
# Check for class naming collisions.
m.class_collisions class_name, "#{class_name}Test"
# Mailer, view, test, and fixture directories.
m.directory File.join('app/models', class_path)
m.directory File.join('app/views', file_path)
m.directory File.join('test/unit', class_path)
m.directory File.join('test/fixtures', file_path)
# Mailer class and unit test.
m.template "mailer.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")
# View template and fixture for each action.
actions.each do |action|
relative_path = File.join(file_path, action)
view_path = File.join('app/views', "#{relative_path}.erb")
fixture_path = File.join('test/fixtures', relative_path)
m.template "view.erb", view_path,
:assigns => { :action => action, :path => view_path }
m.template "fixture.erb", fixture_path,
:assigns => { :action => action, :path => view_path }
end
end
end
end
class <%= class_name %> < ActionMailer::Base
<% for action in actions -%>
def <%= action %>(sent_at = Time.now)
subject '<%= class_name %>#<%= action %>'
recipients ''
from ''
sent_on sent_at
body :greeting => 'Hi,'
end
<% end -%>
end
require 'test_helper'
class <%= class_name %>Test < ActionMailer::TestCase
<% for action in actions -%>
test "<%= action %>" do
@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 -%>
<% if actions.blank? -%>
# replace this with your real tests
test "the truth" do
assert true
end
<% end -%>
end
Description:
Cast some metal!
Examples:
`./script/generate metal poller`
This will create:
Metal: app/metal/poller.rb
class MetalGenerator < Rails::Generator::NamedBase
def manifest
record do |m|
m.directory 'app/metal'
m.template 'metal.rb', File.join('app/metal', "#{file_name}.rb")
end
end
end
# Allow the metal piece to run in isolation
require(File.dirname(__FILE__) + "/../../config/environment") unless defined?(Rails)
class <%= class_name %>
def self.call(env)
if env["PATH_INFO"] =~ /^\/<%= file_name %>/
[200, {"Content-Type" => "text/html"}, ["Hello, World!"]]
else
[404, {"Content-Type" => "text/html"}, ["Not Found"]]
end
end
end
Description:
Stubs out a new database migration. Pass the migration name, either
CamelCased or under_scored, and an optional list of attribute pairs as arguments.
A migration class is generated in db/migrate prefixed by a timestamp of the current date and time.
You can name your migration in either of these formats to generate add/remove
column lines from supplied attributes: AddColumnsToTable or RemoveColumnsFromTable
Example:
`./script/generate migration AddSslFlag`
If the current date is May 14, 2008 and the current time 09:09:12, this creates the AddSslFlag migration
db/migrate/20080514090912_add_ssl_flag.rb
`./script/generate migration AddTitleBodyToPost title:string body:text published:boolean`
This will create the AddTitleBodyToPost in db/migrate/20080514090912_add_title_body_to_post.rb with
this in the Up migration:
add_column :posts, :title, :string
add_column :posts, :body, :text
add_column :posts, :published, :boolean
And this in the Down migration:
remove_column :posts, :published
remove_column :posts, :body
remove_column :posts, :title
class MigrationGenerator < Rails::Generator::NamedBase
def manifest
record do |m|
m.migration_template 'migration.rb', 'db/migrate', :assigns => get_local_assigns
end
end
private
def get_local_assigns
returning(assigns = {}) do
if class_name.underscore =~ /^(add|remove)_.*_(?:to|from)_(.*)/
assigns[:migration_action] = $1
assigns[:table_name] = $2.pluralize
else
assigns[:attributes] = []
end
end
end
end
class <%= class_name.underscore.camelize %> < ActiveRecord::Migration
def self.up<% attributes.each do |attribute| %>
<%= migration_action %>_column :<%= table_name %>, :<%= attribute.name %><% if migration_action == 'add' %>, :<%= attribute.type %><% end -%>
<%- end %>
end
def self.down<% attributes.reverse.each do |attribute| %>
<%= migration_action == 'add' ? 'remove' : 'add' %>_column :<%= table_name %>, :<%= attribute.name %><% if migration_action == 'remove' %>, :<%= attribute.type %><% end -%>
<%- end %>
end
end
Description:
Stubs out a new model. Pass the model name, either CamelCased or
under_scored, and an optional list of attribute pairs as arguments.
Attribute pairs are column_name:sql_type arguments specifying the
model's attributes. Timestamps are added by default, so you don't have to
specify them by hand as 'created_at:datetime updated_at:datetime'.
You don't have to think up every attribute up front, but it helps to
sketch out a few so you can start working with the model immediately.
This generates a model class in app/models, a unit test in test/unit,
a test fixture in test/fixtures/singular_name.yml, and a migration in
db/migrate.
Examples:
`./script/generate model account`
creates an Account model, test, fixture, and migration:
Model: app/models/account.rb
Test: test/unit/account_test.rb
Fixtures: test/fixtures/accounts.yml
Migration: db/migrate/XXX_add_accounts.rb
`./script/generate model post title:string body:text published:boolean`
creates a Post model with a string title, text body, and published flag.
class ModelGenerator < Rails::Generator::NamedBase
default_options :skip_timestamps => false, :skip_migration => false, :skip_fixture => false
def manifest
record do |m|
# Check for class naming collisions.
m.class_collisions class_name, "#{class_name}Test"
# Model, test, and fixture directories.
m.directory File.join('app/models', class_path)
m.directory File.join('test/unit', class_path)
m.directory File.join('test/fixtures', class_path)
# 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")
unless options[:skip_fixture]
m.template 'fixtures.yml', File.join('test/fixtures', "#{table_name}.yml")
end
unless options[:skip_migration]
m.migration_template 'migration.rb', 'db/migrate', :assigns => {
:migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}"
}, :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}"
end
end
end
protected
def banner
"Usage: #{$0} #{spec.name} 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 }
opt.on("--skip-fixture",
"Don't generation a fixture file for this model") { |v| options[:skip_fixture] = v}
end
end
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
<% unless attributes.empty? -%>
one:
<% for attribute in attributes -%>
<%= attribute.name %>: <%= attribute.default %>
<% end -%>
two:
<% for attribute in attributes -%>
<%= attribute.name %>: <%= attribute.default %>
<% end -%>
<% else -%>
# one:
# column: value
#
# two:
# column: value
<% end -%>
class <%= migration_name %> < ActiveRecord::Migration
def self.up
create_table :<%= table_name %> do |t|
<% for attribute in attributes -%>
t.<%= attribute.type %> :<%= attribute.name %>
<% end -%>
<% unless options[:skip_timestamps] %>
t.timestamps
<% end -%>
end
end
def self.down
drop_table :<%= table_name %>
end
end
class <%= class_name %> < ActiveRecord::Base
<% attributes.select {|attr| attr.reference? }.each do |attribute| -%>
belongs_to :<%= attribute.name %>
<% end -%>
end
require 'test_helper'
class <%= class_name %>Test < ActiveSupport::TestCase
# Replace this with your real tests.
test "the truth" do
assert true
end
end
Description:
Create a model subclass of parent, used for Single Table Inheritance.
Both subclass and parent name can be either CamelCased or under_scored.
This generates a model class in app/models and a unit test in test/unit.
Examples:
`./script/generate model_subclass admin user`
creates an Admin model, which will inheritate from User model, test:
Model: app/models/admin.rb
Test: test/unit/admin_test.rb
class ModelSubclassGenerator < Rails::Generator::NamedBase
default_options :skip_unit_test => false
def manifest
record do |m|
# Check for class naming collisions.
m.class_collisions class_name, "#{class_name}Test"
# Model and test directories.
m.directory File.join('app/models', class_path)
m.directory File.join('test/unit', class_path)
# Model class and unit test
m.template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb"), :assigns => assigns
m.template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb"), :assigns => assigns
end
end
protected
def banner
"Usage: #{$0} #{spec.name} Subclass Parent"
end
def assigns
{:parent_class_name => parent_class_name}
end
def parent_class_name
@args.first.try(:camelize) || usage
end
end
class <%= class_name %> < <%= parent_class_name %>
end
\ No newline at end of file
require 'test_helper'
class <%= class_name %>Test < ActiveSupport::TestCase
# Replace this with your real tests.
test "the truth" do
assert true
end
end
Description:
Stubs out a new observer. Pass the observer name, either CamelCased or
under_scored, as an argument.
The generator creates an observer class in app/models and a unit test in
test/unit.
Example:
`./script/generate observer Account`
creates an Account observer and unit test:
Observer: app/models/account_observer.rb
Test: test/unit/account_observer_test.rb
class ObserverGenerator < Rails::Generator::NamedBase
def manifest
record do |m|
# Check for class naming collisions.
m.class_collisions "#{class_name}Observer", "#{class_name}ObserverTest"
# Observer, and test directories.
m.directory File.join('app/models', class_path)
m.directory File.join('test/unit', class_path)
# Observer class and unit test fixtures.
m.template 'observer.rb', File.join('app/models', class_path, "#{file_name}_observer.rb")
m.template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_observer_test.rb")
end
end
end
require 'test_helper'
class <%= class_name %>ObserverTest < ActiveSupport::TestCase
# Replace this with your real tests.
test "the truth" do
assert true
end
end
Description:
Stubs out a new performance test. Pass the name of the test, either
CamelCased or under_scored, as an argument. The new test class is
generated in test/performance/testname_test.rb
Example:
`./script/generate performance_test GeneralStories` creates a GeneralStories
performance test in test/performance/general_stories_test.rb
class PerformanceTestGenerator < Rails::Generator::NamedBase
default_options :skip_migration => false
def manifest
record do |m|
# Check for class naming collisions.
m.class_collisions class_name, "#{class_name}Test"
# performance test directory
m.directory File.join('test/performance', class_path)
# performance test stub
m.template 'performance_test.rb', File.join('test/performance', class_path, "#{file_name}_test.rb")
end
end
end
require 'test_helper'
require 'performance_test_help'
class <%= class_name %>Test < ActionController::PerformanceTest
# Replace this with your real tests.
def test_homepage
get '/'
end
end
Description:
Stubs out a new plugin. Pass the plugin name, either CamelCased or
under_scored, as an argument. Pass --with-generator to add an example
generator also.
This creates a plugin in vendor/plugins including an init.rb and README
as well as standard lib, task, and test directories.
Example:
`./script/generate plugin BrowserFilters`
creates a standard browser_filters plugin:
vendor/plugins/browser_filters/README
vendor/plugins/browser_filters/init.rb
vendor/plugins/browser_filters/install.rb
vendor/plugins/browser_filters/lib/browser_filters.rb
vendor/plugins/browser_filters/test/browser_filters_test.rb
vendor/plugins/browser_filters/tasks/browser_filters_tasks.rake
./script/generate plugin BrowserFilters --with-generator
creates a browser_filters generator also:
vendor/plugins/browser_filters/generators/browser_filters/browser_filters_generator.rb
vendor/plugins/browser_filters/generators/browser_filters/USAGE
vendor/plugins/browser_filters/generators/browser_filters/templates/
class PluginGenerator < Rails::Generator::NamedBase
attr_reader :plugin_path
def initialize(runtime_args, runtime_options = {})
@with_generator = runtime_args.delete("--with-generator")
super
@plugin_path = "vendor/plugins/#{file_name}"
end
def manifest
record do |m|
# Check for class naming collisions.
m.class_collisions class_name
m.directory "#{plugin_path}/lib"
m.directory "#{plugin_path}/tasks"
m.directory "#{plugin_path}/test"
m.template 'README', "#{plugin_path}/README"
m.template 'MIT-LICENSE', "#{plugin_path}/MIT-LICENSE"
m.template 'Rakefile', "#{plugin_path}/Rakefile"
m.template 'init.rb', "#{plugin_path}/init.rb"
m.template 'install.rb', "#{plugin_path}/install.rb"
m.template 'uninstall.rb', "#{plugin_path}/uninstall.rb"
m.template 'plugin.rb', "#{plugin_path}/lib/#{file_name}.rb"
m.template 'tasks.rake', "#{plugin_path}/tasks/#{file_name}_tasks.rake"
m.template 'unit_test.rb', "#{plugin_path}/test/#{file_name}_test.rb"
m.template 'test_helper.rb', "#{plugin_path}/test/test_helper.rb"
if @with_generator
m.directory "#{plugin_path}/generators"
m.directory "#{plugin_path}/generators/#{file_name}"
m.directory "#{plugin_path}/generators/#{file_name}/templates"
m.template 'generator.rb', "#{plugin_path}/generators/#{file_name}/#{file_name}_generator.rb"
m.template 'USAGE', "#{plugin_path}/generators/#{file_name}/USAGE"
end
end
end
end
Copyright (c) <%= Date.today.year %> [name of plugin creator]
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<%= class_name %>
<%= "=" * class_name.size %>
Introduction goes here.
Example
=======
Example goes here.
Copyright (c) <%= Date.today.year %> [name of plugin creator], released under the MIT license
require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'
desc 'Default: run unit tests.'
task :default => :test
desc 'Test the <%= file_name %> plugin.'
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
t.verbose = true
end
desc 'Generate documentation for the <%= file_name %> plugin.'
Rake::RDocTask.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = '<%= class_name %>'
rdoc.options << '--line-numbers' << '--inline-source'
rdoc.rdoc_files.include('README')
rdoc.rdoc_files.include('lib/**/*.rb')
end
Description:
Explain the generator
Example:
./script/generate <%= file_name %> Thing
This will create:
what/will/it/create
class <%= class_name %>Generator < Rails::Generator::NamedBase
def manifest
record do |m|
# m.directory "lib"
# m.template 'README', "README"
end
end
end
# desc "Explaining what the task does"
# task :<%= file_name %> do
# # Task goes here
# end
require 'rubygems'
require 'active_support'
require 'active_support/test_case'
\ No newline at end of file
require 'test_helper'
class <%= class_name %>Test < ActiveSupport::TestCase
# Replace this with your real tests.
test "the truth" do
assert true
end
end
Description:
Stubs out a new resource including an empty model and controller suitable
for a restful, resource-oriented application. Pass the singular model name,
either CamelCased or under_scored, as the first argument, and an optional
list of attribute pairs.
Attribute pairs are column_name:sql_type arguments specifying the
model's attributes. Timestamps are added by default, so you don't have to
specify them by hand as 'created_at:datetime updated_at:datetime'.
You don't have to think up every attribute up front, but it helps to
sketch out a few so you can start working with the resource immediately.
This creates a model, controller, helper, tests and fixtures for all of them,
and the corresponding map.resources declaration in config/routes.rb
Unlike the scaffold generator, the resource generator does not create
views or add any methods to the generated controller.
Examples:
`./script/generate resource post` # no attributes
`./script/generate resource post title:string body:text published:boolean`
`./script/generate resource purchase order_id:integer amount:decimal`
class ResourceGenerator < Rails::Generator::NamedBase
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_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 = @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_singular_name, @controller_plural_name = inflect_names(base_name)
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
record do |m|
# Check for class naming collisions.
m.class_collisions("#{controller_class_name}Controller", "#{controller_class_name}Helper")
m.class_collisions(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('test/functional', controller_class_path))
m.directory(File.join('test/unit', class_path))
m.directory(File.join('test/unit/helpers', class_path))
m.dependency 'model', [name] + @args, :collision => :skip
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('helper.rb', File.join('app/helpers', controller_class_path, "#{controller_file_name}_helper.rb"))
m.template('helper_test.rb', File.join('test/unit/helpers', controller_class_path, "#{controller_file_name}_helper_test.rb"))
m.route_resources controller_file_name
end
end
protected
def banner
"Usage: #{$0} resource 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 model_name
class_name.demodulize
end
end
class <%= controller_class_name %>Controller < ApplicationController
end
require 'test_helper'
class <%= controller_class_name %>ControllerTest < ActionController::TestCase
# Replace this with your real tests.
test "the truth" do
assert true
end
end
require 'test_helper'
class <%= controller_class_name %>HelperTest < ActionView::TestCase
end
Description:
Scaffolds an entire resource, from model and migration to controller and
views, along with a full test suite. The resource is ready to use as a
starting point for your RESTful, resource-oriented application.
Pass the name of the model (in singular form), either CamelCased or
under_scored, as the first argument, and an optional list of attribute
pairs.
Attribute pairs are column_name:sql_type arguments specifying the
model's attributes. Timestamps are added by default, so you don't have to
specify them by hand as 'created_at:datetime updated_at:datetime'.
You don't have to think up every attribute up front, but it helps to
sketch out a few so you can start working with the resource immediately.
For example, 'scaffold post title:string body:text published:boolean'
gives you a model with those three attributes, a controller that handles
the create/show/update/destroy, forms to create and edit your posts, and
an index that lists them all, as well as a map.resources :posts
declaration in config/routes.rb.
If you want to remove all the generated files, run
'script/destroy scaffold ModelName'.
Examples:
`./script/generate scaffold post`
`./script/generate scaffold post title:string body:text published:boolean`
`./script/generate scaffold purchase order_id:integer amount:decimal`
class ScaffoldGenerator < Rails::Generator::NamedBase
default_options :skip_timestamps => false, :skip_migration => false, :force_plural => 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
if @name == @name.pluralize && !options[:force_plural]
logger.warning "Plural version of the model detected, using singularized version. Override with --force-plural."
@name = @name.singularize
end
@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
record do |m|
# Check for class naming collisions.
m.class_collisions("#{controller_class_name}Controller", "#{controller_class_name}Helper")
m.class_collisions(class_name)
# Controller, helper, views, test and stylesheets 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))
m.directory(File.join('test/unit/helpers', class_path))
m.directory(File.join('public/stylesheets', class_path))
for action in scaffold_views
m.template(
"view_#{action}.html.erb",
File.join('app/views', controller_class_path, controller_file_name, "#{action}.html.erb")
)
end
# Layout and stylesheet.
m.template('layout.html.erb', File.join('app/views/layouts', controller_class_path, "#{controller_file_name}.html.erb"))
m.template('style.css', 'public/stylesheets/scaffold.css')
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('helper.rb', File.join('app/helpers', controller_class_path, "#{controller_file_name}_helper.rb"))
m.template('helper_test.rb', File.join('test/unit/helpers', controller_class_path, "#{controller_file_name}_helper_test.rb"))
m.route_resources controller_file_name
m.dependency 'model', [name] + @args, :collision => :skip
end
end
protected
# 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 }
opt.on("--force-plural",
"Forces the generation of a plural ModelName") { |v| options[:force_plural] = v }
end
def scaffold_views
%w[ index show new edit ]
end
def model_name
class_name.demodulize
end
end
class <%= controller_class_name %>Controller < ApplicationController
# GET /<%= table_name %>
# GET /<%= table_name %>.xml
def index
@<%= table_name %> = <%= class_name %>.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @<%= table_name %> }
end
end
# GET /<%= table_name %>/1
# GET /<%= table_name %>/1.xml
def show
@<%= file_name %> = <%= class_name %>.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @<%= file_name %> }
end
end
# GET /<%= table_name %>/new
# GET /<%= table_name %>/new.xml
def new
@<%= file_name %> = <%= class_name %>.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @<%= file_name %> }
end
end
# GET /<%= table_name %>/1/edit
def edit
@<%= file_name %> = <%= class_name %>.find(params[:id])
end
# POST /<%= table_name %>
# POST /<%= table_name %>.xml
def create
@<%= file_name %> = <%= class_name %>.new(params[:<%= file_name %>])
respond_to do |format|
if @<%= file_name %>.save
flash[:notice] = '<%= class_name %> was successfully created.'
format.html { redirect_to(@<%= file_name %>) }
format.xml { render :xml => @<%= file_name %>, :status => :created, :location => @<%= file_name %> }
else
format.html { render :action => "new" }
format.xml { render :xml => @<%= file_name %>.errors, :status => :unprocessable_entity }
end
end
end
# PUT /<%= table_name %>/1
# PUT /<%= table_name %>/1.xml
def update
@<%= file_name %> = <%= class_name %>.find(params[:id])
respond_to do |format|
if @<%= file_name %>.update_attributes(params[:<%= file_name %>])
flash[:notice] = '<%= class_name %> was successfully updated.'
format.html { redirect_to(@<%= file_name %>) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @<%= file_name %>.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /<%= table_name %>/1
# DELETE /<%= table_name %>/1.xml
def destroy
@<%= file_name %> = <%= class_name %>.find(params[:id])
@<%= file_name %>.destroy
respond_to do |format|
format.html { redirect_to(<%= table_name %>_url) }
format.xml { head :ok }
end
end
end
require 'test_helper'
class <%= controller_class_name %>ControllerTest < ActionController::TestCase
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:<%= table_name %>)
end
test "should get new" do
get :new
assert_response :success
end
test "should create <%= file_name %>" do
assert_difference('<%= class_name %>.count') do
post :create, :<%= file_name %> => { }
end
assert_redirected_to <%= file_name %>_path(assigns(:<%= file_name %>))
end
test "should show <%= file_name %>" do
get :show, :id => <%= table_name %>(:one).to_param
assert_response :success
end
test "should get edit" do
get :edit, :id => <%= table_name %>(:one).to_param
assert_response :success
end
test "should update <%= file_name %>" do
put :update, :id => <%= table_name %>(:one).to_param, :<%= file_name %> => { }
assert_redirected_to <%= file_name %>_path(assigns(:<%= file_name %>))
end
test "should destroy <%= file_name %>" do
assert_difference('<%= class_name %>.count', -1) do
delete :destroy, :id => <%= table_name %>(:one).to_param
end
assert_redirected_to <%= table_name %>_path
end
end
require 'test_helper'
class <%= controller_class_name %>HelperTest < ActionView::TestCase
end
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title><%= controller_class_name %>: <%%= controller.action_name %></title>
<%%= stylesheet_link_tag 'scaffold' %>
</head>
<body>
<p style="color: green"><%%= flash[:notice] %></p>
<%%= yield %>
</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; }
.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;
}
<h1>Editing <%= singular_name %></h1>
<%% form_for(@<%= singular_name %>) do |f| %>
<%%= f.error_messages %>
<% for attribute in attributes -%>
<p>
<%%= f.label :<%= attribute.name %> %><br />
<%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
</p>
<% end -%>
<p>
<%%= f.submit 'Update' %>
</p>
<%% end %>
<%%= link_to 'Show', @<%= singular_name %> %> |
<%%= link_to 'Back', <%= plural_name %>_path %>
\ No newline at end of file
<h1>Listing <%= plural_name %></h1>
<table>
<tr>
<% for attribute in attributes -%>
<th><%= attribute.column.human_name %></th>
<% end -%>
</tr>
<%% @<%= plural_name %>.each do |<%= singular_name %>| %>
<tr>
<% for attribute in attributes -%>
<td><%%=h <%= singular_name %>.<%= attribute.name %> %></td>
<% end -%>
<td><%%= link_to 'Show', <%= singular_name %> %></td>
<td><%%= link_to 'Edit', edit_<%= singular_name %>_path(<%= singular_name %>) %></td>
<td><%%= link_to 'Destroy', <%= singular_name %>, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<%% end %>
</table>
<br />
<%%= link_to 'New <%= singular_name %>', new_<%= singular_name %>_path %>
\ No newline at end of file
<h1>New <%= singular_name %></h1>
<%% form_for(@<%= singular_name %>) do |f| %>
<%%= f.error_messages %>
<% for attribute in attributes -%>
<p>
<%%= f.label :<%= attribute.name %> %><br />
<%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
</p>
<% end -%>
<p>
<%%= f.submit 'Create' %>
</p>
<%% end %>
<%%= link_to 'Back', <%= plural_name %>_path %>
\ No newline at end of file
<% for attribute in attributes -%>
<p>
<b><%= attribute.column.human_name %>:</b>
<%%=h @<%= singular_name %>.<%= attribute.name %> %>
</p>
<% end -%>
<%%= link_to 'Edit', edit_<%= singular_name %>_path(@<%= singular_name %>) %> |
<%%= link_to 'Back', <%= plural_name %>_path %>
\ No newline at end of file
Description:
Creates a migration to add the sessions table used by the Active Record
session store. Pass the migration name, either CamelCased or under_scored,
as an argument.
Example:
`./script/generate session_migration CreateSessionTable`
With 4 existing migrations, this creates the AddSessionTable migration
in db/migrate/005_add_session_table.rb
class SessionMigrationGenerator < Rails::Generator::NamedBase
def initialize(runtime_args, runtime_options = {})
runtime_args << 'add_session_table' if runtime_args.empty?
super
end
def manifest
record do |m|
m.migration_template 'migration.rb', 'db/migrate',
:assigns => { :session_table_name => default_session_table_name }
end
end
protected
def default_session_table_name
ActiveRecord::Base.pluralize_table_names ? 'session'.pluralize : 'session'
end
end
class <%= class_name %> < ActiveRecord::Migration
def self.up
create_table :<%= session_table_name %> do |t|
t.string :session_id, :null => false
t.text :data
t.timestamps
end
add_index :<%= session_table_name %>, :session_id
add_index :<%= session_table_name %>, :updated_at
end
def self.down
drop_table :<%= session_table_name %>
end
end
require 'abstract_unit'
require 'generators/generators_test_helper'
require 'generators/rails/scaffold_controller/scaffold_controller_generator'
# Mock out what we need from AR::Base.
module ActiveRecord
class Base
class << self
attr_accessor :pluralize_table_names
end
self.pluralize_table_names = true
end
end
class NamedBaseTest < GeneratorsTestCase
def test_named_generator_attributes
g = Rails::Generators::ScaffoldControllerGenerator.new ["admin/foo"]
assert_equal 'admin/foo', g.name
assert_equal %w(admin), g.class_path
assert_equal 1, g.class_nesting_depth
assert_equal 'Admin::Foo', g.class_name
assert_equal 'foo', g.singular_name
assert_equal 'foos', g.plural_name
assert_equal g.singular_name, g.file_name
assert_equal "admin_#{g.plural_name}", g.table_name
end
def test_named_generator_attributes_without_pluralized
ActiveRecord::Base.pluralize_table_names = false
g = Rails::Generators::ScaffoldControllerGenerator.new ["admin/foo"]
assert_equal "admin_#{g.singular_name}", g.table_name
end
def test_scaffold_plural_names
g = Rails::Generators::ScaffoldControllerGenerator.new ["ProductLine"]
assert_equal "ProductLines", g.controller_name
assert_equal "ProductLines", g.controller_class_name
assert_equal "product_lines", g.controller_file_name
end
end
require 'test/unit'
require 'fileutils'
# Mock out what we need from AR::Base
module ActiveRecord
class Base
class << self
attr_accessor :pluralize_table_names, :timestamped_migrations
end
self.pluralize_table_names = true
self.timestamped_migrations = true
end
module ConnectionAdapters
class Column
attr_reader :name, :default, :type, :limit, :null, :sql_type, :precision, :scale
def initialize(name, default, sql_type = nil)
@name = name
@default = default
@type = @sql_type = sql_type
end
def human_name
@name.humanize
end
end
end
end
# Mock up necessities from ActionView
module ActionView
module Helpers
module ActionRecordHelper; end
class InstanceTag; end
end
end
# Set RAILS_ROOT appropriately fixture generation
tmp_dir = "#{File.dirname(__FILE__)}/../fixtures/tmp"
if defined? RAILS_ROOT
RAILS_ROOT.replace tmp_dir
else
RAILS_ROOT = tmp_dir
end
FileUtils.mkdir_p RAILS_ROOT
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib"
require 'initializer'
# Mocks out the configuration
module Rails
def self.configuration
Rails::Configuration.new
end
end
require 'rails_generator'
class GeneratorTestCase < Test::Unit::TestCase
include FileUtils
def setup
ActiveRecord::Base.pluralize_table_names = true
mkdir_p "#{RAILS_ROOT}/app/views/layouts"
mkdir_p "#{RAILS_ROOT}/config"
mkdir_p "#{RAILS_ROOT}/db"
mkdir_p "#{RAILS_ROOT}/test/fixtures"
mkdir_p "#{RAILS_ROOT}/public/stylesheets"
File.open("#{RAILS_ROOT}/config/routes.rb", 'w') do |f|
f << "ActionController::Routing::Routes.draw do |map|\n\nend"
end
end
def teardown
rm_rf "#{RAILS_ROOT}/app"
rm_rf "#{RAILS_ROOT}/test"
rm_rf "#{RAILS_ROOT}/config"
rm_rf "#{RAILS_ROOT}/db"
rm_rf "#{RAILS_ROOT}/public"
end
def test_truth
# don't complain, test/unit
end
# Instantiates the Generator.
def build_generator(name, params)
Rails::Generator::Base.instance(name, params)
end
# Runs the +create+ command (like the command line does).
def run_generator(name, params)
silence_generator do
build_generator(name, params).command(:create).invoke!
end
end
# Silences the logger temporarily and returns the output as a String.
def silence_generator
logger_original = Rails::Generator::Base.logger
myout = StringIO.new
Rails::Generator::Base.logger = Rails::Generator::SimpleLogger.new(myout)
yield if block_given?
Rails::Generator::Base.logger = logger_original
myout.string
end
# Asserts that the given controller was generated.
# It takes a name or symbol without the <tt>_controller</tt> part and an optional super class.
# The contents of the class source file is passed to a block.
def assert_generated_controller_for(name, parent = "ApplicationController")
assert_generated_class "app/controllers/#{name.to_s.underscore}_controller", parent do |body|
yield body if block_given?
end
end
# Asserts that the given model was generated.
# It takes a name or symbol and an optional super class.
# The contents of the class source file is passed to a block.
def assert_generated_model_for(name, parent = "ActiveRecord::Base")
assert_generated_class "app/models/#{name.to_s.underscore}", parent do |body|
yield body if block_given?
end
end
# Asserts that the given helper was generated.
# It takes a name or symbol without the <tt>_helper</tt> part.
# The contents of the module source file is passed to a block.
def assert_generated_helper_for(name)
assert_generated_module "app/helpers/#{name.to_s.underscore}_helper" do |body|
yield body if block_given?
end
end
# Asserts that the given functional test was generated.
# It takes a name or symbol without the <tt>_controller_test</tt> part and an optional super class.
# The contents of the class source file is passed to a block.
def assert_generated_functional_test_for(name, parent = "ActionController::TestCase")
assert_generated_class "test/functional/#{name.to_s.underscore}_controller_test",parent do |body|
yield body if block_given?
end
end
# Asserts that the given helper test test was generated.
# It takes a name or symbol without the <tt>_helper_test</tt> part and an optional super class.
# The contents of the class source file is passed to a block.
def assert_generated_helper_test_for(name, parent = "ActionView::TestCase")
path = "test/unit/helpers/#{name.to_s.underscore}_helper_test"
# Have to pass the path without the "test/" part so that class_name_from_path will return a correct result
class_name = class_name_from_path(path.gsub(/^test\//, ''))
assert_generated_class path,parent,class_name do |body|
yield body if block_given?
end
end
# Asserts that the given unit test was generated.
# It takes a name or symbol without the <tt>_test</tt> part and an optional super class.
# The contents of the class source file is passed to a block.
def assert_generated_unit_test_for(name, parent = "ActiveSupport::TestCase")
assert_generated_class "test/unit/#{name.to_s.underscore}_test", parent do |body|
yield body if block_given?
end
end
# Asserts that the given file was generated.
# The contents of the file is passed to a block.
def assert_generated_file(path)
assert_file_exists(path)
File.open("#{RAILS_ROOT}/#{path}") do |f|
yield f.read if block_given?
end
end
# asserts that the given file exists
def assert_file_exists(path)
assert File.exist?("#{RAILS_ROOT}/#{path}"),
"The file '#{RAILS_ROOT}/#{path}' should exist"
end
# Asserts that the given class source file was generated.
# It takes a path without the <tt>.rb</tt> part and an optional super class.
# The contents of the class source file is passed to a block.
def assert_generated_class(path, parent = nil, class_name = class_name_from_path(path))
assert_generated_file("#{path}.rb") do |body|
assert_match /class #{class_name}#{parent.nil? ? '':" < #{parent}"}/, body, "the file '#{path}.rb' should be a class"
yield body if block_given?
end
end
def class_name_from_path(path)
# FIXME: Sucky way to detect namespaced classes
if path.split('/').size > 3
path =~ /\/?(\d+_)?(\w+)\/(\w+)$/
"#{$2.camelize}::#{$3.camelize}"
else
path =~ /\/?(\d+_)?(\w+)$/
$2.camelize
end
end
# Asserts that the given module source file was generated.
# It takes a path without the <tt>.rb</tt> part.
# The contents of the class source file is passed to a block.
def assert_generated_module(path)
# FIXME: Sucky way to detect namespaced modules
if path.split('/').size > 3
path =~ /\/?(\w+)\/(\w+)$/
module_name = "#{$1.camelize}::#{$2.camelize}"
else
path =~ /\/?(\w+)$/
module_name = $1.camelize
end
assert_generated_file("#{path}.rb") do |body|
assert_match /module #{module_name}/, body, "the file '#{path}.rb' should be a module"
yield body if block_given?
end
end
# Asserts that the given CSS stylesheet file was generated.
# It takes a path without the <tt>.css</tt> part.
# The contents of the stylesheet source file is passed to a block.
def assert_generated_stylesheet(path)
assert_generated_file("public/stylesheets/#{path}.css") do |body|
yield body if block_given?
end
end
# Asserts that the given YAML file was generated.
# It takes a path without the <tt>.yml</tt> part.
# The parsed YAML tree is passed to a block.
def assert_generated_yaml(path)
assert_generated_file("#{path}.yml") do |body|
yaml = YAML.load(body)
assert yaml, 'YAML data missing'
yield yaml if block_given?
end
end
# Asserts that the given fixtures YAML file was generated.
# It takes a fixture name without the <tt>.yml</tt> part.
# The parsed YAML tree is passed to a block.
def assert_generated_fixtures_for(name)
assert_generated_yaml "test/fixtures/#{name.to_s.underscore}" do |yaml|
yield yaml if block_given?
end
end
# Asserts that the given views were generated.
# It takes a controller name and a list of views (including extensions).
# The body of each view is passed to a block.
def assert_generated_views_for(name, *actions)
actions.each do |action|
assert_generated_file("app/views/#{name.to_s.underscore}/#{action}") do |body|
yield body if block_given?
end
end
end
def assert_generated_migration(name, parent = "ActiveRecord::Migration")
file = Dir.glob("#{RAILS_ROOT}/db/migrate/*_#{name.to_s.underscore}.rb").first
file = file.match(/db\/migrate\/[0-9]+_\w+/).to_s
assert_generated_class file, parent do |body|
assert_match /timestamps/, body, "should have timestamps defined"
yield body if block_given?
end
end
# Asserts that the given migration file was not generated.
# It takes the name of the migration as a parameter.
def assert_skipped_migration(name)
migration_file = "#{RAILS_ROOT}/db/migrate/001_#{name.to_s.underscore}.rb"
assert !File.exist?(migration_file), "should not create migration #{migration_file}"
end
# Asserts that the given resource was added to the routes.
def assert_added_route_for(name)
assert_generated_file("config/routes.rb") do |body|
assert_match /map.resources :#{name.to_s.underscore}/, body,
"should add route for :#{name.to_s.underscore}"
end
end
# Asserts that the given methods are defined in the body.
# This does assume standard rails code conventions with regards to the source code.
# The body of each individual method is passed to a block.
def assert_has_method(body, *methods)
methods.each do |name|
assert body =~ /^ def #{name}(\(.+\))?\n((\n| .*\n)*) end/, "should have method #{name}"
yield(name, $2) if block_given?
end
end
# Asserts that the given column is defined in the migration.
def assert_generated_column(body, name, type)
assert_match /t\.#{type.to_s} :#{name.to_s}/, body, "should have column #{name.to_s} defined"
end
end
require 'rails_generator/generator_test_helper'
module Admin
end
class RailsControllerGeneratorTest < GeneratorTestCase
def test_controller_generates_controller
run_generator('controller', %w(products))
assert_generated_controller_for :products
assert_generated_functional_test_for :products
assert_generated_helper_for :products
assert_generated_helper_test_for :products
end
def test_controller_generates_namespaced_controller
run_generator('controller', %w(admin::products))
assert_generated_controller_for "admin::products"
assert_generated_functional_test_for "admin::products"
assert_generated_helper_for "admin::products"
assert_generated_helper_test_for "admin::products"
end
def test_controller_generates_namespaced_and_not_namespaced_controllers
run_generator('controller', %w(products))
# We have to require the generated helper to show the problem because
# the test helpers just check for generated files and contents but
# do not actually load them. But they have to be loaded (as in a real environment)
# to make the second generator run fail
require "#{RAILS_ROOT}/app/helpers/products_helper"
assert_nothing_raised do
begin
run_generator('controller', %w(admin::products))
ensure
# cleanup
Object.send(:remove_const, :ProductsHelper)
end
end
end
end
require File.dirname(__FILE__) + '/generator_test_helper'
class RailsHelperGeneratorTest < GeneratorTestCase
def test_helper_generates_helper
run_generator('helper', %w(products))
assert_generated_helper_for :products
assert_generated_helper_test_for :products
end
def test_helper_generates_namespaced_helper
run_generator('helper', %w(admin::products))
assert_generated_helper_for "admin::products"
assert_generated_helper_test_for "admin::products"
end
def test_helper_generates_namespaced_and_not_namespaced_helpers
run_generator('helper', %w(products))
# We have to require the generated helper to show the problem because
# the test helpers just check for generated files and contents but
# do not actually load them. But they have to be loaded (as in a real environment)
# to make the second generator run fail
require "#{RAILS_ROOT}/app/helpers/products_helper"
assert_nothing_raised do
begin
run_generator('helper', %w(admin::products))
ensure
# cleanup
Object.send(:remove_const, :ProductsHelper)
end
end
end
end
require 'rails_generator/generator_test_helper'
class RailsMailerGeneratorTest < GeneratorTestCase
def test_generates_mailer
run_generator('mailer', %w(Notifier reset_password))
assert_generated_model_for :notifier, 'ActionMailer::Base' do |model|
assert_has_method model, :reset_password do |name, body|
assert_equal [
"subject 'Notifier#reset_password'",
"recipients ''",
"from ''",
"sent_on sent_at",
"",
"body :greeting => 'Hi,'"
],
body.split("\n").map{|line| line.sub(' '*4, '') }
end
assert_no_match /(self.default_url_options =|default_url_options\[.*\] =)/, model,
'individual mailer models should not set default_url_options because the options are shared by all mailers'
end
assert_generated_views_for :notifier, 'reset_password.erb'
assert_generated_unit_test_for :notifier, 'ActionMailer::TestCase'
assert_generated_file "test/fixtures/notifier/reset_password"
end
end
require 'rails_generator/generator_test_helper'
class RailsModelGeneratorTest < GeneratorTestCase
def test_model_generates_resources
run_generator('model', %w(Product name:string))
assert_generated_model_for :product
assert_generated_fixtures_for :products
assert_generated_migration :create_products
end
def test_model_skip_migration_skips_migration
run_generator('model', %w(Product name:string --skip-migration))
assert_generated_model_for :product
assert_generated_fixtures_for :products
assert_skipped_migration :create_products
end
def test_model_with_attributes_generates_resources_with_attributes
run_generator('model', %w(Product name:string supplier_id:integer created_at:timestamp))
assert_generated_model_for :product
assert_generated_fixtures_for :products
assert_generated_migration :create_products do |t|
assert_generated_column t, :name, :string
assert_generated_column t, :supplier_id, :integer
assert_generated_column t, :created_at, :timestamp
end
end
def test_model_with_reference_attributes_generates_belongs_to_associations
run_generator('model', %w(Product name:string supplier:references))
assert_generated_model_for :product do |body|
assert body =~ /^\s+belongs_to :supplier/, "#{body.inspect} should contain 'belongs_to :supplier'"
end
end
def test_model_with_belongs_to_attributes_generates_belongs_to_associations
run_generator('model', %w(Product name:string supplier:belongs_to))
assert_generated_model_for :product do |body|
assert body =~ /^\s+belongs_to :supplier/, "#{body.inspect} should contain 'belongs_to :supplier'"
end
end
end
require 'rails_generator/generator_test_helper'
class RailsModelSubclassGeneratorTest < GeneratorTestCase
def test_model_subclass_generates_resources
run_generator('model_subclass', %w(Car Product))
assert_generated_model_for :car, "Product"
assert_generated_unit_test_for :car
end
def test_model_subclass_must_have_a_parent_class_name
assert_raise(Rails::Generator::UsageError) { run_generator('model_subclass', %w(Car)) }
end
end
require 'rails_generator/generator_test_helper'
class RailsResourceGeneratorTest < GeneratorTestCase
def test_resource_generates_resources
run_generator('resource', %w(Product name:string))
assert_generated_controller_for :products
assert_generated_model_for :product
assert_generated_fixtures_for :products
assert_generated_functional_test_for :products
assert_generated_helper_for :products
assert_generated_helper_test_for :products
assert_generated_migration :create_products
assert_added_route_for :products
end
def test_resource_skip_migration_skips_migration
run_generator('resource', %w(Product name:string --skip-migration))
assert_generated_controller_for :products
assert_generated_model_for :product
assert_generated_fixtures_for :products
assert_generated_functional_test_for :products
assert_generated_helper_for :products
assert_generated_helper_test_for :products
assert_skipped_migration :create_products
assert_added_route_for :products
end
end
require 'rails_generator/generator_test_helper'
require 'abstract_unit'
class RailsScaffoldGeneratorTest < GeneratorTestCase
def test_scaffolded_names
g = Rails::Generator::Base.instance('scaffold', %w(ProductLine))
assert_equal "ProductLines", g.controller_name
assert_equal "ProductLines", g.controller_class_name
assert_equal "ProductLine", g.controller_singular_name
assert_equal "product_lines", g.controller_plural_name
assert_equal "product_lines", g.controller_file_name
assert_equal "product_lines", g.controller_table_name
end
def test_scaffold_generates_resources
run_generator('scaffold', %w(Product name:string))
assert_generated_controller_for :products do |f|
assert_has_method f, :index do |name, m|
assert_match /@products = Product\.all/, m, "#{name} should query products table"
end
assert_has_method f, :show, :edit, :update, :destroy do |name, m|
assert_match /@product = Product\.find\(params\[:id\]\)/, m, "#{name.to_s} should query products table"
end
assert_has_method f, :new do |name, m|
assert_match /@product = Product\.new/, m, "#{name.to_s} should instantiate a product"
end
assert_has_method f, :create do |name, m|
assert_match /@product = Product\.new\(params\[:product\]\)/, m, "#{name.to_s} should instantiate a product"
assert_match /format.xml \{ render :xml => @product.errors, :status => :unprocessable_entity \}/, m, "#{name.to_s} should set status to :unprocessable_entity code for xml"
end
end
assert_generated_model_for :product
assert_generated_functional_test_for :products
assert_generated_unit_test_for :product
assert_generated_fixtures_for :products
assert_generated_helper_for :products
assert_generated_helper_test_for :products
assert_generated_stylesheet :scaffold
assert_generated_views_for :products, "index.html.erb", "new.html.erb", "edit.html.erb", "show.html.erb"
assert_generated_migration :create_products
assert_added_route_for :products
end
def test_scaffold_skip_migration_skips_migration
run_generator('scaffold', %w(Product name:string --skip-migration))
assert_generated_model_for :product
assert_generated_functional_test_for :products
assert_generated_unit_test_for :product
assert_generated_fixtures_for :products
assert_generated_helper_for :products
assert_generated_helper_test_for :products
assert_generated_stylesheet :scaffold
assert_generated_views_for :products, "index.html.erb","new.html.erb","edit.html.erb","show.html.erb"
assert_skipped_migration :create_products
assert_added_route_for :products
end
def test_scaffold_generates_resources_with_attributes
run_generator('scaffold', %w(Product name:string supplier_id:integer created_at:timestamp))
assert_generated_controller_for :products do |f|
assert_has_method f, :index do |name, m|
assert_match /@products = Product\.all/, m, "#{name} should query products table"
end
assert_has_method f, :show, :edit, :update, :destroy do |name, m|
assert_match /@product = Product\.find\(params\[:id\]\)/, m, "#{name.to_s} should query products table"
end
assert_has_method f, :new do |name, m|
assert_match /@product = Product\.new/, m, "#{name.to_s} should instantiate a product"
end
assert_has_method f, :create do |name, m|
assert_match /@product = Product\.new\(params\[:product\]\)/, m, "#{name.to_s} should instantiate a product"
assert_match /format.xml \{ render :xml => @product.errors, :status => :unprocessable_entity \}/, m, "#{name.to_s} should set status to :unprocessable_entity code for xml"
end
end
assert_generated_model_for :product
assert_generated_functional_test_for :products
assert_generated_unit_test_for :product
assert_generated_fixtures_for :products
assert_generated_helper_for :products
assert_generated_helper_test_for :products
assert_generated_stylesheet :scaffold
assert_generated_views_for :products, "index.html.erb", "new.html.erb", "edit.html.erb", "show.html.erb"
assert_generated_migration :create_products do |t|
assert_generated_column t, :name, :string
assert_generated_column t, :supplier_id, :integer
assert_generated_column t, :created_at, :timestamp
end
assert_added_route_for :products
end
def test_scaffolded_plural_names
Rails::Generator::Base.logger.expects(:warning)
g = Rails::Generator::Base.instance('scaffold', %w(ProductLines))
assert_equal "ProductLines", g.controller_name
assert_equal "ProductLines", g.controller_class_name
assert_equal "ProductLine", g.controller_singular_name
assert_equal "product_lines", g.controller_plural_name
assert_equal "product_lines", g.controller_file_name
assert_equal "product_lines", g.controller_table_name
end
def test_scaffold_plural_model_name_without_force_plural_generates_singular_model
run_generator('scaffold', %w(Products name:string))
assert_generated_model_for :product
assert_generated_functional_test_for :products
assert_generated_unit_test_for :product
assert_generated_fixtures_for :products
assert_generated_helper_for :products
assert_generated_helper_test_for :products
assert_generated_stylesheet :scaffold
assert_generated_views_for :products, "index.html.erb","new.html.erb","edit.html.erb","show.html.erb"
assert_skipped_migration :create_products
assert_added_route_for :products
end
def test_scaffold_plural_model_name_with_force_plural_forces_plural_model
run_generator('scaffold', %w(Products name:string --force-plural))
assert_generated_model_for :products
assert_generated_functional_test_for :products
assert_generated_unit_test_for :products
assert_generated_fixtures_for :products
assert_generated_helper_for :products
assert_generated_helper_test_for :products
assert_generated_stylesheet :scaffold
assert_generated_views_for :products, "index.html.erb","new.html.erb","edit.html.erb","show.html.erb"
assert_skipped_migration :create_products
assert_added_route_for :products
end
end
......@@ -44,105 +44,74 @@ def self.configuration
require 'rails_generator'
class RailsGeneratorTest < Test::Unit::TestCase
BUILTINS = %w(controller integration_test mailer migration model observer plugin resource scaffold session_migration)
CAPITALIZED_BUILTINS = BUILTINS.map { |b| b.capitalize }
def setup
ActiveRecord::Base.pluralize_table_names = true
@initializer = Rails::Initializer.default
@initializer.config = Rails.configuration
@initializer.run(:set_root_path)
end
def test_sources
expected = [:lib, :vendor,
"plugins (vendor/plugins)".to_sym, # <plugin>/generators and <plugin>/rails_generators
:user,
:RubyGems, :RubyGems, # gems named <x>_generator, gems containing /rails_generator/ folder
:builtin]
expected.delete(:RubyGems) unless Object.const_defined?(:Gem)
assert_equal expected, Rails::Generator::Base.sources.map { |s| s.label }
end
def test_lookup_builtins
(BUILTINS + CAPITALIZED_BUILTINS).each do |name|
assert_nothing_raised do
spec = Rails::Generator::Base.lookup(name)
assert_not_nil spec
assert_kind_of Rails::Generator::Spec, spec
klass = spec.klass
assert klass < Rails::Generator::Base
assert_equal spec, klass.spec
end
end
end
def test_autolookup
assert_nothing_raised { ControllerGenerator }
assert_nothing_raised { ModelGenerator }
end
def test_lookup_missing_generator
assert_raise Rails::Generator::GeneratorError do
Rails::Generator::Base.lookup('missing').klass
end
end
def test_lookup_missing_class
spec = nil
assert_nothing_raised { spec = Rails::Generator::Base.lookup('missing_class') }
assert_not_nil spec
assert_kind_of Rails::Generator::Spec, spec
assert_raise(NameError) { spec.klass }
end
def test_generator_usage
(BUILTINS - ["session_migration"]).each do |name|
assert_raise(Rails::Generator::UsageError, "Generator '#{name}' should raise an error without arguments") {
Rails::Generator::Base.instance(name)
}
end
end
def test_generator_spec
spec = Rails::Generator::Base.lookup('working')
assert_equal 'working', spec.name
assert_match(/#{spec.path}$/, "#{RAILS_ROOT}/lib/generators/working")
assert_equal :lib, spec.source
assert_nothing_raised { assert_match(/WorkingGenerator$/, spec.klass.name) }
end
def test_named_generator_attributes
g = Rails::Generator::Base.instance('working', %w(admin/foo bar baz))
assert_equal 'admin/foo', g.name
assert_equal %w(admin), g.class_path
assert_equal 'Admin', g.class_nesting
assert_equal 'Admin::Foo', g.class_name
assert_equal 'foo', g.singular_name
assert_equal 'foos', g.plural_name
assert_equal g.singular_name, g.file_name
assert_equal "admin_#{g.plural_name}", g.table_name
assert_equal %w(bar baz), g.args
end
def test_named_generator_attributes_without_pluralized
ActiveRecord::Base.pluralize_table_names = false
g = Rails::Generator::Base.instance('working', %w(admin/foo bar baz))
assert_equal "admin_#{g.singular_name}", g.table_name
end
def test_session_migration_generator_with_pluralization
g = Rails::Generator::Base.instance('session_migration')
assert_equal 'session'.pluralize, g.send(:default_session_table_name)
ActiveRecord::Base.pluralize_table_names = false
assert_equal 'session', g.send(:default_session_table_name)
end
def test_scaffold_controller_name
# Default behaviour is use the model name
g = Rails::Generator::Base.instance('scaffold', %w(Product))
assert_equal "Products", g.controller_name
end
end
#class RailsGeneratorTest < Test::Unit::TestCase
# BUILTINS = %w(controller integration_test mailer migration model observer plugin resource scaffold session_migration)
# CAPITALIZED_BUILTINS = BUILTINS.map { |b| b.capitalize }
# def setup
# ActiveRecord::Base.pluralize_table_names = true
# @initializer = Rails::Initializer.default
# @initializer.config = Rails.configuration
# @initializer.run(:set_root_path)
# end
# def test_sources
# expected = [:lib, :vendor,
# "plugins (vendor/plugins)".to_sym, # <plugin>/generators and <plugin>/rails_generators
# :user,
# :RubyGems, :RubyGems, # gems named <x>_generator, gems containing /rails_generator/ folder
# :builtin]
# expected.delete(:RubyGems) unless Object.const_defined?(:Gem)
# assert_equal expected, Rails::Generator::Base.sources.map { |s| s.label }
# end
# def test_lookup_builtins
# (BUILTINS + CAPITALIZED_BUILTINS).each do |name|
# assert_nothing_raised do
# spec = Rails::Generator::Base.lookup(name)
# assert_not_nil spec
# assert_kind_of Rails::Generator::Spec, spec
# klass = spec.klass
# assert klass < Rails::Generator::Base
# assert_equal spec, klass.spec
# end
# end
# end
# def test_autolookup
# assert_nothing_raised { ControllerGenerator }
# assert_nothing_raised { ModelGenerator }
# end
# def test_lookup_missing_generator
# assert_raise Rails::Generator::GeneratorError do
# Rails::Generator::Base.lookup('missing').klass
# end
# end
# def test_lookup_missing_class
# spec = nil
# assert_nothing_raised { spec = Rails::Generator::Base.lookup('missing_class') }
# assert_not_nil spec
# assert_kind_of Rails::Generator::Spec, spec
# assert_raise(NameError) { spec.klass }
# end
# def test_generator_usage
# (BUILTINS - ["session_migration"]).each do |name|
# assert_raise(Rails::Generator::UsageError, "Generator '#{name}' should raise an error without arguments") {
# Rails::Generator::Base.instance(name)
# }
# end
# end
# def test_generator_spec
# spec = Rails::Generator::Base.lookup('working')
# assert_equal 'working', spec.name
# assert_match(/#{spec.path}$/, "#{RAILS_ROOT}/lib/generators/working")
# assert_equal :lib, spec.source
# assert_nothing_raised { assert_match(/WorkingGenerator$/, spec.klass.name) }
# end
#end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册