diff options
Diffstat (limited to 'railties')
175 files changed, 3146 insertions, 1013 deletions
diff --git a/railties/Rakefile b/railties/Rakefile index 61c094150a..35ae15ff0f 100644 --- a/railties/Rakefile +++ b/railties/Rakefile @@ -26,7 +26,8 @@ task :default => :test ## below passes. It's not ideal, but at least ## we can see the failures task :test do - Dir['test/**/*_test.rb'].all? do |file| + dir = ENV["TEST_DIR"] || "**" + Dir["test/#{dir}/*_test.rb"].all? do |file| ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME')) system(ruby, '-Itest', "-I#{File.dirname(__FILE__)}/../activesupport/lib", file) end or raise "Failures" diff --git a/railties/bin/gen b/railties/bin/gen new file mode 100755 index 0000000000..9f105d2e19 --- /dev/null +++ b/railties/bin/gen @@ -0,0 +1,42 @@ +require File.dirname(__FILE__) + '/../lib/ruby_version_check' +Signal.trap("INT") { puts; exit } + +require File.dirname(__FILE__) + '/../lib/rails/version' +if %w(--version -v).include? ARGV.first + puts "Rails #{Rails::VERSION::STRING}" + exit(0) +end + +require File.dirname(__FILE__) + '/../lib/generators' + +if ARGV.size == 0 + rails = Rails::Generators.builtin.map do |group, name| + name if group == "rails" + end + rails.compact! + rails.sort! + + others = Rails::Generators.builtin.map do |group, name| + "#{group}:#{name}" unless rails.include?(name) + end.compact + others.sort! + + puts "Please select a generator." + puts "Builtin: #{rails.join(', ')}." + puts "Others: #{others.join(', ')}." unless others.empty? + + exit +end + +Rails::Generators.builtin.each do |group, name| + require "generators/#{group}/#{name}/#{name}_generator" +end + +name = ARGV.shift + +if klass = Rails::Generators.find_by_namespace(name, "rails") + ARGV << "--help" if klass.arguments.any? { |a| a.required? } && ARGV.empty? + klass.start +else + puts "Could not find generator #{name}." +end diff --git a/railties/bin/rails b/railties/bin/rails index 6a0c675206..538d0cbc84 100755 --- a/railties/bin/rails +++ b/railties/bin/rails @@ -7,14 +7,9 @@ if %w(--version -v).include? ARGV.first exit(0) end -freeze = ARGV.any? { |option| %w(--freeze -f).include?(option) } +ARGV << "--help" if ARGV.empty? -app_path = ARGV.first +require File.dirname(__FILE__) + '/../lib/generators' +require 'generators/rails/app/app_generator' -require File.dirname(__FILE__) + '/../lib/rails_generator' - -require 'rails_generator/scripts/generate' -Rails::Generator::Base.use_application_sources! -Rails::Generator::Scripts::Generate.new.run(ARGV, :generator => 'app') - -Dir.chdir(app_path) { `rake rails:freeze:gems`; puts "froze" } if freeze
\ No newline at end of file +Rails::Generators::AppGenerator.start diff --git a/railties/lib/generators.rb b/railties/lib/generators.rb new file mode 100644 index 0000000000..fd7d3c9580 --- /dev/null +++ b/railties/lib/generators.rb @@ -0,0 +1,62 @@ +activesupport_path = "#{File.dirname(__FILE__)}/../../activesupport/lib" +$:.unshift(activesupport_path) if File.directory?(activesupport_path) +require 'active_support/all' + +# TODO Use vendored Thor +require 'rubygems' +gem 'josevalim-thor' +require 'thor' + +$:.unshift(File.dirname(__FILE__)) +require 'rails/version' unless defined?(Rails::VERSION) + +require 'generators/base' +require 'generators/named_base' + +module Rails + module Generators + def self.builtin + Dir[File.dirname(__FILE__) + '/generators/*/*'].collect do |file| + file.split('/')[-2, 2] + end + end + + # Receives a namespace and tries different combinations to find a generator. + # + # ==== Examples + # + # lookup_by_namespace :webrat, :rails, :integration + # + # Will search for the following generators: + # + # "rails:generators:webrat", "webrat:generators:integration", "webrat" + # + # If the namespace has ":" included we consider that a absolute namespace + # was given and the lookup above does not happen. Just the name is searched. + # + # Finally, it deals with one kind of shortcut: + # + # lookup_by_namespace "test_unit:model" + # + # It will search for generators at: + # + # "test_unit:generators:model", "test_unit:model" + # + def self.find_by_namespace(name, base=nil, context=nil) + name, attempts = name.to_s, [] + + attempts << "#{base}:generators:#{name}" if base && name.count(':') == 0 + attempts << "#{name}:generators:#{context}" if context && name.count(':') == 0 + attempts << name.sub(':', ':generators:') if name.count(':') == 1 + attempts << name + + attempts.each do |namespace| + klass, task = Thor::Util.find_by_namespace(namespace) + return klass if klass + end + + nil + end + end +end + diff --git a/railties/lib/generators/actions.rb b/railties/lib/generators/actions.rb new file mode 100644 index 0000000000..080d374a2f --- /dev/null +++ b/railties/lib/generators/actions.rb @@ -0,0 +1,274 @@ +require 'open-uri' + +module Rails + module Generators + module Actions + + # Loads an external file and execute it in the instance binding. + # + # ==== Parameters + # path<String>:: The path to the file to execute. Can be a web address or + # a relative path from the source root. + # + # ==== Examples + # + # apply "http://gist.github.com/103208" + # + # apply "recipes/jquery.rb" + # + def apply(path, log_status=true) + path = File.expand_path(path, source_root) unless path =~ /^http\:\/\// + + log :apply, path, log_status + instance_eval(open(path).read) + log :applied, path, log_status + end + + # Install a plugin. You must provide either a Subversion url or Git url. + # For a Git-hosted plugin, you can specify if it should be added as a submodule instead of cloned. + # + # ==== Examples + # + # plugin 'restful-authentication', :git => 'git://github.com/technoweenie/restful-authentication.git' + # plugin 'restful-authentication', :git => 'git://github.com/technoweenie/restful-authentication.git', :submodule => true + # plugin 'restful-authentication', :svn => 'svn://svnhub.com/technoweenie/restful-authentication/trunk' + # + def plugin(name, options) + log :plugin, name + + if options[:git] && options[:submodule] + in_root do + run "git submodule add #{options[:git]} vendor/plugins/#{name}", false + end + elsif options[:git] || options[:svn] + in_root do + run_ruby_script "script/plugin install #{options[:svn] || options[:git]}", false + end + else + log "! no git or svn provided for #{name}. Skipping..." + end + end + + # Adds an entry into config/environment.rb for the supplied gem. If env + # is specified, add the gem to the given environment. + # + # ==== Example + # + # gem "rspec", :env => :test + # gem "technoweenie-restful-authentication", :lib => "restful-authentication", :source => "http://gems.github.com/" + # + def gem(name, options = {}) + log :gem, name + env = options.delete(:env) + + gems_code = "config.gem '#{name}'" + + if options.any? + opts = options.inject([]) {|result, h| result << [":#{h[0]} => #{h[1].inspect.gsub('"',"'")}"] }.sort.join(", ") + gems_code << ", #{opts}" + end + + environment gems_code, :env => env + end + + # Adds a line inside the Initializer block for config/environment.rb. + # + # If options :env is specified, the line is appended to the corresponding + # file in config/environments. + # + def environment(data=nil, options={}, &block) + sentinel = "Rails::Initializer.run do |config|" + + data = block.call if !data && block_given? + + in_root do + if options[:env].nil? + inject_into_file 'config/environment.rb', "\n #{data}", { :after => sentinel }, false + else + Array.wrap(options[:env]).each do|env| + append_file "config/environments/#{env}.rb", "\n#{data}", false + end + end + end + end + + # Run a command in git. + # + # ==== Examples + # + # git :init + # git :add => "this.file that.rb" + # git :add => "onefile.rb", :rm => "badfile.cxx" + # + def git(command = {}) + in_root do + if command.is_a?(Symbol) + run "git #{command}" + else + command.each do |command, options| + run "git #{command} #{options}" + end + end + end + end + + # Create a new file in the vendor/ directory. Code can be specified + # in a block or a data string can be given. + # + # ==== Examples + # + # vendor("sekrit.rb") do + # sekrit_salt = "#{Time.now}--#{3.years.ago}--#{rand}--" + # "salt = '#{sekrit_salt}'" + # end + # + # vendor("foreign.rb", "# Foreign code is fun") + # + def vendor(filename, data=nil, &block) + log :vendor, filename + create_file("vendor/#{filename}", data, false, &block) + end + + # Create a new file in the lib/ directory. Code can be specified + # in a block or a data string can be given. + # + # ==== Examples + # + # lib("crypto.rb") do + # "crypted_special_value = '#{rand}--#{Time.now}--#{rand(1337)}--'" + # end + # + # lib("foreign.rb", "# Foreign code is fun") + # + def lib(filename, data=nil, &block) + log :lib, filename + create_file("lib/#{filename}", data, false, &block) + end + + # Create a new Rakefile with the provided code (either in a block or a string). + # + # ==== Examples + # + # rakefile("bootstrap.rake") do + # project = ask("What is the UNIX name of your project?") + # + # <<-TASK + # namespace :#{project} do + # task :bootstrap do + # puts "i like boots!" + # end + # end + # TASK + # end + # + # rakefile("seed.rake", "puts 'im plantin ur seedz'") + # + def rakefile(filename, data=nil, &block) + log :rakefile, filename + create_file("lib/tasks/#{filename}", data, false, &block) + end + + # Create a new initializer with the provided code (either in a block or a string). + # + # ==== Examples + # + # initializer("globals.rb") do + # data = "" + # + # ['MY_WORK', 'ADMINS', 'BEST_COMPANY_EVAR'].each do + # data << "#{const} = :entp" + # end + # + # data + # end + # + # initializer("api.rb", "API_KEY = '123456'") + # + def initializer(filename, data=nil, &block) + log :initializer, filename + create_file("config/initializers/#{filename}", data, false, &block) + end + + # Generate something using a generator from Rails or a plugin. + # The second parameter is the argument string that is passed to + # the generator or an Array that is joined. + # + # ==== Example + # + # generate(:authenticated, "user session") + # + def generate(what, *args) + log :generate, what + argument = args.map {|arg| arg.to_s }.flatten.join(" ") + + in_root { run_ruby_script("script/generate #{what} #{argument}", false) } + end + + # Runs the supplied rake task + # + # ==== Example + # + # rake("db:migrate") + # rake("db:migrate", :env => "production") + # rake("gems:install", :sudo => true) + # + def rake(command, options={}) + log :rake, command + env = options[:env] || 'development' + sudo = options[:sudo] ? 'sudo ' : '' + in_root { run("#{sudo}rake #{command} RAILS_ENV=#{env}", false) } + end + + # Just run the capify command in root + # + # ==== Example + # + # capify! + # + def capify! + log :capify, "" + in_root { run('capify .', false) } + end + + # Add Rails to /vendor/rails + # + # ==== Example + # + # freeze! + # + def freeze!(args = {}) + log :vendor, "rails" + in_root { run('rake rails:freeze:edge', false) } + end + + # Make an entry in Rails routing file conifg/routes.rb + # + # === Example + # + # route "map.root :controller => :welcome" + # + def route(routing_code) + log :route, routing_code + sentinel = "ActionController::Routing::Routes.draw do |map|" + + in_root do + inject_into_file 'config/routes.rb', "\n #{routing_code}\n", { :after => sentinel }, false + end + end + + protected + + # Define log for backwards compatibility. If just one argument is sent, + # invoke say, otherwise invoke say_status. + # + def log(*args) + if args.size == 1 + say args.first.to_s + else + say_status *args + end + end + + end + end +end diff --git a/railties/lib/generators/active_record.rb b/railties/lib/generators/active_record.rb new file mode 100644 index 0000000000..4e585a11e7 --- /dev/null +++ b/railties/lib/generators/active_record.rb @@ -0,0 +1,58 @@ +require 'generators/named_base' +require 'active_record' + +module ActiveRecord + module Generators + module Migration + + # Creates a migration template at the given destination. The difference + # to the default template method is that the migration number is appended + # to the destination file name. + # + # The migration number, migration file name, migration class name are + # available as instance variables in the template to be rendered. + # + # ==== Examples + # + # migration_template "migration.rb", "db/migrate/add_foo_to_bar.rb" + # + def migration_template(source, destination=nil, log_status=true) + destination = File.expand_path(destination || source, self.destination_root) + + migration_dir = File.dirname(destination) + @migration_number = next_migration_number(migration_dir) + @migration_file_name = File.basename(destination).sub(/\.rb$/, '') + @migration_class_name = @migration_file_name.camelize + + if existing = migration_exists?(migration_dir, @migration_file_name) + raise Rails::Generators::Error, "Another migration is already named #{@migration_file_name}: #{existing}" + end + + destination = File.join(migration_dir, "#{@migration_number}_#{@migration_file_name}.rb") + template(source, destination, log_status) + end + + protected + + def migration_exists?(dirname, file_name) #:nodoc: + Dir.glob("#{dirname}/[0-9]*_*.rb").grep(/\d+_#{file_name}.rb$/).first + end + + def current_migration_number(dirname) #:nodoc: + Dir.glob("#{dirname}/[0-9]*_*.rb").collect{ |f| f.split("_").first.to_i }.max + end + + def next_migration_number(dirname) #:nodoc: + if ActiveRecord::Base.timestamped_migrations + Time.now.utc.strftime("%Y%m%d%H%M%S") + else + "%.3d" % (current_migration_number(dirname) + 1) + end + end + end + + class Base < Rails::Generators::NamedBase + include Migration + end + end +end diff --git a/railties/lib/generators/active_record/migration/migration_generator.rb b/railties/lib/generators/active_record/migration/migration_generator.rb new file mode 100644 index 0000000000..95cc34ba42 --- /dev/null +++ b/railties/lib/generators/active_record/migration/migration_generator.rb @@ -0,0 +1,25 @@ +require 'generators/active_record' + +module ActiveRecord + module Generators + class MigrationGenerator < Base + argument :attributes, :type => :hash, :default => {}, :banner => "field:type field:type" + + def create_migration_file + set_local_assigns! + migration_template "migration.rb", "db/migrate/#{file_name}.rb" + end + + protected + attr_reader :migration_action + + def set_local_assigns! + if file_name =~ /^(add|remove)_.*_(?:to|from)_(.*)/ + @migration_action = $1 + @table_name = $2.pluralize + end + end + + end + end +end diff --git a/railties/lib/generators/active_record/migration/templates/migration.rb b/railties/lib/generators/active_record/migration/templates/migration.rb new file mode 100644 index 0000000000..2851f7cb42 --- /dev/null +++ b/railties/lib/generators/active_record/migration/templates/migration.rb @@ -0,0 +1,11 @@ +class <%= @migration_class_name %> < 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 diff --git a/railties/lib/generators/active_record/model/model_generator.rb b/railties/lib/generators/active_record/model/model_generator.rb new file mode 100644 index 0000000000..59310f6c61 --- /dev/null +++ b/railties/lib/generators/active_record/model/model_generator.rb @@ -0,0 +1,34 @@ +require 'generators/active_record' + +module ActiveRecord + module Generators + class ModelGenerator < Base + argument :attributes, :type => :hash, :default => {}, :banner => "field:type field:type" + + check_class_collision + + conditional_class_options :migration, :timestamps + + class_option :parent, :type => :string, + :desc => "The parent class for the generated model" + + def create_model_file + template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb") + end + + def create_migration_file + if options[:migration] && options[:parent].nil? + file_name = "create_#{file_path.gsub(/\//, '_').pluralize}" + migration_template "migration.rb", "db/migrate/#{file_name}.rb" + end + end + + protected + + def parent_class_name + options[:parent] || "ActiveRecord::Base" + end + + end + end +end diff --git a/railties/lib/generators/active_record/model/templates/migration.rb b/railties/lib/generators/active_record/model/templates/migration.rb new file mode 100644 index 0000000000..542e9db2fc --- /dev/null +++ b/railties/lib/generators/active_record/model/templates/migration.rb @@ -0,0 +1,16 @@ +class <%= @migration_class_name %> < ActiveRecord::Migration + def self.up + create_table :<%= table_name %> do |t| +<% for attribute in attributes -%> + t.<%= attribute.type %> :<%= attribute.name %> +<% end -%> +<% if options[:timestamps] %> + t.timestamps +<% end -%> + end + end + + def self.down + drop_table :<%= table_name %> + end +end diff --git a/railties/lib/generators/active_record/model/templates/model.rb b/railties/lib/generators/active_record/model/templates/model.rb new file mode 100644 index 0000000000..21ae29e9f2 --- /dev/null +++ b/railties/lib/generators/active_record/model/templates/model.rb @@ -0,0 +1,5 @@ +class <%= class_name %> < <%= parent_class_name.classify %> +<% attributes.select {|attr| attr.reference? }.each do |attribute| -%> + belongs_to :<%= attribute.name %> +<% end -%> +end diff --git a/railties/lib/generators/active_record/observer/observer_generator.rb b/railties/lib/generators/active_record/observer/observer_generator.rb new file mode 100644 index 0000000000..fa51c23336 --- /dev/null +++ b/railties/lib/generators/active_record/observer/observer_generator.rb @@ -0,0 +1,13 @@ +require 'generators/active_record' + +module ActiveRecord + module Generators + class ObserverGenerator < Base + check_class_collision :suffix => "Observer" + + def create_observer_file + template 'observer.rb', File.join('app/models', class_path, "#{file_name}_observer.rb") + end + end + end +end diff --git a/railties/lib/generators/active_record/observer/templates/observer.rb b/railties/lib/generators/active_record/observer/templates/observer.rb new file mode 100644 index 0000000000..b9a3004161 --- /dev/null +++ b/railties/lib/generators/active_record/observer/templates/observer.rb @@ -0,0 +1,2 @@ +class <%= class_name %>Observer < ActiveRecord::Observer +end diff --git a/railties/lib/generators/active_record/session_migration/session_migration_generator.rb b/railties/lib/generators/active_record/session_migration/session_migration_generator.rb new file mode 100644 index 0000000000..d60da5c0a5 --- /dev/null +++ b/railties/lib/generators/active_record/session_migration/session_migration_generator.rb @@ -0,0 +1,20 @@ +require 'generators/active_record' + +module ActiveRecord + module Generators + class SessionMigrationGenerator < Base + argument :name, :type => :string, :default => "add_sessions_table" + + def create_migration_file + migration_template "migration.rb", "db/migrate/#{file_name}.rb" + end + + protected + + def session_table_name + ActiveRecord::Base.pluralize_table_names ? 'session'.pluralize : 'session' + end + + end + end +end diff --git a/railties/lib/generators/active_record/session_migration/templates/migration.rb b/railties/lib/generators/active_record/session_migration/templates/migration.rb new file mode 100644 index 0000000000..19811d9455 --- /dev/null +++ b/railties/lib/generators/active_record/session_migration/templates/migration.rb @@ -0,0 +1,16 @@ +class <%= @migration_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 diff --git a/railties/lib/generators/base.rb b/railties/lib/generators/base.rb new file mode 100644 index 0000000000..c1a384647c --- /dev/null +++ b/railties/lib/generators/base.rb @@ -0,0 +1,349 @@ +require 'generators/actions' + +module Rails + module Generators + DEFAULTS = { + :fixture => true, + :helper => true, + :migration => true, + :orm => 'active_record', + :resource_controller => 'controller', + :test_framework => 'test_unit', + :template_engine => 'erb', + :timestamps => true + } + + ALIASES = { + :fixture_replacement => '-r', + :orm => '-o', + :resource_controller => '-c', + :test_framework => '-t', + :template_engine => '-e' + } + + class Error < Thor::Error + end + + class Base < Thor::Group + include Rails::Generators::Actions + include Thor::Actions + + # Automatically sets the source root based on the class name. + # + def self.source_root + @source_root ||= File.expand_path(File.join(File.dirname(__FILE__), base_name, generator_name, 'templates')) + end + + # Tries to get the description from a USAGE file one folder above the source + # root otherwise uses a default description. + # + def self.desc(description=nil) + return super if description + usage = File.expand_path(File.join(source_root, "..", "USAGE")) + + @desc ||= if File.exist?(usage) + File.read(usage) + else + "Description:\n Create #{base_name.humanize.downcase} files for #{generator_name} generator." + end + end + + # Convenience method to get the namespace from the class name. It's the + # same as Thor default except that the Generator at the end of the class + # is removed. + # + def self.namespace(name=nil) + return super if name + @namespace ||= super.sub(/_generator$/, '') + end + + # Invoke a generator based on the value supplied by the user to the + # given option named "name". A class option is created when this method + # is invoked and you can set a hash to customize it, although type and + # default values cannot be given. + # + # ==== Examples + # + # class ControllerGenerator < Rails::Generators::Base + # hook_for :test_framework, :aliases => "-t" + # end + # + # The example above will create a test framework option and will invoke + # a generator based on the user supplied value. + # + # For example, if the user invoke the controller generator as: + # + # ruby script/generate controller Account --test-framework=test_unit + # + # The controller generator will then try to invoke the following generators: + # + # "rails:generators:test_unit", "test_unit:generators:controller", "test_unit" + # + # In this case, the "test_unit:generators:controller" is available and is + # invoked. This allows any test framework to hook into Rails as long as it + # provides any of the hooks above. + # + # Finally, if the user don't want to use any test framework, he can do: + # + # ruby script/generate controller Account --skip-test-framework + # + # Or similarly: + # + # ruby script/generate controller Account --no-test-framework + # + # ==== Custom invocations + # + # You can also supply a block to hook for to customize how the hook is + # going to be invoked. The block receives two parameters, an instance + # of the current class and the klass to be invoked. + # + # For example, in the resource generator, the controller should be invoked + # with a pluralized class name. By default, it is invoked with the same + # name as the resource generator, which is singular. To change this, we + # can give a block to customize how the controller can be invoked. + # + # hook_for :resource_controller do |instance, controller| + # instance.invoke controller, [ instance.name.pluralize ] + # end + # + def self.hook_for(*names, &block) + default_class_options(*names) + options = names.extract_options! + verbose = options.fetch(:verbose, :blue) + + names.each do |name| + invocations << [ name, base_name, generator_name ] + invocation_blocks[name] = block if block_given? + + class_eval <<-METHOD, __FILE__, __LINE__ + def invoke_for_#{name} + return unless options[#{name.inspect}] + + klass = Rails::Generators.find_by_namespace(options[#{name.inspect}], + #{base_name.inspect}, #{generator_name.inspect}) + + if klass + say_status :invoke, options[#{name.inspect}], #{verbose.inspect} + invoke_class_with_block #{name.inspect}, klass + else + say "Could not find and invoke '\#{options[#{name.inspect}]}'." + end + end + METHOD + end + end + + # Invoke a generator with the given name if the user requires it. The + # difference to hook_for is that the class option here is boolean + # and the generator invoked is not based on user input. + # + # A class option is created when this method is invoked and you can set + # a hash to customize it, although type and default values cannot be + # given. + # + # ==== Examples + # + # class ControllerGenerator < Rails::Generators::Base + # invoke_if :webrat, :aliases => "-w" + # end + # + # The example above will create a helper option and will be invoked + # when the user requires so: + # + # ruby script/generate controller Account --webrat + # + # The controller generator will then try to invoke the following generators: + # + # "rails:generators:webrat", "webrat:generators:controller", "webrat" + # + # ==== Custom invocations + # + # This method accepts custom invocations as in hook_for. Check hook_for + # for usage and examples. + # + def self.invoke_if(*names, &block) + conditional_class_options(*names) + options = names.extract_options! + verbose = options.fetch(:verbose, :blue) + + names.each do |name| + invocations << [ name, base_name, generator_name ] + invocation_blocks[name] = block if block_given? + + class_eval <<-METHOD, __FILE__, __LINE__ + def invoke_if_#{name} + return unless options[#{name.inspect}] + + klass = Rails::Generators.find_by_namespace(#{name.inspect}, + #{base_name.inspect}, #{generator_name.inspect}) + + if klass + say_status :invoke, #{name.inspect}, #{verbose.inspect} + invoke_class_with_block #{name.inspect}, klass + else + say "Could not find and invoke '#{name}'." + end + end + METHOD + end + end + + protected + + # This is the common method that both hook_for and invoke_if use to + # invoke a class. It searches for a block in the invocation blocks + # in case the user wants to customize how the class is invoked. + # + def invoke_class_with_block(name, klass) #:nodoc: + if block = self.class.invocation_blocks[name] + block.call(self, klass) + else + invoke klass + end + end + + # Check whether the given class names are already taken by user + # application or Ruby on Rails. + # + def class_collisions(*class_names) + return unless behavior == :invoke + + class_names.flatten.each do |class_name| + class_name = class_name.to_s + next if class_name.strip.empty? + + # Split the class from its module nesting + nesting = class_name.split('::') + last_name = nesting.pop + + # Hack to limit const_defined? to non-inherited on 1.9 + extra = [] + extra << false unless Object.method(:const_defined?).arity == 1 + + # Extract the last Module in the nesting + last = nesting.inject(Object) do |last, nest| + break unless last.const_defined?(nest, *extra) + last.const_get(nest) + end + + if last && last.const_defined?(last_name.camelize, *extra) + raise Error, "The name '#{class_name}' is either already used in your application " << + "or reserved by Ruby on Rails. Please choose an alternative and run " << + "this generator again." + end + end + end + + # Use Rails default banner. + # + def self.banner + "#{$0} #{generator_name} #{self.arguments.map(&:usage).join(' ')} [options]" + end + + # Sets the base_name taking into account the current class namespace. + # + def self.base_name + @base_name ||= self.name.split('::').first.underscore + end + + # Removes the namespaces and get the generator name. For example, + # Rails::Generators::MetalGenerator will return "metal" as generator name. + # + def self.generator_name + @generator_name ||= begin + klass_name = self.name.split('::').last + klass_name.sub!(/Generator$/, '') + klass_name.underscore + end + end + + # Stores invocations for this class merging with superclass values. + # + def self.invocations #:nodoc: + @invocations ||= from_superclass(:invocations, []) + end + + # Stores invocation blocks used on hook_for and invoke_if. + # + def self.invocation_blocks #:nodoc: + @invocation_blocks ||= from_superclass(:invocation_blocks, {}) + end + + # Creates a conditional class option with type boolean, default value + # lookup and default description. + # + def self.conditional_class_options(*names) + default_options = names.extract_options! + + names.each do |name| + options = default_options.dup + options[:desc] ||= "Indicates when to generate #{name.to_s.humanize.downcase}" + class_option name, options.merge!(:type => :boolean, :default => DEFAULTS[name] || false) + end + end + + # Creates a class option with type default, banner, alias lookup and + # description. Used internally by hook_for (ie, not part of plugin API). + # + def self.default_class_options(*names) #:nodoc: + default_options = names.extract_options! + + names.each do |name| + options = default_options.dup + options[:desc] ||= "#{name.to_s.humanize} to be invoked" + options[:banner] ||= "NAME" + options[:aliases] ||= ALIASES[name] + class_option name, options.merge!(:type => :default, :default => DEFAULTS[name]) + end + end + + # Overwrite class options help to allow invoked generators options to be + # shown when invoking a generator. Only first level options and options + # that belongs to the default group are shown. + # + def self.class_options_help(shell, ungrouped_name=nil, extra_group=nil) + klass_options = Thor::CoreExt::OrderedHash.new + + invocations.each do |args| + name, base, generator = args + option = class_options[name] + + klass_name = option.type == :boolean ? name : option.default + next unless klass_name + + klass = Rails::Generators.find_by_namespace(klass_name, base, generator) + next unless klass + + human_name = klass_name.to_s.classify + + klass_options[human_name] ||= [] + klass_options[human_name] += klass.class_options.values.select do |option| + class_options[option.human_name.to_sym].nil? && option.group.nil? + end + end + + klass_options.merge!(extra_group) if extra_group + super(shell, ungrouped_name, klass_options) + end + + # Small macro to add ruby as an option to the generator with proper + # default value plus an instance helper method called shebang. + # + def self.add_shebang_option! + require 'rbconfig' + default = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']) + + class_option :ruby, :type => :string, :aliases => "-r", :default => default, + :desc => "Path to the Ruby binary of your choice", :banner => "PATH" + + class_eval <<-METHOD, __FILE__, __LINE__ + protected + def shebang + "#!\#{options[:ruby] || "/usr/bin/env ruby"}" + end + METHOD + end + + end + end +end diff --git a/railties/lib/generators/erb.rb b/railties/lib/generators/erb.rb new file mode 100644 index 0000000000..da99cec895 --- /dev/null +++ b/railties/lib/generators/erb.rb @@ -0,0 +1,8 @@ +require 'generators/named_base' + +module Erb + module Generators + class Base < Rails::Generators::NamedBase + end + end +end diff --git a/railties/lib/generators/erb/controller/controller_generator.rb b/railties/lib/generators/erb/controller/controller_generator.rb new file mode 100644 index 0000000000..706c92cb91 --- /dev/null +++ b/railties/lib/generators/erb/controller/controller_generator.rb @@ -0,0 +1,21 @@ +require 'generators/erb' + +module Erb + module Generators + class ControllerGenerator < Base + argument :actions, :type => :array, :default => [], :banner => "action action" + + def create_view_files + base_path = File.join('app', 'views', class_path, file_name) + empty_directory base_path + + actions.each do |action| + @action = action + @path = File.join(base_path, "#{action}.html.erb") + + template 'view.html.erb', @path + end + end + end + end +end diff --git a/railties/lib/generators/erb/controller/templates/view.html.erb b/railties/lib/generators/erb/controller/templates/view.html.erb new file mode 100644 index 0000000000..cd54d13d83 --- /dev/null +++ b/railties/lib/generators/erb/controller/templates/view.html.erb @@ -0,0 +1,2 @@ +<h1><%= class_name %>#<%= @action %></h1> +<p>Find me in <%= @path %></p> diff --git a/railties/lib/generators/erb/mailer/mailer_generator.rb b/railties/lib/generators/erb/mailer/mailer_generator.rb new file mode 100644 index 0000000000..398ab46dd8 --- /dev/null +++ b/railties/lib/generators/erb/mailer/mailer_generator.rb @@ -0,0 +1,20 @@ +require 'generators/erb' + +module Erb + module Generators + class MailerGenerator < Base + argument :actions, :type => :array, :default => [], :banner => "method method" + + def create_view_folder + empty_directory File.join("app", "views", file_path) + end + + def create_view_files + actions.each do |action| + @action, @path = action, File.join(file_path, action) + template "view.erb", File.join("app", "views", "#{@path}.erb") + end + end + end + end +end diff --git a/railties/lib/generators/erb/mailer/templates/view.erb b/railties/lib/generators/erb/mailer/templates/view.erb new file mode 100644 index 0000000000..fcce7bd805 --- /dev/null +++ b/railties/lib/generators/erb/mailer/templates/view.erb @@ -0,0 +1,3 @@ +<%= class_name %>#<%= @action %> + +Find me in app/views/<%= @path %> diff --git a/railties/lib/generators/generated_attribute.rb b/railties/lib/generators/generated_attribute.rb new file mode 100644 index 0000000000..7cd1fed8a4 --- /dev/null +++ b/railties/lib/generators/generated_attribute.rb @@ -0,0 +1,43 @@ +module Rails + module Generators + class GeneratedAttribute + attr_accessor :name, :type + + def initialize(name, type) + @name, @type = name, type.to_sym + end + + def field_type + @field_type ||= case type + when :integer, :float, :decimal then :text_field + when :datetime, :timestamp, :time then :datetime_select + when :date then :date_select + when :string then :text_field + when :text then :text_area + when :boolean then :check_box + else + :text_field + end + end + + def default + @default ||= case type + when :integer then 1 + when :float then 1.5 + when :decimal then "9.99" + when :datetime, :timestamp, :time then Time.now.to_s(:db) + when :date then Date.today.to_s(:db) + when :string then "MyString" + when :text then "MyText" + when :boolean then false + else + "" + end + end + + def reference? + [ :references, :belongs_to ].include?(self.type) + end + end + end +end diff --git a/railties/lib/generators/named_base.rb b/railties/lib/generators/named_base.rb new file mode 100644 index 0000000000..9538931a6e --- /dev/null +++ b/railties/lib/generators/named_base.rb @@ -0,0 +1,108 @@ +require 'generators/base' +require 'generators/generated_attribute' + +module Rails + module Generators + class NamedBase < Base + argument :name, :type => :string + + attr_reader :class_name, :singular_name, :plural_name, :table_name, + :class_path, :file_path, :class_nesting, :class_nesting_depth + + alias :file_name :singular_name + + class << self + # Add a class collisions name to be checked on class initialization. You + # can supply a hash with a :prefix or :suffix to be tested. + # + # ==== Examples + # + # check_class_collision :suffix => "Observer" + # + # If the generator is invoked with class name Admin, it will check for + # the presence of "AdminObserver". + # + def check_class_collision(options={}) + @class_collisions = options + end + + # Returns the class collisions for this class and retreives one from + # superclass. The from_superclass method used below is from Thor. + # + def class_collisions #:nodoc: + @class_collisions ||= from_superclass(:class_collisions, nil) + end + end + + def initialize(*args) #:nodoc: + super + assign_names!(self.name) + parse_attributes! if respond_to?(:attributes) + + if self.class.class_collisions + value = add_prefix_and_suffix(class_name, self.class.class_collisions) + class_collisions(value) + end + end + + protected + + def assign_names!(given_name) #:nodoc: + self.name, @class_path, @file_path, @class_nesting, @class_nesting_depth = extract_modules(given_name) + @class_name_without_nesting, @singular_name, @plural_name = inflect_names(self.name) + + @table_name = if !defined?(ActiveRecord::Base) || ActiveRecord::Base.pluralize_table_names + plural_name + else + singular_name + end + @table_name.gsub! '/', '_' + + if @class_nesting.empty? + @class_name = @class_name_without_nesting + else + @table_name = @class_nesting.underscore << "_" << @table_name + @class_name = "#{@class_nesting}::#{@class_name_without_nesting}" + end + end + + # Convert attributes hash into an array with GeneratedAttribute objects. + # + def parse_attributes! #:nodoc: + self.attributes = (attributes || {}).map do |name, type| + Rails::Generators::GeneratedAttribute.new(name, type) + end + end + + # Extract modules from filesystem-style or ruby-style path. Both + # good/fun/stuff and Good::Fun::Stuff produce the same results. + # + def extract_modules(name) #:nodoc: + modules = name.include?('/') ? name.split('/') : name.split('::') + name = modules.pop + path = modules.map { |m| m.underscore } + + file_path = (path + [name.underscore]).join('/') + nesting = modules.map { |m| m.camelize }.join('::') + + [name, path, file_path, nesting, modules.size] + end + + # Receives name and return camelized, underscored and pluralized names. + # + def inflect_names(name) #:nodoc: + camel = name.camelize + under = camel.underscore + plural = under.pluralize + [camel, under, plural] + end + + # Receives a name and add suffix and prefix values frrm hash. + # + def add_prefix_and_suffix(name, hash) #:nodoc: + "#{hash[:prefix]}#{name}#{hash[:suffix]}" + end + + end + end +end diff --git a/railties/lib/rails_generator/generators/applications/app/USAGE b/railties/lib/generators/rails/app/USAGE index 36d6061a59..36d6061a59 100644 --- a/railties/lib/rails_generator/generators/applications/app/USAGE +++ b/railties/lib/generators/rails/app/USAGE diff --git a/railties/lib/generators/rails/app/app_generator.rb b/railties/lib/generators/rails/app/app_generator.rb new file mode 100644 index 0000000000..6bd464a16c --- /dev/null +++ b/railties/lib/generators/rails/app/app_generator.rb @@ -0,0 +1,207 @@ +require 'digest/md5' +require 'active_support/secure_random' + +module Rails::Generators + class AppGenerator < Base + DATABASES = %w( mysql oracle postgresql sqlite2 sqlite3 frontbase ibm_db ) + add_shebang_option! + + argument :app_path, :type => :string + + class_option :database, :type => :string, :aliases => "-d", :default => "sqlite3", + :desc => "Preconfigure for selected database (options: #{DATABASES.join('/')})" + + class_option :freeze, :type => :boolean, :aliases => "-F", :default => false, + :desc => "Freeze Rails in vendor/rails from the gems" + + class_option :template, :type => :string, :aliases => "-m", + :desc => "Path to an application template (can be a filesystem path or URL)." + + class_option :with_dispatchers, :type => :boolean, :aliases => "-D", :default => false, + :desc => "Add CGI/FastCGI/mod_ruby dispatchers code" + + class_option :skip_activerecord, :type => :boolean, :aliases => "-A", :default => false, + :desc => "Skip ActiveRecord files" + + class_option :skip_testunit, :type => :boolean, :aliases => "-U", :default => false, + :desc => "Skip TestUnit files" + + class_option :skip_prototype, :type => :boolean, :aliases => "-P", :default => false, + :desc => "Skip Prototype files" + + # Add Rails options + # + class_option :version, :type => :boolean, :aliases => "-v", :group => :rails, + :desc => "Show Rails version number and quit" + + class_option :help, :type => :boolean, :aliases => "-h", :group => :rails, + :desc => "Show this help message and quit" + + def initialize(*args) + super + if !options[:no_activerecord] && !DATABASES.include?(options[:database]) + raise Error, "Invalid value for --database option. Supported for preconfiguration are: #{DATABASES.join(", ")}." + end + end + + def create_root + self.root = File.expand_path(app_path, root) + empty_directory '.' + + app_name # Sets the app name + FileUtils.cd(root) + end + + def create_root_files + copy_file "Rakefile" + copy_file "README" + end + + def create_app_files + directory "app" + end + + def create_config_files + empty_directory "config" + + inside "config" do + copy_file "boot.rb" + copy_file "routes.rb" + template "environment.rb" + + directory "environments" + directory "initializers" + directory "locales" + end + end + + def create_activerecord_files + return if options[:skip_activerecord] + template "config/databases/#{options[:database]}.yml", "config/database.yml" + end + + def create_db_files + directory "db" + end + + def create_doc_files + directory "doc" + end + + def create_lib_files + empty_directory "lib" + empty_directory "lib/tasks" + end + + def create_log_files + empty_directory "log" + + inside "log" do + %w( server production development test ).each do |file| + create_file "#{file}.log" + chmod "#{file}.log", 0666, false + end + end + end + + def create_public_files + directory "public", "public", false # Non-recursive. Do small steps, so anyone can overwrite it. + end + + def create_dispatch_files + return unless options[:with_dispatchers] + copy_file "dispatchers/config.ru", "config.ru" + + template "dispatchers/dispatch.rb", "public/dispatch.rb" + chmod "public/dispatch.rb", 0755, false + + template "dispatchers/dispatch.rb", "public/dispatch.cgi" + chmod "public/dispatch.cgi", 0755, false + + template "dispatchers/dispatch.fcgi", "public/dispatch.fcgi" + chmod "public/dispatch.fcgi", 0755, false + end + + def create_public_image_files + directory "public/images" + end + + def create_public_stylesheets_files + directory "public/stylesheets" + end + + def create_prototype_files + return if options[:skip_prototype] + directory "public/javascripts" + end + + def create_script_files + directory "script" + chmod "script", 0755, false + end + + def create_test_files + return if options[:skip_testunit] + directory "test" + end + + def create_tmp_files + empty_directory "tmp" + + inside "tmp" do + %w(sessions sockets cache pids).each do |dir| + empty_directory dir + end + end + end + + def create_vendor_files + empty_directory "vendor/plugins" + end + + def apply_rails_template + apply options[:template] if options[:template] + rescue LoadError, Errno::ENOENT => e + raise Error, "The template [#{options[:template]}] could not be loaded. Error: #{e}" + end + + def freeze? + freeze! if options[:freeze] + end + + protected + + # Define file as an alias to create_file for backwards compatibility. + # TODO Add deprecation warning? + # + def file(*args, &block) + create_file(*args, &block) + end + + def app_name + @app_name ||= File.basename(root) + end + + def app_secret + ActiveSupport::SecureRandom.hex(64) + end + + def self.banner + "#{$0} #{self.arguments.map(&:usage).join(' ')} [options]" + end + + def mysql_socket + @mysql_socket ||= [ + "/tmp/mysql.sock", # default + "/var/run/mysqld/mysqld.sock", # debian/gentoo + "/var/tmp/mysql.sock", # freebsd + "/var/lib/mysql/mysql.sock", # fedora + "/opt/local/lib/mysql/mysql.sock", # fedora + "/opt/local/var/run/mysqld/mysqld.sock", # mac + darwinports + mysql + "/opt/local/var/run/mysql4/mysqld.sock", # mac + darwinports + mysql4 + "/opt/local/var/run/mysql5/mysqld.sock", # mac + darwinports + mysql5 + "/opt/lampp/var/mysql/mysql.sock" # xampp for linux + ].find { |f| File.exist?(f) } unless RUBY_PLATFORM =~ /(:?mswin|mingw)/ + end + end +end diff --git a/railties/README b/railties/lib/generators/rails/app/templates/README index 37ec8ea211..37ec8ea211 100644 --- a/railties/README +++ b/railties/lib/generators/rails/app/templates/README diff --git a/railties/fresh_rakefile b/railties/lib/generators/rails/app/templates/Rakefile index 3bb0e8592a..3bb0e8592a 100755 --- a/railties/fresh_rakefile +++ b/railties/lib/generators/rails/app/templates/Rakefile diff --git a/railties/helpers/application_controller.rb b/railties/lib/generators/rails/app/templates/app/controllers/application_controller.rb index 6635a3f487..6635a3f487 100644 --- a/railties/helpers/application_controller.rb +++ b/railties/lib/generators/rails/app/templates/app/controllers/application_controller.rb diff --git a/railties/helpers/application_helper.rb b/railties/lib/generators/rails/app/templates/app/helpers/application_helper.rb index 22a7940eb2..22a7940eb2 100644 --- a/railties/helpers/application_helper.rb +++ b/railties/lib/generators/rails/app/templates/app/helpers/application_helper.rb diff --git a/railties/configs/empty.log b/railties/lib/generators/rails/app/templates/app/models/.empty_directory index e69de29bb2..e69de29bb2 100644 --- a/railties/configs/empty.log +++ b/railties/lib/generators/rails/app/templates/app/models/.empty_directory diff --git a/railties/html/favicon.ico b/railties/lib/generators/rails/app/templates/app/views/layouts/.empty_directory index e69de29bb2..e69de29bb2 100644 --- a/railties/html/favicon.ico +++ b/railties/lib/generators/rails/app/templates/app/views/layouts/.empty_directory diff --git a/railties/environments/boot.rb b/railties/lib/generators/rails/app/templates/config/boot.rb index 0ad0f787f8..0ad0f787f8 100644 --- a/railties/environments/boot.rb +++ b/railties/lib/generators/rails/app/templates/config/boot.rb diff --git a/railties/configs/databases/frontbase.yml b/railties/lib/generators/rails/app/templates/config/databases/frontbase.yml index c0c3588be1..c0c3588be1 100644 --- a/railties/configs/databases/frontbase.yml +++ b/railties/lib/generators/rails/app/templates/config/databases/frontbase.yml diff --git a/railties/configs/databases/ibm_db.yml b/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml index a9716ddb44..a9716ddb44 100644 --- a/railties/configs/databases/ibm_db.yml +++ b/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml diff --git a/railties/configs/databases/mysql.yml b/railties/lib/generators/rails/app/templates/config/databases/mysql.yml index 1a14bfb332..6bf2f7b1fd 100644 --- a/railties/configs/databases/mysql.yml +++ b/railties/lib/generators/rails/app/templates/config/databases/mysql.yml @@ -22,8 +22,8 @@ development: pool: 5 username: root password: -<% if socket -%> - socket: <%= socket %> +<% if mysql_socket -%> + socket: <%= mysql_socket %> <% else -%> host: localhost <% end -%> @@ -39,8 +39,8 @@ test: pool: 5 username: root password: -<% if socket -%> - socket: <%= socket %> +<% if mysql_socket -%> + socket: <%= mysql_socket %> <% else -%> host: localhost <% end -%> @@ -53,8 +53,8 @@ production: pool: 5 username: root password: -<% if socket -%> - socket: <%= socket %> +<% if mysql_socket -%> + socket: <%= mysql_socket %> <% else -%> host: localhost <% end -%> diff --git a/railties/configs/databases/oracle.yml b/railties/lib/generators/rails/app/templates/config/databases/oracle.yml index a1883f6256..a1883f6256 100644 --- a/railties/configs/databases/oracle.yml +++ b/railties/lib/generators/rails/app/templates/config/databases/oracle.yml diff --git a/railties/configs/databases/postgresql.yml b/railties/lib/generators/rails/app/templates/config/databases/postgresql.yml index f600e054cf..f600e054cf 100644 --- a/railties/configs/databases/postgresql.yml +++ b/railties/lib/generators/rails/app/templates/config/databases/postgresql.yml diff --git a/railties/configs/databases/sqlite2.yml b/railties/lib/generators/rails/app/templates/config/databases/sqlite2.yml index 46f01cb42c..46f01cb42c 100644 --- a/railties/configs/databases/sqlite2.yml +++ b/railties/lib/generators/rails/app/templates/config/databases/sqlite2.yml diff --git a/railties/configs/databases/sqlite3.yml b/railties/lib/generators/rails/app/templates/config/databases/sqlite3.yml index 025d62a8d8..025d62a8d8 100644 --- a/railties/configs/databases/sqlite3.yml +++ b/railties/lib/generators/rails/app/templates/config/databases/sqlite3.yml diff --git a/railties/environments/environment.rb b/railties/lib/generators/rails/app/templates/config/environment.rb index 4a2df36307..84c5abf1e9 100644 --- a/railties/environments/environment.rb +++ b/railties/lib/generators/rails/app/templates/config/environment.rb @@ -1,7 +1,7 @@ # Be sure to restart your server when you modify this file # Specifies gem version of Rails to use when vendor/rails is not present -<%= '# ' if freeze %>RAILS_GEM_VERSION = '<%= Rails::VERSION::STRING %>' unless defined? RAILS_GEM_VERSION +<%= '# ' if options[:freeze] %>RAILS_GEM_VERSION = '<%= Rails::VERSION::STRING %>' unless defined? RAILS_GEM_VERSION # Bootstrap the Rails environment, frameworks, and default configuration require File.join(File.dirname(__FILE__), 'boot') @@ -26,10 +26,14 @@ Rails::Initializer.run do |config| # Skip frameworks you're not going to use. To use Rails without a database, # you must remove the Active Record framework. +<% if options[:skip_activerecord] -%> + config.frameworks -= [ :active_record ] +<% else -%> # config.frameworks -= [ :active_record, :active_resource, :action_mailer ] # Activate observers that should always be running # config.active_record.observers = :cacher, :garbage_collector, :forum_observer +<% end -%> # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. # Run "rake -D time" for a list of tasks for finding time zone names. @@ -38,4 +42,4 @@ Rails::Initializer.run do |config| # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')] # config.i18n.default_locale = :de -end
\ No newline at end of file +end diff --git a/railties/environments/development.rb b/railties/lib/generators/rails/app/templates/config/environments/development.rb index 85c9a6080e..85c9a6080e 100644 --- a/railties/environments/development.rb +++ b/railties/lib/generators/rails/app/templates/config/environments/development.rb diff --git a/railties/environments/production.rb b/railties/lib/generators/rails/app/templates/config/environments/production.rb index 1fc9f6b923..1fc9f6b923 100644 --- a/railties/environments/production.rb +++ b/railties/lib/generators/rails/app/templates/config/environments/production.rb diff --git a/railties/environments/test.rb b/railties/lib/generators/rails/app/templates/config/environments/test.rb index 496eb9572b..496eb9572b 100644 --- a/railties/environments/test.rb +++ b/railties/lib/generators/rails/app/templates/config/environments/test.rb diff --git a/railties/configs/initializers/backtrace_silencers.rb b/railties/lib/generators/rails/app/templates/config/initializers/backtrace_silencers.rb index 839d4cde19..839d4cde19 100644 --- a/railties/configs/initializers/backtrace_silencers.rb +++ b/railties/lib/generators/rails/app/templates/config/initializers/backtrace_silencers.rb diff --git a/railties/configs/initializers/inflections.rb b/railties/lib/generators/rails/app/templates/config/initializers/inflections.rb index d531b8bb82..d531b8bb82 100644 --- a/railties/configs/initializers/inflections.rb +++ b/railties/lib/generators/rails/app/templates/config/initializers/inflections.rb diff --git a/railties/configs/initializers/mime_types.rb b/railties/lib/generators/rails/app/templates/config/initializers/mime_types.rb index 72aca7e441..72aca7e441 100644 --- a/railties/configs/initializers/mime_types.rb +++ b/railties/lib/generators/rails/app/templates/config/initializers/mime_types.rb diff --git a/railties/configs/initializers/new_rails_defaults.rb b/railties/lib/generators/rails/app/templates/config/initializers/new_rails_defaults.rb index 8ec3186c84..8ec3186c84 100644 --- a/railties/configs/initializers/new_rails_defaults.rb +++ b/railties/lib/generators/rails/app/templates/config/initializers/new_rails_defaults.rb diff --git a/railties/configs/initializers/session_store.rb b/railties/lib/generators/rails/app/templates/config/initializers/session_store.rb.tt index 4499ab84b6..4499ab84b6 100644 --- a/railties/configs/initializers/session_store.rb +++ b/railties/lib/generators/rails/app/templates/config/initializers/session_store.rb.tt diff --git a/railties/configs/locales/en.yml b/railties/lib/generators/rails/app/templates/config/locales/en.yml index f265c068d8..f265c068d8 100644 --- a/railties/configs/locales/en.yml +++ b/railties/lib/generators/rails/app/templates/config/locales/en.yml diff --git a/railties/configs/routes.rb b/railties/lib/generators/rails/app/templates/config/routes.rb index ea14ce1bfc..ea14ce1bfc 100644 --- a/railties/configs/routes.rb +++ b/railties/lib/generators/rails/app/templates/config/routes.rb diff --git a/railties/configs/seeds.rb b/railties/lib/generators/rails/app/templates/db/seeds.rb index 3174d0cb8a..3174d0cb8a 100644 --- a/railties/configs/seeds.rb +++ b/railties/lib/generators/rails/app/templates/db/seeds.rb diff --git a/railties/dispatches/config.ru b/railties/lib/generators/rails/app/templates/dispatchers/config.ru index acbfe4e9ae..acbfe4e9ae 100644 --- a/railties/dispatches/config.ru +++ b/railties/lib/generators/rails/app/templates/dispatchers/config.ru diff --git a/railties/dispatches/dispatch.fcgi b/railties/lib/generators/rails/app/templates/dispatchers/dispatch.fcgi index 664dbbbee8..f5b3b71875 100755 --- a/railties/dispatches/dispatch.fcgi +++ b/railties/lib/generators/rails/app/templates/dispatchers/dispatch.fcgi @@ -1,4 +1,4 @@ -#!/usr/bin/env ruby +<%= shebang %> # # You may specify the path to the FastCGI crash log (a log of unhandled # exceptions which forced the FastCGI instance to exit, great for debugging) diff --git a/railties/dispatches/dispatch.rb b/railties/lib/generators/rails/app/templates/dispatchers/dispatch.rb index 32fa3b2665..48e888113a 100755 --- a/railties/dispatches/dispatch.rb +++ b/railties/lib/generators/rails/app/templates/dispatchers/dispatch.rb @@ -1,4 +1,4 @@ -#!/usr/bin/env ruby +<%= shebang %> require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT) diff --git a/railties/dispatches/gateway.cgi b/railties/lib/generators/rails/app/templates/dispatchers/gateway.cgi index 0305b7f810..bdc1055a22 100755 --- a/railties/dispatches/gateway.cgi +++ b/railties/lib/generators/rails/app/templates/dispatchers/gateway.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/env ruby +<%= shebang %> require 'drb' diff --git a/railties/doc/README_FOR_APP b/railties/lib/generators/rails/app/templates/doc/README_FOR_APP index fe41f5cc24..fe41f5cc24 100644 --- a/railties/doc/README_FOR_APP +++ b/railties/lib/generators/rails/app/templates/doc/README_FOR_APP diff --git a/railties/html/404.html b/railties/lib/generators/rails/app/templates/public/404.html index eff660b90c..eff660b90c 100644 --- a/railties/html/404.html +++ b/railties/lib/generators/rails/app/templates/public/404.html diff --git a/railties/html/422.html b/railties/lib/generators/rails/app/templates/public/422.html index b54e4a3cad..b54e4a3cad 100644 --- a/railties/html/422.html +++ b/railties/lib/generators/rails/app/templates/public/422.html diff --git a/railties/html/500.html b/railties/lib/generators/rails/app/templates/public/500.html index ec3bbf02c4..ec3bbf02c4 100644 --- a/railties/html/500.html +++ b/railties/lib/generators/rails/app/templates/public/500.html diff --git a/railties/lib/generators/rails/app/templates/public/favicon.ico b/railties/lib/generators/rails/app/templates/public/favicon.ico new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/railties/lib/generators/rails/app/templates/public/favicon.ico diff --git a/railties/html/images/rails.png b/railties/lib/generators/rails/app/templates/public/images/rails.png Binary files differindex d5edc04e65..d5edc04e65 100644 --- a/railties/html/images/rails.png +++ b/railties/lib/generators/rails/app/templates/public/images/rails.png diff --git a/railties/html/index.html b/railties/lib/generators/rails/app/templates/public/index.html index cd337dc74c..cd337dc74c 100644 --- a/railties/html/index.html +++ b/railties/lib/generators/rails/app/templates/public/index.html diff --git a/railties/html/javascripts/application.js b/railties/lib/generators/rails/app/templates/public/javascripts/application.js index fe4577696b..fe4577696b 100644 --- a/railties/html/javascripts/application.js +++ b/railties/lib/generators/rails/app/templates/public/javascripts/application.js diff --git a/railties/html/javascripts/controls.js b/railties/lib/generators/rails/app/templates/public/javascripts/controls.js index ca29aefdd1..ca29aefdd1 100644 --- a/railties/html/javascripts/controls.js +++ b/railties/lib/generators/rails/app/templates/public/javascripts/controls.js diff --git a/railties/html/javascripts/dragdrop.js b/railties/lib/generators/rails/app/templates/public/javascripts/dragdrop.js index 07229f986f..07229f986f 100644 --- a/railties/html/javascripts/dragdrop.js +++ b/railties/lib/generators/rails/app/templates/public/javascripts/dragdrop.js diff --git a/railties/html/javascripts/effects.js b/railties/lib/generators/rails/app/templates/public/javascripts/effects.js index 5a639d2dea..5a639d2dea 100644 --- a/railties/html/javascripts/effects.js +++ b/railties/lib/generators/rails/app/templates/public/javascripts/effects.js diff --git a/railties/html/javascripts/prototype.js b/railties/lib/generators/rails/app/templates/public/javascripts/prototype.js index dfe8ab4e13..dfe8ab4e13 100644 --- a/railties/html/javascripts/prototype.js +++ b/railties/lib/generators/rails/app/templates/public/javascripts/prototype.js diff --git a/railties/html/robots.txt b/railties/lib/generators/rails/app/templates/public/robots.txt index 085187fa58..085187fa58 100644 --- a/railties/html/robots.txt +++ b/railties/lib/generators/rails/app/templates/public/robots.txt diff --git a/railties/lib/generators/rails/app/templates/public/stylesheets/.empty_directory b/railties/lib/generators/rails/app/templates/public/stylesheets/.empty_directory new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/railties/lib/generators/rails/app/templates/public/stylesheets/.empty_directory diff --git a/railties/bin/about b/railties/lib/generators/rails/app/templates/script/about.tt index ed8deb0dfc..9604485fd2 100755 --- a/railties/bin/about +++ b/railties/lib/generators/rails/app/templates/script/about.tt @@ -1,4 +1,4 @@ -#!/usr/bin/env ruby +<%= shebang %> require File.dirname(__FILE__) + '/../config/boot' $LOAD_PATH.unshift "#{RAILTIES_PATH}/builtin/rails_info" -require 'commands/about'
\ No newline at end of file +require 'commands/about' diff --git a/railties/bin/console b/railties/lib/generators/rails/app/templates/script/console.tt index 498077ab33..307b7c09c4 100755 --- a/railties/bin/console +++ b/railties/lib/generators/rails/app/templates/script/console.tt @@ -1,3 +1,3 @@ -#!/usr/bin/env ruby +<%= shebang %> require File.dirname(__FILE__) + '/../config/boot' require 'commands/console' diff --git a/railties/bin/dbconsole b/railties/lib/generators/rails/app/templates/script/dbconsole.tt index caa60ce829..7ce41645a6 100755 --- a/railties/bin/dbconsole +++ b/railties/lib/generators/rails/app/templates/script/dbconsole.tt @@ -1,3 +1,3 @@ -#!/usr/bin/env ruby +<%= shebang %> require File.dirname(__FILE__) + '/../config/boot' require 'commands/dbconsole' diff --git a/railties/bin/destroy b/railties/lib/generators/rails/app/templates/script/destroy.tt index a4df765a39..9f22a9dbca 100755 --- a/railties/bin/destroy +++ b/railties/lib/generators/rails/app/templates/script/destroy.tt @@ -1,3 +1,3 @@ -#!/usr/bin/env ruby +<%= shebang %> require File.dirname(__FILE__) + '/../config/boot' require 'commands/destroy' diff --git a/railties/bin/generate b/railties/lib/generators/rails/app/templates/script/generate.tt index 173a9f147d..9a9e17ab29 100755 --- a/railties/bin/generate +++ b/railties/lib/generators/rails/app/templates/script/generate.tt @@ -1,3 +1,3 @@ -#!/usr/bin/env ruby +<%= shebang %> require File.dirname(__FILE__) + '/../config/boot' require 'commands/generate' diff --git a/railties/bin/performance/benchmarker b/railties/lib/generators/rails/app/templates/script/performance/benchmarker.tt index c842d35d33..3abf448c15 100755 --- a/railties/bin/performance/benchmarker +++ b/railties/lib/generators/rails/app/templates/script/performance/benchmarker.tt @@ -1,3 +1,3 @@ -#!/usr/bin/env ruby +<%= shebang %> require File.dirname(__FILE__) + '/../../config/boot' require 'commands/performance/benchmarker' diff --git a/railties/bin/performance/profiler b/railties/lib/generators/rails/app/templates/script/performance/profiler.tt index d855ac8b13..66f851a079 100755 --- a/railties/bin/performance/profiler +++ b/railties/lib/generators/rails/app/templates/script/performance/profiler.tt @@ -1,3 +1,3 @@ -#!/usr/bin/env ruby +<%= shebang %> require File.dirname(__FILE__) + '/../../config/boot' require 'commands/performance/profiler' diff --git a/railties/bin/plugin b/railties/lib/generators/rails/app/templates/script/plugin.tt index 87cd2070fe..f0603c33c4 100755 --- a/railties/bin/plugin +++ b/railties/lib/generators/rails/app/templates/script/plugin.tt @@ -1,3 +1,3 @@ -#!/usr/bin/env ruby +<%= shebang %> require File.dirname(__FILE__) + '/../config/boot' require 'commands/plugin' diff --git a/railties/bin/runner b/railties/lib/generators/rails/app/templates/script/runner.tt index a4a7cb25ba..7302825f6c 100755 --- a/railties/bin/runner +++ b/railties/lib/generators/rails/app/templates/script/runner.tt @@ -1,3 +1,3 @@ -#!/usr/bin/env ruby +<%= shebang %> require File.dirname(__FILE__) + '/../config/boot' require 'commands/runner' diff --git a/railties/bin/server b/railties/lib/generators/rails/app/templates/script/server.tt index 3c67f39b69..893db31a20 100755 --- a/railties/bin/server +++ b/railties/lib/generators/rails/app/templates/script/server.tt @@ -1,3 +1,3 @@ -#!/usr/bin/env ruby +<%= shebang %> require File.dirname(__FILE__) + '/../config/boot' require 'commands/server' diff --git a/railties/lib/generators/rails/app/templates/test/fixtures/.empty_directory b/railties/lib/generators/rails/app/templates/test/fixtures/.empty_directory new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/railties/lib/generators/rails/app/templates/test/fixtures/.empty_directory diff --git a/railties/lib/generators/rails/app/templates/test/functional/.empty_directory b/railties/lib/generators/rails/app/templates/test/functional/.empty_directory new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/railties/lib/generators/rails/app/templates/test/functional/.empty_directory diff --git a/railties/lib/generators/rails/app/templates/test/integration/.empty_directory b/railties/lib/generators/rails/app/templates/test/integration/.empty_directory new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/railties/lib/generators/rails/app/templates/test/integration/.empty_directory diff --git a/railties/helpers/performance_test.rb b/railties/lib/generators/rails/app/templates/test/performance/performance_test.rb index 4b60558b43..4b60558b43 100644 --- a/railties/helpers/performance_test.rb +++ b/railties/lib/generators/rails/app/templates/test/performance/performance_test.rb diff --git a/railties/helpers/test_helper.rb b/railties/lib/generators/rails/app/templates/test/test_helper.rb index b9fe2517c8..b9fe2517c8 100644 --- a/railties/helpers/test_helper.rb +++ b/railties/lib/generators/rails/app/templates/test/test_helper.rb diff --git a/railties/lib/generators/rails/app/templates/test/unit/.empty_directory b/railties/lib/generators/rails/app/templates/test/unit/.empty_directory new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/railties/lib/generators/rails/app/templates/test/unit/.empty_directory diff --git a/railties/lib/generators/rails/controller/USAGE b/railties/lib/generators/rails/controller/USAGE new file mode 100644 index 0000000000..6ed4b2edfc --- /dev/null +++ b/railties/lib/generators/rails/controller/USAGE @@ -0,0 +1,18 @@ +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 and invokes helper, + template engine and test framework generators. + +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 diff --git a/railties/lib/generators/rails/controller/controller_generator.rb b/railties/lib/generators/rails/controller/controller_generator.rb new file mode 100644 index 0000000000..3fed058c00 --- /dev/null +++ b/railties/lib/generators/rails/controller/controller_generator.rb @@ -0,0 +1,15 @@ +module Rails + module Generators + class ControllerGenerator < NamedBase + argument :actions, :type => :array, :default => [], :banner => "action action" + check_class_collision :suffix => "Controller" + + def create_controller_files + template 'controller.rb', File.join('app/controllers', class_path, "#{file_name}_controller.rb") + end + + hook_for :template_engine, :test_framework + invoke_if :helper + end + end +end diff --git a/railties/lib/generators/rails/controller/templates/controller.rb b/railties/lib/generators/rails/controller/templates/controller.rb new file mode 100644 index 0000000000..cda2659e69 --- /dev/null +++ b/railties/lib/generators/rails/controller/templates/controller.rb @@ -0,0 +1,7 @@ +class <%= class_name %>Controller < ApplicationController +<% for action in actions -%> + def <%= action %> + end + +<% end -%> +end diff --git a/railties/lib/generators/rails/helper/USAGE b/railties/lib/generators/rails/helper/USAGE new file mode 100644 index 0000000000..531c9b390a --- /dev/null +++ b/railties/lib/generators/rails/helper/USAGE @@ -0,0 +1,17 @@ +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 invokes the configured + test framework. + +Example: + `./script/generate helper CreditCard` + + Credit card helper. + Helper: app/helpers/credit_card_helper.rb + Test: test/unit/helpers/credit_card_helper_test.rb + diff --git a/railties/lib/generators/rails/helper/helper_generator.rb b/railties/lib/generators/rails/helper/helper_generator.rb new file mode 100644 index 0000000000..ad66388591 --- /dev/null +++ b/railties/lib/generators/rails/helper/helper_generator.rb @@ -0,0 +1,13 @@ +module Rails + module Generators + class HelperGenerator < NamedBase + check_class_collision :suffix => "Helper" + + def create_helper_files + template 'helper.rb', File.join('app/helpers', class_path, "#{file_name}_helper.rb") + end + + hook_for :test_framework + end + end +end diff --git a/railties/lib/generators/rails/helper/templates/helper.rb b/railties/lib/generators/rails/helper/templates/helper.rb new file mode 100644 index 0000000000..3fe2ecdc74 --- /dev/null +++ b/railties/lib/generators/rails/helper/templates/helper.rb @@ -0,0 +1,2 @@ +module <%= class_name %>Helper +end diff --git a/railties/lib/generators/rails/integration_test/USAGE b/railties/lib/generators/rails/integration_test/USAGE new file mode 100644 index 0000000000..b76c35a702 --- /dev/null +++ b/railties/lib/generators/rails/integration_test/USAGE @@ -0,0 +1,10 @@ +Description: + Stubs out a new integration test. Pass the name of the test, either + CamelCased or under_scored, as an argument. + + This generator invokes the current integration tool, which defaults to + TestUnit. + +Example: + `./script/generate integration_test GeneralStories` creates a GeneralStories + integration test in test/integration/general_stories_test.rb diff --git a/railties/lib/generators/rails/integration_test/integration_test_generator.rb b/railties/lib/generators/rails/integration_test/integration_test_generator.rb new file mode 100644 index 0000000000..b45ef1597c --- /dev/null +++ b/railties/lib/generators/rails/integration_test/integration_test_generator.rb @@ -0,0 +1,11 @@ +module Rails + module Generators + class IntegrationTestGenerator < NamedBase + check_class_collision :suffix => "Test" + + def create_test_files + template 'integration_test.rb', File.join('test/integration', class_path, "#{file_name}_test.rb") + end + end + end +end diff --git a/railties/lib/generators/rails/integration_test/templates/integration_test.rb b/railties/lib/generators/rails/integration_test/templates/integration_test.rb new file mode 100644 index 0000000000..2c57158b1c --- /dev/null +++ b/railties/lib/generators/rails/integration_test/templates/integration_test.rb @@ -0,0 +1,10 @@ +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 diff --git a/railties/lib/generators/rails/mailer/USAGE b/railties/lib/generators/rails/mailer/USAGE new file mode 100644 index 0000000000..c56095b2c8 --- /dev/null +++ b/railties/lib/generators/rails/mailer/USAGE @@ -0,0 +1,15 @@ +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 and invokes your template + engine and test framework generators. + +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 [...] diff --git a/railties/lib/generators/rails/mailer/mailer_generator.rb b/railties/lib/generators/rails/mailer/mailer_generator.rb new file mode 100644 index 0000000000..33f1665b83 --- /dev/null +++ b/railties/lib/generators/rails/mailer/mailer_generator.rb @@ -0,0 +1,14 @@ +module Rails + module Generators + class MailerGenerator < NamedBase + argument :actions, :type => :array, :default => [], :banner => "method method" + check_class_collision + + def create_mailer_file + template "mailer.rb", File.join('app/models', class_path, "#{file_name}.rb") + end + + hook_for :template_engine, :test_framework + end + end +end diff --git a/railties/lib/generators/rails/mailer/templates/mailer.rb b/railties/lib/generators/rails/mailer/templates/mailer.rb new file mode 100644 index 0000000000..ce15ae9de9 --- /dev/null +++ b/railties/lib/generators/rails/mailer/templates/mailer.rb @@ -0,0 +1,15 @@ +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 diff --git a/railties/lib/generators/rails/metal/USAGE b/railties/lib/generators/rails/metal/USAGE new file mode 100644 index 0000000000..123ec6c03f --- /dev/null +++ b/railties/lib/generators/rails/metal/USAGE @@ -0,0 +1,8 @@ +Description: + Cast some metal! + +Examples: + `./script/generate metal poller` + + This will create: + Metal: app/metal/poller.rb diff --git a/railties/lib/generators/rails/metal/metal_generator.rb b/railties/lib/generators/rails/metal/metal_generator.rb new file mode 100644 index 0000000000..d814b6c38b --- /dev/null +++ b/railties/lib/generators/rails/metal/metal_generator.rb @@ -0,0 +1,11 @@ +module Rails + module Generators + class MetalGenerator < NamedBase + check_class_collision + + def create_file + template "metal.rb", "app/metal/#{file_name}.rb" + end + end + end +end diff --git a/railties/lib/generators/rails/metal/templates/metal.rb b/railties/lib/generators/rails/metal/templates/metal.rb new file mode 100644 index 0000000000..e94982b69a --- /dev/null +++ b/railties/lib/generators/rails/metal/templates/metal.rb @@ -0,0 +1,12 @@ +# 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 diff --git a/railties/lib/generators/rails/migration/USAGE b/railties/lib/generators/rails/migration/USAGE new file mode 100644 index 0000000000..d91127aac3 --- /dev/null +++ b/railties/lib/generators/rails/migration/USAGE @@ -0,0 +1,29 @@ +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 diff --git a/railties/lib/generators/rails/migration/migration_generator.rb b/railties/lib/generators/rails/migration/migration_generator.rb new file mode 100644 index 0000000000..cfaa5f0ad2 --- /dev/null +++ b/railties/lib/generators/rails/migration/migration_generator.rb @@ -0,0 +1,8 @@ +module Rails + module Generators + class MigrationGenerator < NamedBase + argument :attributes, :type => :hash, :default => {}, :banner => "field:type field:type" + hook_for :orm + end + end +end diff --git a/railties/lib/generators/rails/model/USAGE b/railties/lib/generators/rails/model/USAGE new file mode 100644 index 0000000000..b056d5df8b --- /dev/null +++ b/railties/lib/generators/rails/model/USAGE @@ -0,0 +1,30 @@ +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 field: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 generator invokes your configured ORM and test framework, which + defaults to ActiveRecord and TestUnit. + + Finally, if --parent option is given, it's used as superclass of the + created model. This allows you create Single Table Inheritance models. + +Examples: + `./script/generate model account` + + For ActiveRecord and TestUnit it creates: + + 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. diff --git a/railties/lib/generators/rails/model/model_generator.rb b/railties/lib/generators/rails/model/model_generator.rb new file mode 100644 index 0000000000..36354c5638 --- /dev/null +++ b/railties/lib/generators/rails/model/model_generator.rb @@ -0,0 +1,8 @@ +module Rails + module Generators + class ModelGenerator < NamedBase + argument :attributes, :type => :hash, :default => {}, :banner => "field:type field:type" + hook_for :orm, :test_framework + end + end +end diff --git a/railties/lib/generators/rails/model_subclass/model_subclass_generator.rb b/railties/lib/generators/rails/model_subclass/model_subclass_generator.rb new file mode 100644 index 0000000000..4649709780 --- /dev/null +++ b/railties/lib/generators/rails/model_subclass/model_subclass_generator.rb @@ -0,0 +1,11 @@ +module Rails + module Generators + class ModelSubclassGenerator < Base + desc "model_subclass is deprecated. Invoke model with --parent option instead." + + def say_deprecation_warn + say self.class.desc + end + end + end +end diff --git a/railties/lib/generators/rails/observer/USAGE b/railties/lib/generators/rails/observer/USAGE new file mode 100644 index 0000000000..9a20f55a89 --- /dev/null +++ b/railties/lib/generators/rails/observer/USAGE @@ -0,0 +1,12 @@ +Description: + Stubs out a new observer. Pass the observer name, either CamelCased or + under_scored, as an argument. + + This generator only invokes your ORM and test framework generators. + +Example: + `./script/generate observer Account` + + For ActiveRecord and TestUnit it creates: + Observer: app/models/account_observer.rb + TestUnit: test/unit/account_observer_test.rb diff --git a/railties/lib/generators/rails/observer/observer_generator.rb b/railties/lib/generators/rails/observer/observer_generator.rb new file mode 100644 index 0000000000..e33247959b --- /dev/null +++ b/railties/lib/generators/rails/observer/observer_generator.rb @@ -0,0 +1,7 @@ +module Rails + module Generators + class ObserverGenerator < NamedBase + hook_for :orm, :test_framework + end + end +end diff --git a/railties/lib/generators/rails/performance_test/USAGE b/railties/lib/generators/rails/performance_test/USAGE new file mode 100644 index 0000000000..ee82578cdb --- /dev/null +++ b/railties/lib/generators/rails/performance_test/USAGE @@ -0,0 +1,10 @@ +Description: + Stubs out a new performance test. Pass the name of the test, either + CamelCased or under_scored, as an argument. + + This generator invokes the current performance tool, which defaults to + TestUnit. + +Example: + `./script/generate performance_test GeneralStories` creates a GeneralStories + performance test in test/performance/general_stories_test.rb diff --git a/railties/lib/generators/rails/performance_test/performance_test_generator.rb b/railties/lib/generators/rails/performance_test/performance_test_generator.rb new file mode 100644 index 0000000000..b8efda8df3 --- /dev/null +++ b/railties/lib/generators/rails/performance_test/performance_test_generator.rb @@ -0,0 +1,11 @@ +module Rails + module Generators + class PerformanceTestGenerator < NamedBase + check_class_collision :suffix => "Test" + + def create_test_files + template 'performance_test.rb', File.join('test/performance', class_path, "#{file_name}_test.rb") + end + end + end +end diff --git a/railties/lib/generators/rails/performance_test/templates/performance_test.rb b/railties/lib/generators/rails/performance_test/templates/performance_test.rb new file mode 100644 index 0000000000..27c91b0fca --- /dev/null +++ b/railties/lib/generators/rails/performance_test/templates/performance_test.rb @@ -0,0 +1,9 @@ +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 diff --git a/railties/lib/generators/rails/plugin/USAGE b/railties/lib/generators/rails/plugin/USAGE new file mode 100644 index 0000000000..8a17fa4dec --- /dev/null +++ b/railties/lib/generators/rails/plugin/USAGE @@ -0,0 +1,13 @@ +Description: + Stubs out a new plugin at vendor/plugins. Pass the plugin name, either + CamelCased or under_scored, as an argument. + +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 diff --git a/railties/lib/generators/rails/plugin/plugin_generator.rb b/railties/lib/generators/rails/plugin/plugin_generator.rb new file mode 100644 index 0000000000..c2583ee147 --- /dev/null +++ b/railties/lib/generators/rails/plugin/plugin_generator.rb @@ -0,0 +1,41 @@ +module Rails + module Generators + class PluginGenerator < NamedBase + class_option :with_tasks, :type => :boolean, :aliases => "-r", :default => false, + :desc => "When supplied creates tasks base files." + + class_option :with_generator, :type => :boolean, :aliases => "-g", :default => false, + :desc => "When supplied creates generator base files." + + check_class_collision + + def create_root + self.root = File.expand_path("vendor/plugins/#{file_name}", root) + empty_directory '.' + FileUtils.cd(root) + end + + def create_root_files + %w(README MIT-LICENSE Rakefile init.rb install.rb uninstall.rb).each do |file| + template file + end + end + + def create_lib_files + directory 'lib' + end + + hook_for :test_framework + + def create_tasks_files + return unless options[:with_tasks] + directory 'tasks' + end + + def create_generator_files + return unless options[:with_generator] + directory 'generators' + end + end + end +end diff --git a/railties/lib/generators/rails/plugin/templates/MIT-LICENSE b/railties/lib/generators/rails/plugin/templates/MIT-LICENSE new file mode 100644 index 0000000000..8717df053d --- /dev/null +++ b/railties/lib/generators/rails/plugin/templates/MIT-LICENSE @@ -0,0 +1,20 @@ +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. diff --git a/railties/lib/generators/rails/plugin/templates/README b/railties/lib/generators/rails/plugin/templates/README new file mode 100644 index 0000000000..702db07cb1 --- /dev/null +++ b/railties/lib/generators/rails/plugin/templates/README @@ -0,0 +1,13 @@ +<%= 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 diff --git a/railties/lib/generators/rails/plugin/templates/Rakefile b/railties/lib/generators/rails/plugin/templates/Rakefile new file mode 100644 index 0000000000..85e8ff1834 --- /dev/null +++ b/railties/lib/generators/rails/plugin/templates/Rakefile @@ -0,0 +1,23 @@ +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 diff --git a/railties/lib/generators/rails/plugin/templates/generators/%file_name%/%file_name%_generator.rb.tt b/railties/lib/generators/rails/plugin/templates/generators/%file_name%/%file_name%_generator.rb.tt new file mode 100644 index 0000000000..90aa557eeb --- /dev/null +++ b/railties/lib/generators/rails/plugin/templates/generators/%file_name%/%file_name%_generator.rb.tt @@ -0,0 +1,2 @@ +class <%= class_name %>Generator < Rails::Generators::NamedBase +end diff --git a/railties/lib/generators/rails/plugin/templates/generators/%file_name%/USAGE.tt b/railties/lib/generators/rails/plugin/templates/generators/%file_name%/USAGE.tt new file mode 100644 index 0000000000..ea9f4f12cc --- /dev/null +++ b/railties/lib/generators/rails/plugin/templates/generators/%file_name%/USAGE.tt @@ -0,0 +1,8 @@ +Description: + Explain the generator + +Example: + ./script/generate <%= file_name %> Thing + + This will create: + what/will/it/create diff --git a/railties/lib/generators/rails/plugin/templates/generators/%file_name%/templates/.empty_directory b/railties/lib/generators/rails/plugin/templates/generators/%file_name%/templates/.empty_directory new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/railties/lib/generators/rails/plugin/templates/generators/%file_name%/templates/.empty_directory diff --git a/railties/lib/generators/rails/plugin/templates/init.rb b/railties/lib/generators/rails/plugin/templates/init.rb new file mode 100644 index 0000000000..3c19a743c9 --- /dev/null +++ b/railties/lib/generators/rails/plugin/templates/init.rb @@ -0,0 +1 @@ +# Include hook code here diff --git a/railties/lib/generators/rails/plugin/templates/install.rb b/railties/lib/generators/rails/plugin/templates/install.rb new file mode 100644 index 0000000000..f7732d3796 --- /dev/null +++ b/railties/lib/generators/rails/plugin/templates/install.rb @@ -0,0 +1 @@ +# Install hook code here diff --git a/railties/lib/generators/rails/plugin/templates/lib/%file_name%.rb.tt b/railties/lib/generators/rails/plugin/templates/lib/%file_name%.rb.tt new file mode 100644 index 0000000000..d8d908a959 --- /dev/null +++ b/railties/lib/generators/rails/plugin/templates/lib/%file_name%.rb.tt @@ -0,0 +1 @@ +# <%= class_name %> diff --git a/railties/lib/generators/rails/plugin/templates/tasks/%file_name%_tasks.rake.tt b/railties/lib/generators/rails/plugin/templates/tasks/%file_name%_tasks.rake.tt new file mode 100644 index 0000000000..72920a9d3a --- /dev/null +++ b/railties/lib/generators/rails/plugin/templates/tasks/%file_name%_tasks.rake.tt @@ -0,0 +1,4 @@ +# desc "Explaining what the task does" +# task :<%= file_name %> do +# # Task goes here +# end diff --git a/railties/lib/generators/rails/plugin/templates/uninstall.rb b/railties/lib/generators/rails/plugin/templates/uninstall.rb new file mode 100644 index 0000000000..9738333463 --- /dev/null +++ b/railties/lib/generators/rails/plugin/templates/uninstall.rb @@ -0,0 +1 @@ +# Uninstall hook code here diff --git a/railties/lib/generators/rails/resource/USAGE b/railties/lib/generators/rails/resource/USAGE new file mode 100644 index 0000000000..936619b0db --- /dev/null +++ b/railties/lib/generators/rails/resource/USAGE @@ -0,0 +1,23 @@ +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 field: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 generator invokes your configured ORM and test framework, besides + creating helpers and add routes to 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` diff --git a/railties/lib/generators/rails/resource/resource_generator.rb b/railties/lib/generators/rails/resource/resource_generator.rb new file mode 100644 index 0000000000..8d787aaa75 --- /dev/null +++ b/railties/lib/generators/rails/resource/resource_generator.rb @@ -0,0 +1,32 @@ +require 'generators/rails/model/model_generator' + +module Rails + module Generators + class ResourceGenerator < ModelGenerator + hook_for :resource_controller do |base, controller| + base.invoke controller, [ base.name.pluralize, base.options[:actions] ] + end + + class_option :actions, :type => :array, :default => [], :banner => "ACTION ACTION", + :desc => "Actions for the resource controller", :aliases => "-a" + + class_option :singleton, :type => :boolean, :default => false, :aliases => "-i", + :desc => "Supply to create a singleton controller" + + def add_resource_route + route "map.resource#{:s unless options[:singleton]} :#{pluralize?(file_name)}" + end + + protected + + def pluralize?(name) + if options[:singleton] + name + else + name.pluralize + end + end + + end + end +end diff --git a/railties/lib/generators/rails/session_migration/USAGE b/railties/lib/generators/rails/session_migration/USAGE new file mode 100644 index 0000000000..e106f6ecc8 --- /dev/null +++ b/railties/lib/generators/rails/session_migration/USAGE @@ -0,0 +1,8 @@ +Description: + Creates a migration to add the sessions table used by the ORM session store. + Pass the migration name, either CamelCased or under_scored, as an argument. + + Before invoking this generator, be sure that your ORM supports session stores. + +Example: + `./script/generate session_migration CreateSessionTable` diff --git a/railties/lib/generators/rails/session_migration/session_migration_generator.rb b/railties/lib/generators/rails/session_migration/session_migration_generator.rb new file mode 100644 index 0000000000..e7d988359c --- /dev/null +++ b/railties/lib/generators/rails/session_migration/session_migration_generator.rb @@ -0,0 +1,8 @@ +module Rails + module Generators + class SessionMigrationGenerator < NamedBase + argument :name, :type => :string, :default => "add_session_table" + hook_for :orm + end + end +end diff --git a/railties/lib/generators/test_unit.rb b/railties/lib/generators/test_unit.rb new file mode 100644 index 0000000000..c4b8a8702d --- /dev/null +++ b/railties/lib/generators/test_unit.rb @@ -0,0 +1,9 @@ +require 'generators/named_base' + +module TestUnit + module Generators + class Base < Rails::Generators::NamedBase + check_class_collision :suffix => "Test" + end + end +end diff --git a/railties/lib/generators/test_unit/controller/controller_generator.rb b/railties/lib/generators/test_unit/controller/controller_generator.rb new file mode 100644 index 0000000000..a8cb5cbdbb --- /dev/null +++ b/railties/lib/generators/test_unit/controller/controller_generator.rb @@ -0,0 +1,13 @@ +require 'generators/test_unit' + +module TestUnit + module Generators + class ControllerGenerator < Base + check_class_collision :suffix => "ControllerTest" + + def create_test_files + template 'functional_test.rb', File.join('test/functional', class_path, "#{file_name}_controller_test.rb") + end + end + end +end diff --git a/railties/lib/generators/test_unit/controller/templates/functional_test.rb b/railties/lib/generators/test_unit/controller/templates/functional_test.rb new file mode 100644 index 0000000000..62fa5d86fd --- /dev/null +++ b/railties/lib/generators/test_unit/controller/templates/functional_test.rb @@ -0,0 +1,8 @@ +require 'test_helper' + +class <%= class_name %>ControllerTest < ActionController::TestCase + # Replace this with your real tests. + test "the truth" do + assert true + end +end diff --git a/railties/lib/generators/test_unit/helper/helper_generator.rb b/railties/lib/generators/test_unit/helper/helper_generator.rb new file mode 100644 index 0000000000..9ecfaa45ab --- /dev/null +++ b/railties/lib/generators/test_unit/helper/helper_generator.rb @@ -0,0 +1,13 @@ +require 'generators/test_unit' + +module TestUnit + module Generators + class HelperGenerator < Base + check_class_collision :suffix => "HelperTest" + + def create_helper_files + template 'helper_test.rb', File.join('test/unit/helpers', class_path, "#{file_name}_helper_test.rb") + end + end + end +end diff --git a/railties/lib/generators/test_unit/helper/templates/helper_test.rb b/railties/lib/generators/test_unit/helper/templates/helper_test.rb new file mode 100644 index 0000000000..591e40900e --- /dev/null +++ b/railties/lib/generators/test_unit/helper/templates/helper_test.rb @@ -0,0 +1,4 @@ +require 'test_helper' + +class <%= class_name %>HelperTest < ActionView::TestCase +end diff --git a/railties/lib/generators/test_unit/mailer/mailer_generator.rb b/railties/lib/generators/test_unit/mailer/mailer_generator.rb new file mode 100644 index 0000000000..bd1906516c --- /dev/null +++ b/railties/lib/generators/test_unit/mailer/mailer_generator.rb @@ -0,0 +1,20 @@ +require 'generators/test_unit' + +module TestUnit + module Generators + class MailerGenerator < Base + argument :actions, :type => :array, :default => [], :banner => "method method" + + def create_test_files + template "unit_test.rb", File.join('test', 'unit', class_path, "#{file_name}_test.rb") + end + + def create_fixtures_files + actions.each do |action| + @action, @path = action, File.join(file_path, action) + template "fixture", File.join("test", "fixtures", @path) + end + end + end + end +end diff --git a/railties/lib/generators/test_unit/mailer/templates/fixture b/railties/lib/generators/test_unit/mailer/templates/fixture new file mode 100644 index 0000000000..fcce7bd805 --- /dev/null +++ b/railties/lib/generators/test_unit/mailer/templates/fixture @@ -0,0 +1,3 @@ +<%= class_name %>#<%= @action %> + +Find me in app/views/<%= @path %> diff --git a/railties/lib/generators/test_unit/mailer/templates/unit_test.rb b/railties/lib/generators/test_unit/mailer/templates/unit_test.rb new file mode 100644 index 0000000000..4de94076e9 --- /dev/null +++ b/railties/lib/generators/test_unit/mailer/templates/unit_test.rb @@ -0,0 +1,20 @@ +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 diff --git a/railties/lib/generators/test_unit/model/model_generator.rb b/railties/lib/generators/test_unit/model/model_generator.rb new file mode 100644 index 0000000000..96883f592f --- /dev/null +++ b/railties/lib/generators/test_unit/model/model_generator.rb @@ -0,0 +1,24 @@ +require 'generators/test_unit' + +module TestUnit + module Generators + class ModelGenerator < Base + argument :attributes, :type => :hash, :default => {}, :banner => "field:type field:type" + + check_class_collision :suffix => "Test" + conditional_class_options :fixture + + def create_test_file + template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb") + end + + hook_for :fixture_replacement + + def create_fixture_file + if options[:fixture] && options[:fixture_replacement].nil? + template 'fixtures.yml', File.join('test/fixtures', "#{table_name}.yml") + end + end + end + end +end diff --git a/railties/lib/generators/test_unit/model/templates/fixtures.yml b/railties/lib/generators/test_unit/model/templates/fixtures.yml new file mode 100644 index 0000000000..c21035113e --- /dev/null +++ b/railties/lib/generators/test_unit/model/templates/fixtures.yml @@ -0,0 +1,19 @@ +# 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 -%> diff --git a/railties/lib/generators/test_unit/model/templates/unit_test.rb b/railties/lib/generators/test_unit/model/templates/unit_test.rb new file mode 100644 index 0000000000..3e0bc29d3a --- /dev/null +++ b/railties/lib/generators/test_unit/model/templates/unit_test.rb @@ -0,0 +1,8 @@ +require 'test_helper' + +class <%= class_name %>Test < ActiveSupport::TestCase + # Replace this with your real tests. + test "the truth" do + assert true + end +end diff --git a/railties/lib/generators/test_unit/observer/observer_generator.rb b/railties/lib/generators/test_unit/observer/observer_generator.rb new file mode 100644 index 0000000000..48742f4b70 --- /dev/null +++ b/railties/lib/generators/test_unit/observer/observer_generator.rb @@ -0,0 +1,11 @@ +require 'generators/test_unit' + +module TestUnit + module Generators + class ObserverGenerator < Base + def create_test_files + template 'unit_test.rb', File.join('test', 'unit', class_path, "#{file_name}_observer_test.rb") + end + end + end +end diff --git a/railties/lib/generators/test_unit/observer/templates/unit_test.rb b/railties/lib/generators/test_unit/observer/templates/unit_test.rb new file mode 100644 index 0000000000..03f6d5666e --- /dev/null +++ b/railties/lib/generators/test_unit/observer/templates/unit_test.rb @@ -0,0 +1,8 @@ +require 'test_helper' + +class <%= class_name %>ObserverTest < ActiveSupport::TestCase + # Replace this with your real tests. + test "the truth" do + assert true + end +end diff --git a/railties/lib/generators/test_unit/plugin/plugin_generator.rb b/railties/lib/generators/test_unit/plugin/plugin_generator.rb new file mode 100644 index 0000000000..9c08dc4d50 --- /dev/null +++ b/railties/lib/generators/test_unit/plugin/plugin_generator.rb @@ -0,0 +1,11 @@ +require 'generators/test_unit' + +module TestUnit + module Generators + class PluginGenerator < Base + def create_test_files + directory 'test' + end + end + end +end diff --git a/railties/lib/generators/test_unit/plugin/templates/test/%file_name%_test.rb.tt b/railties/lib/generators/test_unit/plugin/templates/test/%file_name%_test.rb.tt new file mode 100644 index 0000000000..3e0bc29d3a --- /dev/null +++ b/railties/lib/generators/test_unit/plugin/templates/test/%file_name%_test.rb.tt @@ -0,0 +1,8 @@ +require 'test_helper' + +class <%= class_name %>Test < ActiveSupport::TestCase + # Replace this with your real tests. + test "the truth" do + assert true + end +end diff --git a/railties/lib/generators/test_unit/plugin/templates/test/test_helper.rb b/railties/lib/generators/test_unit/plugin/templates/test/test_helper.rb new file mode 100644 index 0000000000..cf148b8b47 --- /dev/null +++ b/railties/lib/generators/test_unit/plugin/templates/test/test_helper.rb @@ -0,0 +1,3 @@ +require 'rubygems' +require 'active_support' +require 'active_support/test_case'
\ No newline at end of file diff --git a/railties/lib/rails_generator/generators/applications/app/app_generator.rb b/railties/lib/rails_generator/generators/applications/app/app_generator.rb deleted file mode 100644 index c8c2239f34..0000000000 --- a/railties/lib/rails_generator/generators/applications/app/app_generator.rb +++ /dev/null @@ -1,263 +0,0 @@ -require 'rbconfig' -require File.dirname(__FILE__) + '/template_runner' -require 'digest/md5' -require 'active_support/secure_random' - -class AppGenerator < Rails::Generator::Base - DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']) - - DATABASES = %w( mysql oracle postgresql sqlite2 sqlite3 frontbase ibm_db ) - DEFAULT_DATABASE = 'sqlite3' - - mandatory_options :source => "#{File.dirname(__FILE__)}/../../../../.." - default_options :db => (ENV["RAILS_DEFAULT_DATABASE"] || DEFAULT_DATABASE), - :shebang => DEFAULT_SHEBANG, :with_dispatchers => false, :freeze => false - - - def initialize(runtime_args, runtime_options = {}) - super - - usage if args.empty? - usage("Databases supported for preconfiguration are: #{DATABASES.join(", ")}") if (options[:db] && !DATABASES.include?(options[:db])) - - @destination_root = args.shift - @app_name = File.basename(File.expand_path(@destination_root)) - end - - def manifest - record do |m| - create_directories(m) - create_root_files(m) - create_app_files(m) - create_config_files(m) - create_script_files(m) - create_test_files(m) - create_public_files(m) - create_documentation_file(m) - create_log_files(m) - end - end - - def after_generate - if options[:template] - Rails::TemplateRunner.new(options[:template], @destination_root) - end - end - - protected - def banner - "Usage: #{$0} /path/to/your/app [options]" - end - - def add_options!(opt) - opt.separator '' - opt.separator 'Options:' - opt.on("-r", "--ruby=path", String, - "Path to the Ruby binary of your choice (otherwise scripts use env, dispatchers current path).", - "Default: #{DEFAULT_SHEBANG}") { |v| options[:shebang] = v } - - opt.on("-d", "--database=name", String, - "Preconfigure for selected database (options: #{DATABASES.join('/')}).", - "Default: #{DEFAULT_DATABASE}") { |v| options[:db] = v } - - opt.on("-D", "--with-dispatchers", - "Add CGI/FastCGI/mod_ruby dispatches code to generated application skeleton", - "Default: false") { |v| options[:with_dispatchers] = v } - - opt.on("-f", "--freeze", - "Freeze Rails in vendor/rails from the gems generating the skeleton", - "Default: false") { |v| options[:freeze] = v } - - opt.on("-m", "--template=path", String, - "Use an application template that lives at path (can be a filesystem path or URL).", - "Default: (none)") { |v| options[:template] = v } - - end - - - private - def create_directories(m) - m.directory '' - - # Intermediate directories are automatically created so don't sweat their absence here. - %w( - app/controllers - app/helpers - app/models - app/views/layouts - config/environments - config/initializers - config/locales - db - doc - lib - lib/tasks - log - public/images - public/javascripts - public/stylesheets - script/performance - test/fixtures - test/functional - test/integration - test/performance - test/unit - vendor - vendor/plugins - tmp/sessions - tmp/sockets - tmp/cache - tmp/pids - ).each { |path| m.directory(path) } - end - - def create_root_files(m) - m.file "fresh_rakefile", "Rakefile" - m.file "README", "README" - end - - def create_app_files(m) - m.file "helpers/application_controller.rb", "app/controllers/application_controller.rb" - m.file "helpers/application_helper.rb", "app/helpers/application_helper.rb" - end - - def create_config_files(m) - create_database_configuration_file(m) - create_routes_file(m) - create_locale_file(m) - create_seeds_file(m) - create_initializer_files(m) - create_environment_files(m) - end - - def create_documentation_file(m) - m.file "doc/README_FOR_APP", "doc/README_FOR_APP" - end - - def create_log_files(m) - %w( server production development test ).each do |file| - m.file "configs/empty.log", "log/#{file}.log", :chmod => 0666 - end - end - - def create_public_files(m) - create_dispatch_files(m) - create_error_files(m) - create_welcome_file(m) - create_browser_convention_files(m) - create_rails_image(m) - create_javascript_files(m) - end - - def create_script_files(m) - %w( - about console dbconsole destroy generate runner server plugin - performance/benchmarker performance/profiler - ).each do |file| - m.file "bin/#{file}", "script/#{file}", { - :chmod => 0755, - :shebang => options[:shebang] == DEFAULT_SHEBANG ? nil : options[:shebang] - } - end - end - - def create_test_files(m) - m.file "helpers/test_helper.rb", "test/test_helper.rb" - m.file "helpers/performance_test.rb", "test/performance/browsing_test.rb" - end - - - def create_database_configuration_file(m) - m.template "configs/databases/#{options[:db]}.yml", "config/database.yml", :assigns => { - :app_name => @app_name, - :socket => options[:db] == "mysql" ? mysql_socket_location : nil } - end - - def create_routes_file(m) - m.file "configs/routes.rb", "config/routes.rb" - end - - def create_seeds_file(m) - m.file "configs/seeds.rb", "db/seeds.rb" - end - - def create_initializer_files(m) - %w( - backtrace_silencers - inflections - mime_types - new_rails_defaults - ).each do |initializer| - m.file "configs/initializers/#{initializer}.rb", "config/initializers/#{initializer}.rb" - end - - m.template "configs/initializers/session_store.rb", "config/initializers/session_store.rb", - :assigns => { :app_name => @app_name, :app_secret => ActiveSupport::SecureRandom.hex(64) } - end - - def create_locale_file(m) - m.file "configs/locales/en.yml", "config/locales/en.yml" - end - - def create_environment_files(m) - m.template "environments/environment.rb", "config/environment.rb", - :assigns => { :freeze => options[:freeze] } - - m.file "environments/boot.rb", "config/boot.rb" - m.file "environments/production.rb", "config/environments/production.rb" - m.file "environments/development.rb", "config/environments/development.rb" - m.file "environments/test.rb", "config/environments/test.rb" - end - - - def create_dispatch_files(m) - if options[:with_dispatchers] - dispatcher_options = { :chmod => 0755, :shebang => options[:shebang] } - - m.file "dispatches/config.ru", "config.ru" - m.file "dispatches/dispatch.rb", "public/dispatch.rb", dispatcher_options - m.file "dispatches/dispatch.rb", "public/dispatch.cgi", dispatcher_options - m.file "dispatches/dispatch.fcgi", "public/dispatch.fcgi", dispatcher_options - end - end - - def create_error_files(m) - %w( 404 422 500 ).each do |file| - m.file "html/#{file}.html", "public/#{file}.html" - end - end - - def create_welcome_file(m) - m.file 'html/index.html', 'public/index.html' - end - - def create_browser_convention_files(m) - m.file "html/favicon.ico", "public/favicon.ico" - m.file "html/robots.txt", "public/robots.txt" - end - - def create_rails_image(m) - m.file "html/images/rails.png", "public/images/rails.png" - end - - def create_javascript_files(m) - %w( prototype effects dragdrop controls application ).each do |javascript| - m.file "html/javascripts/#{javascript}.js", "public/javascripts/#{javascript}.js" - end - end - - - def mysql_socket_location - [ - "/tmp/mysql.sock", # default - "/var/run/mysqld/mysqld.sock", # debian/gentoo - "/var/tmp/mysql.sock", # freebsd - "/var/lib/mysql/mysql.sock", # fedora - "/opt/local/lib/mysql/mysql.sock", # fedora - "/opt/local/var/run/mysqld/mysqld.sock", # mac + darwinports + mysql - "/opt/local/var/run/mysql4/mysqld.sock", # mac + darwinports + mysql4 - "/opt/local/var/run/mysql5/mysqld.sock", # mac + darwinports + mysql5 - "/opt/lampp/var/mysql/mysql.sock" # xampp for linux - ].find { |f| File.exist?(f) } unless RUBY_PLATFORM =~ /(:?mswin|mingw)/ - end -end
\ No newline at end of file diff --git a/railties/lib/rails_generator/generators/applications/app/scm/git.rb b/railties/lib/rails_generator/generators/applications/app/scm/git.rb deleted file mode 100644 index 445de6ab42..0000000000 --- a/railties/lib/rails_generator/generators/applications/app/scm/git.rb +++ /dev/null @@ -1,16 +0,0 @@ -module Rails - class Git < Scm - def self.clone(repos, branch=nil) - `git clone #{repos}` - - if branch - `cd #{repos.split('/').last}/` - `git checkout #{branch}` - end - end - - def self.run(command) - `git #{command}` - end - end -end
\ No newline at end of file diff --git a/railties/lib/rails_generator/generators/applications/app/scm/scm.rb b/railties/lib/rails_generator/generators/applications/app/scm/scm.rb deleted file mode 100644 index f6c08cad39..0000000000 --- a/railties/lib/rails_generator/generators/applications/app/scm/scm.rb +++ /dev/null @@ -1,8 +0,0 @@ -module Rails - class Scm - private - def self.hash_to_parameters(hash) - hash.collect { |key, value| "--#{key} #{(value.kind_of?(String) ? value : "")}"}.join(" ") - end - end -end
\ No newline at end of file diff --git a/railties/lib/rails_generator/generators/applications/app/scm/svn.rb b/railties/lib/rails_generator/generators/applications/app/scm/svn.rb deleted file mode 100644 index 22b5966d25..0000000000 --- a/railties/lib/rails_generator/generators/applications/app/scm/svn.rb +++ /dev/null @@ -1,7 +0,0 @@ -module Rails - class Svn < Scm - def self.checkout(repos, branch = nil) - `svn checkout #{repos}/#{branch || "trunk"}` - end - end -end
\ No newline at end of file diff --git a/railties/lib/rails_generator/generators/applications/app/template_runner.rb b/railties/lib/rails_generator/generators/applications/app/template_runner.rb deleted file mode 100644 index 0e24d11950..0000000000 --- a/railties/lib/rails_generator/generators/applications/app/template_runner.rb +++ /dev/null @@ -1,401 +0,0 @@ -require File.dirname(__FILE__) + '/scm/scm' -require File.dirname(__FILE__) + '/scm/git' -require File.dirname(__FILE__) + '/scm/svn' - -require 'open-uri' -require 'fileutils' - -module Rails - class TemplateRunner - attr_reader :root - attr_writer :logger - - def initialize(template, root = '') # :nodoc: - @root = File.expand_path(File.directory?(root) ? root : File.join(Dir.pwd, root)) - - log 'applying', "template: #{template}" - - load_template(template) - - log 'applied', "#{template}" - end - - def load_template(template) - begin - code = open(template).read - in_root { self.instance_eval(code) } - rescue LoadError, Errno::ENOENT => e - raise "The template [#{template}] could not be loaded. Error: #{e}" - end - end - - # Create a new file in the Rails project folder. Specify the - # relative path from RAILS_ROOT. Data is the return value of a block - # or a data string. - # - # ==== Examples - # - # file("lib/fun_party.rb") do - # hostname = ask("What is the virtual hostname I should use?") - # "vhost.name = #{hostname}" - # end - # - # file("config/apach.conf", "your apache config") - # - def file(filename, data = nil, log_action = true, &block) - log 'file', filename if log_action - dir, file = [File.dirname(filename), File.basename(filename)] - - inside(dir) do - File.open(file, "w") do |f| - if block_given? - f.write(block.call) - else - f.write(data) - end - end - end - end - - # Install a plugin. You must provide either a Subversion url or Git url. - # For a Git-hosted plugin, you can specify if it should be added as a submodule instead of cloned. - # - # ==== Examples - # - # plugin 'restful-authentication', :git => 'git://github.com/technoweenie/restful-authentication.git' - # plugin 'restful-authentication', :git => 'git://github.com/technoweenie/restful-authentication.git', :submodule => true - # plugin 'restful-authentication', :svn => 'svn://svnhub.com/technoweenie/restful-authentication/trunk' - # - def plugin(name, options) - log 'plugin', name - - if options[:git] && options[:submodule] - in_root do - Git.run("submodule add #{options[:git]} vendor/plugins/#{name}") - end - elsif options[:git] || options[:svn] - in_root do - run_ruby_script("script/plugin install #{options[:svn] || options[:git]}", false) - end - else - log "! no git or svn provided for #{name}. skipping..." - end - end - - # Adds an entry into config/environment.rb for the supplied gem : - def gem(name, options = {}) - log 'gem', name - env = options.delete(:env) - - gems_code = "config.gem '#{name}'" - - if options.any? - opts = options.inject([]) {|result, h| result << [":#{h[0]} => #{h[1].inspect.gsub('"',"'")}"] }.sort.join(", ") - gems_code << ", #{opts}" - end - - environment gems_code, :env => env - end - - # Adds a line inside the Initializer block for config/environment.rb. Used by #gem - # If options :env is specified, the line is appended to the corresponding - # file in config/environments/#{env}.rb - def environment(data = nil, options = {}, &block) - sentinel = 'Rails::Initializer.run do |config|' - - data = block.call if !data && block_given? - - in_root do - if options[:env].nil? - gsub_file 'config/environment.rb', /(#{Regexp.escape(sentinel)})/mi do |match| - "#{match}\n " << data - end - else - Array.wrap(options[:env]).each do|env| - append_file "config/environments/#{env}.rb", "\n#{data}" - end - end - end - end - - # Run a command in git. - # - # ==== Examples - # - # git :init - # git :add => "this.file that.rb" - # git :add => "onefile.rb", :rm => "badfile.cxx" - # - def git(command = {}) - in_root do - if command.is_a?(Symbol) - log 'running', "git #{command}" - Git.run(command.to_s) - else - command.each do |command, options| - log 'running', "git #{command} #{options}" - Git.run("#{command} #{options}") - end - end - end - end - - # Create a new file in the vendor/ directory. Code can be specified - # in a block or a data string can be given. - # - # ==== Examples - # - # vendor("sekrit.rb") do - # sekrit_salt = "#{Time.now}--#{3.years.ago}--#{rand}--" - # "salt = '#{sekrit_salt}'" - # end - # - # vendor("foreign.rb", "# Foreign code is fun") - # - def vendor(filename, data = nil, &block) - log 'vendoring', filename - file("vendor/#{filename}", data, false, &block) - end - - # Create a new file in the lib/ directory. Code can be specified - # in a block or a data string can be given. - # - # ==== Examples - # - # lib("crypto.rb") do - # "crypted_special_value = '#{rand}--#{Time.now}--#{rand(1337)}--'" - # end - # - # lib("foreign.rb", "# Foreign code is fun") - # - def lib(filename, data = nil, &block) - log 'lib', filename - file("lib/#{filename}", data, false, &block) - end - - # Create a new Rakefile with the provided code (either in a block or a string). - # - # ==== Examples - # - # rakefile("bootstrap.rake") do - # project = ask("What is the UNIX name of your project?") - # - # <<-TASK - # namespace :#{project} do - # task :bootstrap do - # puts "i like boots!" - # end - # end - # TASK - # end - # - # rakefile("seed.rake", "puts 'im plantin ur seedz'") - # - def rakefile(filename, data = nil, &block) - log 'rakefile', filename - file("lib/tasks/#{filename}", data, false, &block) - end - - # Create a new initializer with the provided code (either in a block or a string). - # - # ==== Examples - # - # initializer("globals.rb") do - # data = "" - # - # ['MY_WORK', 'ADMINS', 'BEST_COMPANY_EVAR'].each do - # data << "#{const} = :entp" - # end - # - # data - # end - # - # initializer("api.rb", "API_KEY = '123456'") - # - def initializer(filename, data = nil, &block) - log 'initializer', filename - file("config/initializers/#{filename}", data, false, &block) - end - - # Generate something using a generator from Rails or a plugin. - # The second parameter is the argument string that is passed to - # the generator or an Array that is joined. - # - # ==== Example - # - # generate(:authenticated, "user session") - # - def generate(what, *args) - log 'generating', what - argument = args.map {|arg| arg.to_s }.flatten.join(" ") - - in_root { run_ruby_script("script/generate #{what} #{argument}", false) } - end - - # Executes a command - # - # ==== Example - # - # inside('vendor') do - # run('ln -s ~/edge rails) - # end - # - def run(command, log_action = true) - log 'executing', "#{command} from #{Dir.pwd}" if log_action - `#{command}` - end - - # Executes a ruby script (taking into account WIN32 platform quirks) - def run_ruby_script(command, log_action = true) - ruby_command = RUBY_PLATFORM=~ /win32/ ? 'ruby ' : '' - run("#{ruby_command}#{command}", log_action) - end - - # Runs the supplied rake task - # - # ==== Example - # - # rake("db:migrate") - # rake("db:migrate", :env => "production") - # rake("gems:install", :sudo => true) - # - def rake(command, options = {}) - log 'rake', command - env = options[:env] || 'development' - sudo = options[:sudo] ? 'sudo ' : '' - in_root { run("#{sudo}rake #{command} RAILS_ENV=#{env}", false) } - end - - # Just run the capify command in root - # - # ==== Example - # - # capify! - # - def capify! - log 'capifying' - in_root { run('capify .', false) } - end - - # Add Rails to /vendor/rails - # - # ==== Example - # - # freeze! - # - def freeze!(args = {}) - log 'vendor', 'rails edge' - in_root { run('rake rails:freeze:edge', false) } - end - - # Make an entry in Rails routing file conifg/routes.rb - # - # === Example - # - # route "map.root :controller => :welcome" - # - def route(routing_code) - log 'route', routing_code - sentinel = 'ActionController::Routing::Routes.draw do |map|' - - in_root do - gsub_file 'config/routes.rb', /(#{Regexp.escape(sentinel)})/mi do |match| - "#{match}\n #{routing_code}\n" - end - end - end - - protected - - # Get a user's input - # - # ==== Example - # - # answer = ask("Should I freeze the latest Rails?") - # freeze! if ask("Should I freeze the latest Rails?") == "yes" - # - def ask(string) - log '', string - STDIN.gets.strip - end - - # Do something in the root of the Rails application or - # a provided subfolder; the full path is yielded to the block you provide. - # The path is set back to the previous path when the method exits. - def inside(dir = '', &block) - folder = File.join(root, dir) - FileUtils.mkdir_p(folder) unless File.exist?(folder) - FileUtils.cd(folder) { block.arity == 1 ? yield(folder) : yield } - end - - def in_root - FileUtils.cd(root) { yield } - end - - # Helper to test if the user says yes(y)? - # - # ==== Example - # - # freeze! if yes?("Should I freeze the latest Rails?") - # - def yes?(question) - answer = ask(question).downcase - answer == "y" || answer == "yes" - end - - # Helper to test if the user does NOT say yes(y)? - # - # ==== Example - # - # capify! if no?("Will you be using vlad to deploy your application?") - # - def no?(question) - !yes?(question) - end - - # Run a regular expression replacement on a file - # - # ==== Example - # - # gsub_file 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1' - # - def gsub_file(relative_destination, regexp, *args, &block) - path = destination_path(relative_destination) - content = File.read(path).gsub(regexp, *args, &block) - File.open(path, 'wb') { |file| file.write(content) } - end - - # Append text to a file - # - # ==== Example - # - # append_file 'config/environments/test.rb', 'config.gem "rspec"' - # - def append_file(relative_destination, data) - path = destination_path(relative_destination) - File.open(path, 'ab') { |file| file.write(data) } - end - - def destination_path(relative_destination) - File.join(root, relative_destination) - end - - def log(action, message = '') - logger.log(action, message) - end - - def logger - @logger ||= Rails::Generator::Base.logger - end - - def logger - @logger ||= if defined?(Rails::Generator::Base) - Rails::Generator::Base.logger - else - require 'rails_generator/simple_logger' - Rails::Generator::SimpleLogger.new(STDOUT) - end - end - - end -end diff --git a/railties/lib/rails_generator/secret_key_generator.rb b/railties/lib/rails_generator/secret_key_generator.rb deleted file mode 100644 index 7dd495a2f5..0000000000 --- a/railties/lib/rails_generator/secret_key_generator.rb +++ /dev/null @@ -1,24 +0,0 @@ -require 'active_support/deprecation' - -module Rails - # A class for creating random secret keys. This class will do its best to create a - # random secret key that's as secure as possible, using whatever methods are - # available on the current platform. For example: - # - # generator = Rails::SecretKeyGenerator("some unique identifier, such as the application name") - # generator.generate_secret # => "f3f1be90053fa851... (some long string)" - # - # This class is *deprecated* in Rails 2.2 in favor of ActiveSupport::SecureRandom. - # It is currently a wrapper around ActiveSupport::SecureRandom. - class SecretKeyGenerator - def initialize(identifier) - end - - # Generate a random secret key with the best possible method available on - # the current platform. - def generate_secret - ActiveSupport::SecureRandom.hex(64) - end - deprecate :generate_secret=>"You should use ActiveSupport::SecureRandom.hex(64)" - end -end diff --git a/railties/test/boot_test.rb b/railties/test/boot_test.rb index 2dd68857c3..7bf420d4f2 100644 --- a/railties/test/boot_test.rb +++ b/railties/test/boot_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' require 'initializer' -require "#{File.dirname(__FILE__)}/../environments/boot" +require "#{File.dirname(__FILE__)}/../lib/generators/rails/app/templates/config/boot" require 'rails/gem_dependency' class BootTest < Test::Unit::TestCase diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb new file mode 100644 index 0000000000..baf687336a --- /dev/null +++ b/railties/test/generators/actions_test.rb @@ -0,0 +1,185 @@ +require 'abstract_unit' +require 'generators/generators_test_helper' +require 'generators/rails/app/app_generator' + +class ActionsTest < GeneratorsTestCase + def setup + super + @git_plugin_uri = 'git://github.com/technoweenie/restful-authentication.git' + @svn_plugin_uri = 'svn://svnhub.com/technoweenie/restful-authentication/trunk' + end + + def test_apply_loads_and_evaluates_a_template + template = <<-TEMPLATE + @foo = "FOO" + TEMPLATE + template.instance_eval "def read; self; end" # Make the string respond to read + + generator.expects(:open).with("http://gist.github.com/103208.txt").returns(template) + action :apply, "http://gist.github.com/103208.txt" + assert_equal generator.instance_variable_get("@foo"), "FOO" + end + + def test_create_file_should_write_data_to_file_path + action :create_file, 'lib/test_file.rb', 'heres test data' + assert_file 'lib/test_file.rb', 'heres test data' + end + + def test_create_file_should_write_block_contents_to_file_path + action(:create_file, 'lib/test_file.rb'){ 'heres block data' } + assert_file 'lib/test_file.rb', 'heres block data' + end + + def test_plugin_with_git_option_should_run_plugin_install + generator.expects(:run).once.with("ruby script/plugin install #{@git_plugin_uri}", false) + action :plugin, 'restful-authentication', :git => @git_plugin_uri + end + + def test_plugin_with_svn_option_should_run_plugin_install + generator.expects(:run).once.with("ruby script/plugin install #{@svn_plugin_uri}", false) + action :plugin, 'restful-authentication', :svn => @svn_plugin_uri + end + + def test_plugin_with_git_option_and_submodule_should_use_git_scm + generator.expects(:run).with("git submodule add #{@git_plugin_uri} vendor/plugins/rest_auth", false) + action :plugin, 'rest_auth', :git => @git_plugin_uri, :submodule => true + end + + def test_plugin_with_no_options_should_skip_method + generator.expects(:run).never + action :plugin, 'rest_auth', {} + end + + def test_gem_should_put_gem_dependency_in_enviroment + run_generator + action :gem, 'will-paginate' + assert_file 'config/environment.rb', /config\.gem 'will\-paginate'/ + end + + def test_gem_with_options_should_include_options_in_gem_dependency_in_environment + run_generator + action :gem, 'mislav-will-paginate', :lib => 'will-paginate', :source => 'http://gems.github.com' + + regexp = /#{Regexp.escape("config.gem 'mislav-will-paginate', :lib => 'will-paginate', :source => 'http://gems.github.com'")}/ + assert_file 'config/environment.rb', regexp + end + + def test_gem_with_env_string_should_put_gem_dependency_in_specified_environment + run_generator + action :gem, 'rspec', :env => 'test' + assert_file 'config/environments/test.rb', /config\.gem 'rspec'/ + end + + def test_gem_with_env_array_should_put_gem_dependency_in_specified_environments + run_generator + action :gem, 'quietbacktrace', :env => %w[ development test ] + assert_file 'config/environments/development.rb', /config\.gem 'quietbacktrace'/ + assert_file 'config/environments/test.rb', /config\.gem 'quietbacktrace'/ + end + + def test_gem_with_lib_option_set_to_false_should_put_gem_dependency_in_enviroment_correctly + run_generator + action :gem, 'mislav-will-paginate', :lib => false + assert_file 'config/environment.rb', /config\.gem 'mislav\-will\-paginate'\, :lib => false/ + end + + def test_environment_should_include_data_in_environment_initializer_block + run_generator + load_paths = 'config.load_paths += %w["#{RAILS_ROOT}/app/extras"]' + action :environment, load_paths + assert_file 'config/environment.rb', /#{Regexp.escape(load_paths)}/ + end + + def test_environment_with_block_should_include_block_contents_in_environment_initializer_block + run_generator + + action :environment do + '# This wont be added' + '# This will be added' + end + + assert_file 'config/environment.rb', /# This will be added/ + end + + def test_git_with_symbol_should_run_command_using_git_scm + generator.expects(:run).once.with('git init') + action :git, :init + end + + def test_git_with_hash_should_run_each_command_using_git_scm + generator.expects(:run).times(2) + action :git, :rm => 'README', :add => '.' + end + + def test_vendor_should_write_data_to_file_in_vendor + action :vendor, 'vendor_file.rb', '# vendor data' + assert_file 'vendor/vendor_file.rb', '# vendor data' + end + + def test_lib_should_write_data_to_file_in_lib + action :lib, 'my_library.rb', 'class MyLibrary' + assert_file 'lib/my_library.rb', 'class MyLibrary' + end + + def test_rakefile_should_write_date_to_file_in_lib_tasks + action :rakefile, 'myapp.rake', 'task :run => [:environment]' + assert_file 'lib/tasks/myapp.rake', 'task :run => [:environment]' + end + + def test_initializer_should_write_date_to_file_in_config_initializers + action :initializer, 'constants.rb', 'MY_CONSTANT = 42' + assert_file 'config/initializers/constants.rb', 'MY_CONSTANT = 42' + end + + def test_generate_should_run_script_generate_with_argument_and_options + generator.expects(:run).once.with('ruby script/generate model MyModel', false) + action :generate, 'model', 'MyModel' + end + + def test_rake_should_run_rake_command_with_development_env + generator.expects(:run).once.with('rake log:clear RAILS_ENV=development', false) + action :rake, 'log:clear' + end + + def test_rake_with_env_option_should_run_rake_command_in_env + generator.expects(:run).once.with('rake log:clear RAILS_ENV=production', false) + action :rake, 'log:clear', :env => 'production' + end + + def test_rake_with_sudo_option_should_run_rake_command_with_sudo + generator.expects(:run).once.with('sudo rake log:clear RAILS_ENV=development', false) + action :rake, 'log:clear', :sudo => true + end + + def test_capify_should_run_the_capify_command + generator.expects(:run).once.with('capify .', false) + action :capify! + end + + def test_freeze_should_freeze_rails_edge + generator.expects(:run).once.with('rake rails:freeze:edge', false) + action :freeze! + end + + def test_route_should_add_data_to_the_routes_block_in_config_routes + run_generator + route_command = "map.route '/login', :controller => 'sessions', :action => 'new'" + action :route, route_command + assert_file 'config/routes.rb', /#{Regexp.escape(route_command)}/ + end + + protected + + def run_generator + silence(:stdout) { Rails::Generators::AppGenerator.start [destination_root] } + end + + def generator(config={}) + @generator ||= Rails::Generators::Base.new([], {}, { :root => destination_root }.merge!(config)) + end + + def action(*args, &block) + silence(:stdout){ generator.send(*args, &block) } + end + +end diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb new file mode 100644 index 0000000000..98994f6ad2 --- /dev/null +++ b/railties/test/generators/app_generator_test.rb @@ -0,0 +1,166 @@ +require 'abstract_unit' +require 'generators/generators_test_helper' +require 'generators/rails/app/app_generator' + +class AppGeneratorTest < GeneratorsTestCase + + def setup + super + Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) + end + + def teardown + super + Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) + end + + def test_application_skeleton_is_created + run_generator + + %w( + app/controllers + app/helpers + app/models + app/views/layouts + config/environments + config/initializers + config/locales + db + doc + lib + lib/tasks + log + public/images + public/javascripts + public/stylesheets + script/performance + test/fixtures + test/functional + test/integration + test/performance + test/unit + vendor + vendor/plugins + tmp/sessions + tmp/sockets + tmp/cache + tmp/pids + ).each{ |path| assert_file path } + end + + def test_invalid_database_option_raises_an_error + content = capture(:stderr){ run_generator(["-d", "unknown"]) } + assert_match /Invalid value for \-\-database option/, content + end + + def test_dispatchers_are_not_added_by_default + run_generator + assert_no_file "config.ru" + assert_no_file "public/dispatch.cgi" + assert_no_file "public/dispatch.fcgi" + end + + def test_dispatchers_are_added_if_required + run_generator ["--with-dispatchers"] + assert_file "config.ru" + assert_file "public/dispatch.cgi" + assert_file "public/dispatch.fcgi" + end + + def test_config_database_is_added_by_default + run_generator + assert_file "config/database.yml", /sqlite3/ + end + + def test_config_database_is_not_added_if_skip_activerecord_is_given + run_generator ["--skip-activerecord"] + assert_no_file "config/database.yml" + end + + def test_activerecord_is_removed_from_frameworks_if_skip_activerecord_is_given + run_generator ["--skip-activerecord"] + assert_file "config/environment.rb", /config\.frameworks \-= \[ :active_record \]/ + end + + def test_prototype_and_test_unit_are_added_by_default + run_generator + assert_file "public/javascripts/prototype.js" + assert_file "test" + end + + def test_prototype_and_test_unit_are_skipped_if_required + run_generator ["--skip-prototype", "--skip-testunit"] + assert_no_file "public/javascripts/prototype.js" + assert_no_file "test" + end + + def test_shebang_is_added_to_files + run_generator ["--ruby", "foo/bar/baz"] + + %w( + about + console + dbconsole + destroy + generate + plugin + runner + server + ).each { |path| assert_file "script/#{path}", /#!foo\/bar\/baz/ } + end + + def test_rails_is_frozen + generator(:freeze => true, :database => "sqlite3").expects(:run).with("rake rails:freeze:edge", false) + silence(:stdout){ generator.invoke } + assert_file 'config/environment.rb', /# RAILS_GEM_VERSION/ + end + + def test_template_raises_an_error_with_invalid_path + content = capture(:stderr){ run_generator(["-m", "non/existant/path"]) } + assert_match /The template \[.*\] could not be loaded/, content + assert_match /non\/existant\/path/, content + end + + def test_template_is_executed_when_supplied + path = "http://gist.github.com/103208.txt" + template = %{ say "It works!" } + template.instance_eval "def read; self; end" # Make the string respond to read + + generator(:template => path, :database => "sqlite3").expects(:open).with(path).returns(template) + assert_match /It works!/, silence(:stdout){ generator.invoke } + end + + def test_usage_read_from_file + File.expects(:read).returns("USAGE FROM FILE") + assert_equal "USAGE FROM FILE", Rails::Generators::AppGenerator.desc + end + + def test_default_usage + File.expects(:exist?).returns(false) + assert_match /Create rails files for app generator/, Rails::Generators::AppGenerator.desc + end + + def test_default_namespace + assert_match "rails:generators:app", Rails::Generators::AppGenerator.namespace + end + + def test_file_is_added_for_backwards_compatibility + action :file, 'lib/test_file.rb', 'heres test data' + assert_file 'lib/test_file.rb', 'heres test data' + end + + protected + + def run_generator(args=[]) + silence(:stdout) { Rails::Generators::AppGenerator.start [destination_root].concat(args) } + end + + def generator(options={}) + @generator ||= Rails::Generators::AppGenerator.new([destination_root], options, :root => destination_root) + end + + def action(*args, &block) + silence(:stdout){ generator.send(*args, &block) } + end + +end diff --git a/railties/test/generators/controller_generator_test.rb b/railties/test/generators/controller_generator_test.rb new file mode 100644 index 0000000000..e3fe2594b9 --- /dev/null +++ b/railties/test/generators/controller_generator_test.rb @@ -0,0 +1,83 @@ +require 'abstract_unit' +require 'generators/generators_test_helper' +require 'generators/erb/controller/controller_generator' +require 'generators/rails/controller/controller_generator' +require 'generators/rails/helper/helper_generator' +require 'generators/test_unit/controller/controller_generator' +require 'generators/test_unit/helper/helper_generator' + +ObjectController = Class.new + +class ControllerGeneratorTest < GeneratorsTestCase + + def test_help_does_not_show_invoked_generators_options_if_they_already_exist + content = run_generator ["--help"] + assert_no_match /Helper options:/, content + end + + def test_controller_skeleton_is_created + run_generator + assert_file "app/controllers/account_controller.rb", /class AccountController < ApplicationController/ + end + + def test_check_class_collision + content = capture(:stderr){ run_generator ["object"] } + assert_match /The name 'ObjectController' is either already used in your application or reserved/, content + end + + # No need to spec content since it's already spec'ed on helper generator. + # + def test_invokes_helper + run_generator + assert_file "app/helpers/account_helper.rb" + assert_file "test/unit/helpers/account_helper_test.rb" + end + + def test_does_not_invoke_helper_if_required + run_generator ["account", "--skip-helper"] + assert_no_file "app/helpers/account_helper.rb" + assert_no_file "test/unit/helpers/account_helper_test.rb" + end + + def test_invokes_default_test_framework + run_generator + assert_file "test/functional/account_controller_test.rb" + end + + def test_does_not_invoke_test_framework_if_required + run_generator ["account", "--no-test-framework"] + assert_no_file "test/functional/account_controller_test.rb" + end + + def test_invokes_default_template_engine + run_generator + assert_file "app/views/account/foo.html.erb", /app\/views\/account\/foo/ + assert_file "app/views/account/bar.html.erb", /app\/views\/account\/bar/ + end + + def test_invokes_default_template_engine_even_with_no_action + run_generator ["account"] + assert_file "app/views/account" + end + + def test_template_engine_with_class_path + run_generator ["admin/account"] + assert_file "app/views/admin/account" + end + + def test_actions_are_turned_into_methods + run_generator + + assert_file "app/controllers/account_controller.rb" do |controller| + assert_instance_method controller, :foo + assert_instance_method controller, :bar + end + end + + protected + + def run_generator(args=["Account", "foo", "bar"]) + silence(:stdout) { Rails::Generators::ControllerGenerator.start args, :root => destination_root } + end + +end diff --git a/railties/test/generators/generators_test_helper.rb b/railties/test/generators/generators_test_helper.rb new file mode 100644 index 0000000000..591da45c72 --- /dev/null +++ b/railties/test/generators/generators_test_helper.rb @@ -0,0 +1,88 @@ +require 'test/unit' +require 'fileutils' + +$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib" +require 'generators' + +class GeneratorsTestCase < Test::Unit::TestCase + include FileUtils + + def destination_root + @destination_root ||= File.expand_path("#{File.dirname(__FILE__)}/../fixtures/tmp") + end + + def setup + rm_rf(destination_root) + mkdir_p(destination_root) + end + + def test_truth + # don't complain, test/unit + end + + def capture(stream) + begin + stream = stream.to_s + eval "$#{stream} = StringIO.new" + yield + result = eval("$#{stream}").string + ensure + eval("$#{stream} = #{stream.upcase}") + end + + result + end + alias :silence :capture + + def assert_file(relative, *contents) + absolute = File.join(destination_root, relative) + assert File.exists?(absolute), "Expected file #{relative.inspect} to exist, but does not" + + read = File.read(absolute) if block_given? || !contents.empty? + yield read if block_given? + + contents.each do |content| + case content + when String + assert_equal content, read + when Regexp + assert_match content, read + end + end + end + + def assert_no_file(relative) + absolute = File.join(destination_root, relative) + assert !File.exists?(absolute), "Expected file #{relative.inspect} to not exist, but does" + end + + def assert_migration(relative, *contents, &block) + file_name = migration_file_name(relative) + assert file_name, "Expected migration #{relative} to exist, but was not found" + assert_file File.join(File.dirname(relative), file_name), *contents, &block + end + + def assert_no_migration(relative) + file_name = migration_file_name(relative) + assert_nil file_name, "Expected migration #{relative} to not exist, but found #{file_name}" + end + + def assert_class_method(content, method, &block) + assert_instance_method content, "self.#{method}", &block + end + + def assert_instance_method(content, method) + assert_match /def #{method}(.*?)end/m, content + yield content.match(/def #{method}(.*?)end/m)[1] if block_given? + end + + protected + + def migration_file_name(relative) + absolute = File.join(destination_root, relative) + dirname, file_name = File.dirname(absolute), File.basename(absolute).sub(/\.rb$/, '') + + migration = Dir.glob("#{dirname}/[0-9]*_*.rb").grep(/\d+_#{file_name}.rb$/).first + File.basename(migration) if migration + end +end diff --git a/railties/test/generators/helper_generator_test.rb b/railties/test/generators/helper_generator_test.rb new file mode 100644 index 0000000000..41e1e1dce2 --- /dev/null +++ b/railties/test/generators/helper_generator_test.rb @@ -0,0 +1,61 @@ +require 'abstract_unit' +require 'generators/generators_test_helper' +require 'generators/rails/helper/helper_generator' +require 'generators/test_unit/helper/helper_generator' + +ObjectHelper = Class.new +AnotherObjectHelperTest = Class.new + +class HelperGeneratorTest < GeneratorsTestCase + + def test_helper_skeleton_is_created + run_generator + assert_file "app/helpers/admin_helper.rb", /module AdminHelper/ + end + + def test_invokes_default_test_framework + run_generator + assert_file "test/unit/helpers/admin_helper_test.rb", /class AdminHelperTest < ActionView::TestCase/ + end + + def test_logs_if_the_test_framework_cannot_be_found + content = run_generator ["admin", "--test-framework=unknown"] + assert_match /Could not find and invoke 'unknown'/, content + end + + def test_check_class_collision + content = capture(:stderr){ run_generator ["object"] } + assert_match /The name 'ObjectHelper' is either already used in your application or reserved/, content + end + + def test_check_class_collision_on_tests + content = capture(:stderr){ run_generator ["another_object"] } + assert_match /The name 'AnotherObjectHelperTest' is either already used in your application or reserved/, content + end + + def test_namespaced_and_not_namespaced_helpers + run_generator ["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 "#{destination_root}/app/helpers/products_helper" + + assert_nothing_raised do + begin + run_generator ["admin::products"] + ensure + # cleanup + Object.send(:remove_const, :ProductsHelper) + end + end + end + + protected + + def run_generator(args=["admin"]) + silence(:stdout) { Rails::Generators::HelperGenerator.start args, :root => destination_root } + end + +end diff --git a/railties/test/generators/integration_test_generator_test.rb b/railties/test/generators/integration_test_generator_test.rb new file mode 100644 index 0000000000..1961a102b9 --- /dev/null +++ b/railties/test/generators/integration_test_generator_test.rb @@ -0,0 +1,18 @@ +require 'abstract_unit' +require 'generators/generators_test_helper' +require 'generators/rails/integration_test/integration_test_generator' + +class IntegrationTestGeneratorTest < GeneratorsTestCase + + def test_integration_test_skeleton_is_created + run_generator + assert_file "test/integration/integration_test.rb", /class IntegrationTest < ActionController::IntegrationTest/ + end + + protected + + def run_generator(args=["integration"]) + silence(:stdout) { Rails::Generators::IntegrationTestGenerator.start args, :root => destination_root } + end + +end diff --git a/railties/test/generators/mailer_generator_test.rb b/railties/test/generators/mailer_generator_test.rb new file mode 100644 index 0000000000..5d21da3dd1 --- /dev/null +++ b/railties/test/generators/mailer_generator_test.rb @@ -0,0 +1,54 @@ +require 'abstract_unit' +require 'generators/generators_test_helper' +require 'generators/erb/mailer/mailer_generator' +require 'generators/rails/mailer/mailer_generator' +require 'generators/test_unit/mailer/mailer_generator' + +class MailerGeneratorTest < GeneratorsTestCase + + def test_mailer_skeleton_is_created + run_generator + assert_file "app/models/notifier.rb", /class Notifier < ActionMailer::Base/ + end + + def test_check_class_collision + content = capture(:stderr){ run_generator ["object"] } + assert_match /The name 'Object' is either already used in your application or reserved/, content + end + + def test_invokes_default_test_framework + run_generator + assert_file "test/unit/notifier_test.rb", /class NotifierTest < ActionMailer::TestCase/ + assert_file "test/fixtures/notifier/foo", /app\/views\/notifier\/foo/ + assert_file "test/fixtures/notifier/bar", /app\/views\/notifier\/bar/ + end + + def test_invokes_default_template_engine + run_generator + assert_file "app/views/notifier/foo.erb", /app\/views\/notifier\/foo/ + assert_file "app/views/notifier/bar.erb", /app\/views\/notifier\/bar/ + end + + def test_invokes_default_template_engine_even_with_no_action + run_generator ["notifier"] + assert_file "app/views/notifier" + end + + def test_logs_if_the_template_engine_cannot_be_found + content = run_generator ["notifier", "foo", "bar", "--template-engine=unknown"] + assert_match /Could not find and invoke 'unknown'/, content + end + + def test_actions_are_turned_into_methods + run_generator + assert_file "app/models/notifier.rb", /def foo/ + assert_file "app/models/notifier.rb", /def bar/ + end + + protected + + def run_generator(args=["notifier", "foo", "bar"]) + silence(:stdout) { Rails::Generators::MailerGenerator.start args, :root => destination_root } + end + +end diff --git a/railties/test/generators/metal_generator_test.rb b/railties/test/generators/metal_generator_test.rb new file mode 100644 index 0000000000..4e73883feb --- /dev/null +++ b/railties/test/generators/metal_generator_test.rb @@ -0,0 +1,23 @@ +require 'abstract_unit' +require 'generators/generators_test_helper' +require 'generators/rails/metal/metal_generator' + +class MetalGeneratorTest < GeneratorsTestCase + + def test_metal_skeleton_is_created + run_generator + assert_file "app/metal/foo.rb", /class Foo/ + end + + def test_check_class_collision + content = capture(:stderr){ run_generator ["object"] } + assert_match /The name 'Object' is either already used in your application or reserved/, content + end + + protected + + def run_generator(args=["foo"]) + silence(:stdout) { Rails::Generators::MetalGenerator.start args, :root => destination_root } + end + +end diff --git a/railties/test/generators/migration_generator_test.rb b/railties/test/generators/migration_generator_test.rb new file mode 100644 index 0000000000..547ca6a9e3 --- /dev/null +++ b/railties/test/generators/migration_generator_test.rb @@ -0,0 +1,60 @@ +require 'abstract_unit' +require 'generators/generators_test_helper' +require 'generators/active_record/migration/migration_generator' +require 'generators/rails/migration/migration_generator' + +class MigrationGeneratorTest < GeneratorsTestCase + + def test_migration + @migration = "change_title_body_from_posts" + run_generator + assert_migration "db/migrate/#{@migration}.rb", /class ChangeTitleBodyFromPosts < ActiveRecord::Migration/ + end + + def test_migration_with_class_name + @migration = "ChangeTitleBodyFromPosts" + run_generator + assert_migration "db/migrate/change_title_body_from_posts.rb", /class #{@migration} < ActiveRecord::Migration/ + end + + def test_add_migration_with_attributes + @migration = "add_title_body_to_posts" + run_generator [@migration, "title:string", "body:text"] + + assert_migration "db/migrate/#{@migration}.rb" do |content| + assert_class_method content, :up do |up| + assert_match /add_column :posts, :title, :string/, up + assert_match /add_column :posts, :body, :text/, up + end + + assert_class_method content, :down do |down| + assert_match /remove_column :posts, :title/, down + assert_match /remove_column :posts, :body/, down + end + end + end + + def test_remove_migration_with_attributes + @migration = "remove_title_body_from_posts" + run_generator [@migration, "title:string", "body:text"] + + assert_migration "db/migrate/#{@migration}.rb" do |content| + assert_class_method content, :up do |up| + assert_match /remove_column :posts, :title/, up + assert_match /remove_column :posts, :body/, up + end + + assert_class_method content, :down do |down| + assert_match /add_column :posts, :title, :string/, down + assert_match /add_column :posts, :body, :text/, down + end + end + end + + protected + + def run_generator(args=[@migration]) + silence(:stdout) { Rails::Generators::MigrationGenerator.start args, :root => destination_root } + end + +end diff --git a/railties/test/generators/model_generator_test.rb b/railties/test/generators/model_generator_test.rb new file mode 100644 index 0000000000..14cafe7b0d --- /dev/null +++ b/railties/test/generators/model_generator_test.rb @@ -0,0 +1,110 @@ +require 'abstract_unit' +require 'generators/generators_test_helper' +require 'generators/active_record/model/model_generator' +require 'generators/rails/model/model_generator' +require 'generators/test_unit/model/model_generator' + +class ModelGeneratorTest < GeneratorsTestCase + + def test_help_shows_invoked_generators_options + content = run_generator ["--help"] + assert_match /ActiveRecord options:/, content + assert_match /TestUnit options:/, content + end + + def test_invokes_default_orm + run_generator + assert_file "app/models/account.rb", /class Account < ActiveRecord::Base/ + end + + def test_model_with_parent_option + run_generator ["account", "--parent", "Admin::Account"] + assert_file "app/models/account.rb", /class Account < Admin::Account/ + assert_no_migration "db/migrate/create_accounts.rb" + end + + def test_model_with_underscored_parent_option + run_generator ["account", "--parent", "admin/account"] + assert_file "app/models/account.rb", /class Account < Admin::Account/ + end + + def test_migration + run_generator + assert_migration "db/migrate/create_accounts.rb", /class CreateAccounts < ActiveRecord::Migration/ + end + + def test_migration_is_skipped + run_generator ["account", "--no-migration"] + assert_no_migration "db/migrate/create_accounts.rb" + end + + def test_migration_with_attributes + run_generator ["product", "name:string", "supplier_id:integer"] + + assert_migration "db/migrate/create_products.rb" do |m| + assert_class_method m, :up do |up| + assert_match /create_table :products/, up + assert_match /t\.string :name/, up + assert_match /t\.integer :supplier_id/, up + end + + assert_class_method m, :down do |down| + assert_match /drop_table :products/, down + end + end + end + + def test_model_with_references_attribute_generates_belongs_to_associations + run_generator ["product", "name:string", "supplier_id:references"] + assert_file "app/models/product.rb", /belongs_to :supplier/ + end + + def test_model_with_belongs_to_attribute_generates_belongs_to_associations + run_generator ["product", "name:string", "supplier_id:belongs_to"] + assert_file "app/models/product.rb", /belongs_to :supplier/ + end + + def test_migration_with_timestamps + run_generator + assert_migration "db/migrate/create_accounts.rb", /t.timestamps/ + end + + def test_migration_timestamps_are_skipped + run_generator ["account", "--no-timestamps"] + + assert_migration "db/migrate/create_accounts.rb" do |m| + assert_class_method m, :up do |up| + assert_no_match /t.timestamps/, up + end + end + end + + def test_invokes_default_test_framework + run_generator + assert_file "test/unit/account_test.rb", /class AccountTest < ActiveSupport::TestCase/ + assert_file "test/fixtures/accounts.yml", /name: MyString/, /age: 1/ + end + + def test_fixture_is_skipped + run_generator ["account", "--skip-fixture"] + assert_no_file "test/fixtures/accounts.yml" + end + + def test_fixture_is_skipped_if_fixture_replacement_is_given + content = run_generator ["account", "-r", "fixjour"] + assert_match /Could not find and invoke 'fixjour'/, content + assert_no_file "test/fixtures/accounts.yml" + end + + def test_check_class_collision + content = capture(:stderr){ run_generator ["object"] } + assert_match /The name 'Object' is either already used in your application or reserved/, content + end + + protected + + def run_generator(args=["Account", "name:string", "age:integer"]) + silence(:stdout) { Rails::Generators::ModelGenerator.start args, :root => destination_root } + end + +end diff --git a/railties/test/generators/observer_generator_test.rb b/railties/test/generators/observer_generator_test.rb new file mode 100644 index 0000000000..3707b70c7e --- /dev/null +++ b/railties/test/generators/observer_generator_test.rb @@ -0,0 +1,35 @@ +require 'abstract_unit' +require 'generators/generators_test_helper' +require 'generators/active_record/observer/observer_generator' +require 'generators/rails/observer/observer_generator' +require 'generators/test_unit/observer/observer_generator' + +class ObserverGeneratorTest < GeneratorsTestCase + + def test_invokes_default_orm + run_generator + assert_file "app/models/account_observer.rb", /class AccountObserver < ActiveRecord::Observer/ + end + + def test_invokes_default_orm_with_class_path + run_generator ["admin/account"] + assert_file "app/models/admin/account_observer.rb", /class Admin::AccountObserver < ActiveRecord::Observer/ + end + + def test_invokes_default_test_framework + run_generator + assert_file "test/unit/account_observer_test.rb", /class AccountObserverTest < ActiveSupport::TestCase/ + end + + def test_logs_if_the_test_framework_cannot_be_found + content = run_generator ["account", "--test-framework=unknown"] + assert_match /Could not find and invoke 'unknown'/, content + end + + protected + + def run_generator(args=["account"]) + silence(:stdout) { Rails::Generators::ObserverGenerator.start args, :root => destination_root } + end + +end diff --git a/railties/test/generators/performance_test_generator_test.rb b/railties/test/generators/performance_test_generator_test.rb new file mode 100644 index 0000000000..fdfbf9031c --- /dev/null +++ b/railties/test/generators/performance_test_generator_test.rb @@ -0,0 +1,18 @@ +require 'abstract_unit' +require 'generators/generators_test_helper' +require 'generators/rails/performance_test/performance_test_generator' + +class PerformanceTestGeneratorTest < GeneratorsTestCase + + def test_performance_test_skeleton_is_created + run_generator + assert_file "test/performance/performance_test.rb", /class PerformanceTest < ActionController::PerformanceTest/ + end + + protected + + def run_generator(args=["performance"]) + silence(:stdout) { Rails::Generators::PerformanceTestGenerator.start args, :root => destination_root } + end + +end diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb new file mode 100644 index 0000000000..3388b2f6f5 --- /dev/null +++ b/railties/test/generators/plugin_generator_test.rb @@ -0,0 +1,53 @@ +require 'abstract_unit' +require 'generators/generators_test_helper' +require 'generators/rails/plugin/plugin_generator' +require 'generators/test_unit/plugin/plugin_generator' + +class PluginGeneratorTest < GeneratorsTestCase + + def test_plugin_skeleton_is_created + run_generator + + %w( + vendor/plugins + vendor/plugins/plugin_fu + vendor/plugins/plugin_fu/lib + ).each{ |path| assert_file path } + end + + def test_check_class_collision + content = capture(:stderr){ run_generator ["object"] } + assert_match /The name 'Object' is either already used in your application or reserved/, content + end + + def test_invokes_default_test_framework + run_generator + assert_file "vendor/plugins/plugin_fu/test/plugin_fu_test.rb", /class PluginFuTest < ActiveSupport::TestCase/ + assert_file "vendor/plugins/plugin_fu/test/test_helper.rb" + end + + def test_logs_if_the_test_framework_cannot_be_found + content = run_generator ["plugin_fu", "--test-framework=unknown"] + assert_match /Could not find and invoke 'unknown'/, content + end + + def test_creates_tasks_if_required + run_generator ["plugin_fu", "--with-tasks"] + assert_file "vendor/plugins/plugin_fu/tasks/plugin_fu_tasks.rake" + end + + def test_creates_generator_if_required + run_generator ["plugin_fu", "--with-generator"] + assert_file "vendor/plugins/plugin_fu/generators/plugin_fu/templates" + + flag = /class PluginFuGenerator < Rails::Generators::NamedBase/ + assert_file "vendor/plugins/plugin_fu/generators/plugin_fu/plugin_fu_generator.rb", flag + end + + protected + + def run_generator(args=["plugin_fu"]) + silence(:stdout) { Rails::Generators::PluginGenerator.start args, :root => destination_root } + end + +end diff --git a/railties/test/generators/rails_template_runner_test.rb b/railties/test/generators/rails_template_runner_test.rb deleted file mode 100644 index 2da6bd59b5..0000000000 --- a/railties/test/generators/rails_template_runner_test.rb +++ /dev/null @@ -1,216 +0,0 @@ -require 'abstract_unit' -require 'generators/generator_test_helper' - -class RailsTemplateRunnerTest < GeneratorTestCase - def setup - Rails::Generator::Base.use_application_sources! - run_generator('app', [RAILS_ROOT]) - # generate empty template - @template_path = File.join(RAILS_ROOT, 'template.rb') - File.open(File.join(@template_path), 'w') {|f| f << '' } - - @git_plugin_uri = 'git://github.com/technoweenie/restful-authentication.git' - @svn_plugin_uri = 'svn://svnhub.com/technoweenie/restful-authentication/trunk' - end - - def teardown - super - rm_rf "#{RAILS_ROOT}/README" - rm_rf "#{RAILS_ROOT}/Rakefile" - rm_rf "#{RAILS_ROOT}/doc" - rm_rf "#{RAILS_ROOT}/lib" - rm_rf "#{RAILS_ROOT}/log" - rm_rf "#{RAILS_ROOT}/script" - rm_rf "#{RAILS_ROOT}/vendor" - rm_rf "#{RAILS_ROOT}/tmp" - rm_rf "#{RAILS_ROOT}/Capfile" - rm_rf @template_path - end - - def test_initialize_should_load_template - Rails::TemplateRunner.any_instance.expects(:load_template).with(@template_path) - silence_generator do - Rails::TemplateRunner.new(@template_path, RAILS_ROOT) - end - end - - def test_initialize_should_raise_error_on_missing_template_file - assert_raise(RuntimeError) do - silence_generator do - Rails::TemplateRunner.new('non/existent/path/to/template.rb', RAILS_ROOT) - end - end - end - - def test_file_should_write_data_to_file_path - run_template_method(:file, 'lib/test_file.rb', 'heres test data') - assert_generated_file_with_data 'lib/test_file.rb', 'heres test data' - end - - def test_file_should_write_block_contents_to_file_path - run_template_method(:file, 'lib/test_file.rb') { 'heres block data' } - assert_generated_file_with_data 'lib/test_file.rb', 'heres block data' - end - - def test_plugin_with_git_option_should_run_plugin_install - expects_run_ruby_script_with_command("script/plugin install #{@git_plugin_uri}") - run_template_method(:plugin, 'restful-authentication', :git => @git_plugin_uri) - end - - def test_plugin_with_svn_option_should_run_plugin_install - expects_run_ruby_script_with_command("script/plugin install #{@svn_plugin_uri}") - run_template_method(:plugin, 'restful-authentication', :svn => @svn_plugin_uri) - end - - def test_plugin_with_git_option_and_submodule_should_use_git_scm - Rails::Git.expects(:run).with("submodule add #{@git_plugin_uri} vendor/plugins/rest_auth") - run_template_method(:plugin, 'rest_auth', :git => @git_plugin_uri, :submodule => true) - end - - def test_plugin_with_no_options_should_skip_method - Rails::TemplateRunner.any_instance.expects(:run).never - run_template_method(:plugin, 'rest_auth', {}) - end - - def test_gem_should_put_gem_dependency_in_enviroment - run_template_method(:gem, 'will-paginate') - assert_rails_initializer_includes("config.gem 'will-paginate'") - end - - def test_gem_with_options_should_include_options_in_gem_dependency_in_environment - run_template_method(:gem, 'mislav-will-paginate', :lib => 'will-paginate', :source => 'http://gems.github.com') - assert_rails_initializer_includes("config.gem 'mislav-will-paginate', :lib => 'will-paginate', :source => 'http://gems.github.com'") - end - - def test_gem_with_env_string_should_put_gem_dependency_in_specified_environment - run_template_method(:gem, 'rspec', :env => 'test') - assert_generated_file_with_data('config/environments/test.rb', "config.gem 'rspec'", 'test') - end - - def test_gem_with_env_array_should_put_gem_dependency_in_specified_environments - run_template_method(:gem, 'quietbacktrace', :env => %w[ development test ]) - assert_generated_file_with_data('config/environments/development.rb', "config.gem 'quietbacktrace'") - assert_generated_file_with_data('config/environments/test.rb', "config.gem 'quietbacktrace'") - end - - def test_gem_with_lib_option_set_to_false_should_put_gem_dependency_in_enviroment_correctly - run_template_method(:gem, 'mislav-will-paginate', :lib => false, :source => 'http://gems.github.com') - assert_rails_initializer_includes("config.gem 'mislav-will-paginate', :lib => false, :source => 'http://gems.github.com'") - end - - def test_environment_should_include_data_in_environment_initializer_block - load_paths = 'config.load_paths += %w["#{RAILS_ROOT}/app/extras"]' - run_template_method(:environment, load_paths) - assert_rails_initializer_includes(load_paths) - end - - def test_environment_with_block_should_include_block_contents_in_environment_initializer_block - run_template_method(:environment) do - '# This wont be added' - '# This will be added' - end - assert_rails_initializer_includes('# This will be added') - end - - def test_git_with_symbol_should_run_command_using_git_scm - Rails::Git.expects(:run).once.with('init') - run_template_method(:git, :init) - end - - def test_git_with_hash_should_run_each_command_using_git_scm - Rails::Git.expects(:run).times(2) - run_template_method(:git, {:init => '', :add => '.'}) - end - - def test_vendor_should_write_data_to_file_in_vendor - run_template_method(:vendor, 'vendor_file.rb', '# vendor data') - assert_generated_file_with_data('vendor/vendor_file.rb', '# vendor data') - end - - def test_lib_should_write_data_to_file_in_lib - run_template_method(:lib, 'my_library.rb', 'class MyLibrary') - assert_generated_file_with_data('lib/my_library.rb', 'class MyLibrary') - end - - def test_rakefile_should_write_date_to_file_in_lib_tasks - run_template_method(:rakefile, 'myapp.rake', 'task :run => [:environment]') - assert_generated_file_with_data('lib/tasks/myapp.rake', 'task :run => [:environment]') - end - - def test_initializer_should_write_date_to_file_in_config_initializers - run_template_method(:initializer, 'constants.rb', 'MY_CONSTANT = 42') - assert_generated_file_with_data('config/initializers/constants.rb', 'MY_CONSTANT = 42') - end - - def test_generate_should_run_script_generate_with_argument_and_options - expects_run_ruby_script_with_command('script/generate model MyModel') - run_template_method(:generate, 'model', 'MyModel') - end - - def test_rake_should_run_rake_command_with_development_env - expects_run_with_command('rake log:clear RAILS_ENV=development') - run_template_method(:rake, 'log:clear') - end - - def test_rake_with_env_option_should_run_rake_command_in_env - expects_run_with_command('rake log:clear RAILS_ENV=production') - run_template_method(:rake, 'log:clear', :env => 'production') - end - - def test_rake_with_sudo_option_should_run_rake_command_with_sudo - expects_run_with_command('sudo rake log:clear RAILS_ENV=development') - run_template_method(:rake, 'log:clear', :sudo => true) - end - - def test_capify_should_run_the_capify_command - expects_run_with_command('capify .') - run_template_method(:capify!) - end - - def test_freeze_should_freeze_rails_edge - expects_run_with_command('rake rails:freeze:edge') - run_template_method(:freeze!) - end - - def test_route_should_add_data_to_the_routes_block_in_config_routes - route_command = "map.route '/login', :controller => 'sessions', :action => 'new'" - run_template_method(:route, route_command) - assert_generated_file_with_data 'config/routes.rb', route_command - end - - def test_run_ruby_script_should_add_ruby_to_command_in_win32_environment - ruby_command = RUBY_PLATFORM =~ /win32/ ? 'ruby ' : '' - expects_run_with_command("#{ruby_command}script/generate model MyModel") - run_template_method(:generate, 'model', 'MyModel') - end - - protected - def run_template_method(method_name, *args, &block) - silence_generator do - @template_runner = Rails::TemplateRunner.new(@template_path, RAILS_ROOT) - @template_runner.send(method_name, *args, &block) - end - end - - def expects_run_with_command(command) - Rails::TemplateRunner.any_instance.stubs(:run).once.with(command, false) - end - - def expects_run_ruby_script_with_command(command) - Rails::TemplateRunner.any_instance.stubs(:run_ruby_script).once.with(command,false) - end - - def assert_rails_initializer_includes(data, message = nil) - message ||= "Rails::Initializer should include #{data}" - assert_generated_file 'config/environment.rb' do |body| - assert_match(/#{Regexp.escape("Rails::Initializer.run do |config|")}.+#{Regexp.escape(data)}.+end/m, body, message) - end - end - - def assert_generated_file_with_data(file, data, message = nil) - message ||= "#{file} should include '#{data}'" - assert_generated_file(file) do |file| - assert_match(/#{Regexp.escape(data)}/,file, message) - end - end -end
\ No newline at end of file diff --git a/railties/test/generators/resource_generator_test.rb b/railties/test/generators/resource_generator_test.rb new file mode 100644 index 0000000000..456e6ff3ea --- /dev/null +++ b/railties/test/generators/resource_generator_test.rb @@ -0,0 +1,95 @@ +require 'abstract_unit' +require 'generators/generators_test_helper' +require 'generators/rails/resource/resource_generator' + +# Model +require 'generators/active_record/model/model_generator' +require 'generators/rails/model/model_generator' +require 'generators/test_unit/model/model_generator' + +# Controller +require 'generators/erb/controller/controller_generator' +require 'generators/rails/controller/controller_generator' +require 'generators/rails/helper/helper_generator' +require 'generators/test_unit/controller/controller_generator' +require 'generators/test_unit/helper/helper_generator' + +class ResourceGeneratorTest < GeneratorsTestCase + + def setup + super + routes = Rails::Generators::ResourceGenerator.source_root + routes = File.join(routes, "..", "..", "app", "templates", "config", "routes.rb") + destination = File.join(destination_root, "config") + + FileUtils.mkdir_p(destination) + FileUtils.cp File.expand_path(routes), destination + end + + def test_help_with_inherited_options + content = run_generator ["--help"] + assert_match /ActiveRecord options:/, content + assert_match /TestUnit options:/, content + end + + def test_files_from_inherited_invocation + run_generator + + %w( + app/models/account.rb + test/unit/account_test.rb + test/fixtures/accounts.yml + ).each { |path| assert_file path } + + assert_migration "db/migrate/create_accounts.rb" + end + + def test_inherited_invocations_with_attributes + run_generator ["account", "name:string"] + assert_migration "db/migrate/create_accounts.rb", /t.string :name/ + end + + def test_resource_controller_with_pluralized_class_name + run_generator + assert_file "app/controllers/accounts_controller.rb", /class AccountsController < ApplicationController/ + assert_file "test/functional/accounts_controller_test.rb", /class AccountsControllerTest < ActionController::TestCase/ + + assert_file "app/helpers/accounts_helper.rb", /module AccountsHelper/ + assert_file "test/unit/helpers/accounts_helper_test.rb", /class AccountsHelperTest < ActionView::TestCase/ + end + + def test_resource_controller_with_actions + run_generator ["account", "--actions", "index", "new"] + + assert_file "app/controllers/accounts_controller.rb" do |controller| + assert_instance_method controller, :index + assert_instance_method controller, :new + end + + assert_file "app/views/accounts/index.html.erb" + assert_file "app/views/accounts/new.html.erb" + end + + def test_resource_routes_are_added + run_generator + + assert_file "config/routes.rb" do |route| + assert_match /map\.resources :accounts$/, route + end + end + + def test_singleton_resource + run_generator ["account", "--singleton"] + + assert_file "config/routes.rb" do |route| + assert_match /map\.resource :account$/, route + end + end + + protected + + def run_generator(args=["account"]) + silence(:stdout) { Rails::Generators::ResourceGenerator.start args, :root => destination_root } + end + +end diff --git a/railties/test/generators/session_migration_generator_test.rb b/railties/test/generators/session_migration_generator_test.rb new file mode 100644 index 0000000000..05b51b1566 --- /dev/null +++ b/railties/test/generators/session_migration_generator_test.rb @@ -0,0 +1,24 @@ +require 'abstract_unit' +require 'generators/generators_test_helper' +require 'generators/active_record/session_migration/session_migration_generator' +require 'generators/rails/session_migration/session_migration_generator' + +class SessionMigrationGeneratorTest < GeneratorsTestCase + + def test_session_migration_with_default_name + run_generator + assert_migration "db/migrate/add_sessions_table.rb", /class AddSessionsTable < ActiveRecord::Migration/ + end + + def test_session_migration_with_given_name + run_generator ["create_session_table"] + assert_migration "db/migrate/create_session_table.rb", /class CreateSessionTable < ActiveRecord::Migration/ + end + + protected + + def run_generator(args=[]) + silence(:stdout) { Rails::Generators::SessionMigrationGenerator.start args, :root => destination_root } + end + +end diff --git a/railties/test/generators/generator_test_helper.rb b/railties/test/rails_generator/generator_test_helper.rb index 01bf1c90bd..01bf1c90bd 100644 --- a/railties/test/generators/generator_test_helper.rb +++ b/railties/test/rails_generator/generator_test_helper.rb diff --git a/railties/test/generators/rails_controller_generator_test.rb b/railties/test/rails_generator/rails_controller_generator_test.rb index 43fbe972e2..6cbb6bf2bd 100644 --- a/railties/test/generators/rails_controller_generator_test.rb +++ b/railties/test/rails_generator/rails_controller_generator_test.rb @@ -1,4 +1,4 @@ -require 'generators/generator_test_helper' +require 'rails_generator/generator_test_helper' module Admin end diff --git a/railties/test/generators/rails_helper_generator_test.rb b/railties/test/rails_generator/rails_helper_generator_test.rb index 8d05f555e6..8d05f555e6 100644 --- a/railties/test/generators/rails_helper_generator_test.rb +++ b/railties/test/rails_generator/rails_helper_generator_test.rb diff --git a/railties/test/generators/rails_mailer_generator_test.rb b/railties/test/rails_generator/rails_mailer_generator_test.rb index de61e6736d..f580fe27ab 100644 --- a/railties/test/generators/rails_mailer_generator_test.rb +++ b/railties/test/rails_generator/rails_mailer_generator_test.rb @@ -1,4 +1,4 @@ -require 'generators/generator_test_helper' +require 'rails_generator/generator_test_helper' class RailsMailerGeneratorTest < GeneratorTestCase diff --git a/railties/test/generators/rails_model_generator_test.rb b/railties/test/rails_generator/rails_model_generator_test.rb index aea2abafba..ae3c2e316e 100644 --- a/railties/test/generators/rails_model_generator_test.rb +++ b/railties/test/rails_generator/rails_model_generator_test.rb @@ -1,4 +1,4 @@ -require 'generators/generator_test_helper' +require 'rails_generator/generator_test_helper' class RailsModelGeneratorTest < GeneratorTestCase diff --git a/railties/test/generators/rails_model_subclass_generator_test.rb b/railties/test/rails_generator/rails_model_subclass_generator_test.rb index 30066b5a3c..4f20de6eba 100644 --- a/railties/test/generators/rails_model_subclass_generator_test.rb +++ b/railties/test/rails_generator/rails_model_subclass_generator_test.rb @@ -1,4 +1,4 @@ -require 'generators/generator_test_helper' +require 'rails_generator/generator_test_helper' class RailsModelSubclassGeneratorTest < GeneratorTestCase @@ -12,4 +12,4 @@ class RailsModelSubclassGeneratorTest < GeneratorTestCase def test_model_subclass_must_have_a_parent_class_name assert_raise(Rails::Generator::UsageError) { run_generator('model_subclass', %w(Car)) } end -end
\ No newline at end of file +end diff --git a/railties/test/generators/rails_resource_generator_test.rb b/railties/test/rails_generator/rails_resource_generator_test.rb index 1f5bd0ef1e..b9a432cbff 100644 --- a/railties/test/generators/rails_resource_generator_test.rb +++ b/railties/test/rails_generator/rails_resource_generator_test.rb @@ -1,4 +1,4 @@ -require 'generators/generator_test_helper' +require 'rails_generator/generator_test_helper' class RailsResourceGeneratorTest < GeneratorTestCase def test_resource_generates_resources diff --git a/railties/test/generators/rails_scaffold_generator_test.rb b/railties/test/rails_generator/rails_scaffold_generator_test.rb index 70829a77fd..ffbeff79fb 100644 --- a/railties/test/generators/rails_scaffold_generator_test.rb +++ b/railties/test/rails_generator/rails_scaffold_generator_test.rb @@ -1,4 +1,4 @@ -require 'generators/generator_test_helper' +require 'rails_generator/generator_test_helper' require 'abstract_unit' class RailsScaffoldGeneratorTest < GeneratorTestCase diff --git a/railties/test/secret_key_generation_test.rb b/railties/test/secret_key_generation_test.rb deleted file mode 100644 index 2c7c3d5dfe..0000000000 --- a/railties/test/secret_key_generation_test.rb +++ /dev/null @@ -1,38 +0,0 @@ -require 'abstract_unit' - -# Must set before requiring generator libs. -if defined?(RAILS_ROOT) - RAILS_ROOT.replace "#{File.dirname(__FILE__)}/fixtures" -else - RAILS_ROOT = "#{File.dirname(__FILE__)}/fixtures" -end - -$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' -require 'rails_generator/secret_key_generator' -require 'rails_generator/generators/applications/app/app_generator' - -class SecretKeyGenerationTest < ActiveSupport::TestCase - SECRET_KEY_MIN_LENGTH = 128 - APP_NAME = "foo" - - def setup - @generator = Rails::SecretKeyGenerator.new(APP_NAME) - end - - def test_secret_key_generation - assert_deprecated /ActiveSupport::SecureRandom\.hex\(64\)/ do - assert @generator.generate_secret.length >= SECRET_KEY_MIN_LENGTH - end - end -end |