Merge remote branch 'drogus/plugin_new'

Conflicts:
	railties/test/generators/app_generator_test.rb
This commit is contained in:
José Valim
2010-11-11 19:39:21 +01:00
57 changed files with 1311 additions and 324 deletions

View File

@@ -14,7 +14,7 @@ module ActiveRecord
config.active_record = ActiveSupport::OrderedOptions.new
config.app_generators.orm :active_record, :migration => true,
:timestamps => true
:timestamps => true
config.app_middleware.insert_after "::ActionDispatch::Callbacks",
"ActiveRecord::QueryCache"

View File

@@ -1,5 +1,6 @@
require 'active_support/core_ext/hash/conversions'
require 'active_support/core_ext/hash/deep_merge'
require 'active_support/core_ext/hash/deep_dup'
require 'active_support/core_ext/hash/diff'
require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/hash/indifferent_access'

View File

@@ -0,0 +1,11 @@
class Hash
# Returns a deep copy of hash.
def deep_dup
duplicate = self.dup
duplicate.each_pair do |k,v|
tv = duplicate[k]
duplicate[k] = tv.is_a?(Hash) && v.is_a?(Hash) ? tv.deep_dup : v
end
duplicate
end
end

View File

@@ -329,6 +329,21 @@ class HashExtTest < Test::Unit::TestCase
assert_equal expected, hash_1
end
def test_deep_dup
hash = { :a => { :b => 'b' } }
dup = hash.deep_dup
dup[:a][:c] = 'c'
assert_equal nil, hash[:a][:c]
assert_equal 'c', dup[:a][:c]
end
def test_deep_dup_initialize
zero_hash = Hash.new 0
hash = { :a => zero_hash }
dup = hash.deep_dup
assert_equal 0, dup[:a][44]
end
def test_store_on_indifferent_access
hash = HashWithIndifferentAccess.new
hash.store(:test1, 1)

View File

@@ -8,4 +8,9 @@ Rails::ScriptRailsLoader.exec_script_rails!
require 'rails/ruby_version_check'
Signal.trap("INT") { puts; exit }
require 'rails/commands/application'
if ARGV.first == 'plugin'
ARGV.shift
require 'rails/commands/plugin_new'
else
require 'rails/commands/application'
end

View File

@@ -0,0 +1,16 @@
require 'rails/version'
if %w(--version -v).include? ARGV.first
puts "Rails #{Rails::VERSION::STRING}"
exit(0)
end
if ARGV.first != "new"
ARGV[0] = "--help"
else
ARGV.shift
end
require 'rails/generators'
require 'rails/generators/rails/plugin_new/plugin_new_generator'
Rails::Generators::PluginNewGenerator.start

View File

@@ -1,5 +1,6 @@
require 'active_support/deprecation'
require 'active_support/ordered_options'
require 'active_support/core_ext/hash/deep_dup'
require 'rails/paths'
require 'rails/rack'
@@ -51,6 +52,13 @@ module Rails
@colorize_logging = true
end
def initialize_copy(source)
@aliases = @aliases.deep_dup
@options = @options.deep_dup
@fallbacks = @fallbacks.deep_dup
@templates = @templates.dup
end
def method_missing(method, *args)
method = method.to_s.sub(/=$/, '').to_sym

View File

@@ -10,6 +10,7 @@ module Rails
def initialize(root=nil)
super()
@root = root
@generators = app_generators.dup
end
# Returns the middleware stack for the engine.

View File

@@ -0,0 +1,176 @@
require 'digest/md5'
require 'active_support/secure_random'
require 'rails/version' unless defined?(Rails::VERSION)
require 'rbconfig'
require 'open-uri'
require 'uri'
module Rails
module Generators
class AppBase < Base
DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db )
JAVASCRIPTS = %w( prototype jquery )
attr_accessor :rails_template
add_shebang_option!
argument :app_path, :type => :string
def self.add_shared_options_for(name)
class_option :builder, :type => :string, :aliases => "-b",
:desc => "Path to a #{name} builder (can be a filesystem path or URL)"
class_option :template, :type => :string, :aliases => "-m",
:desc => "Path to an #{name} template (can be a filesystem path or URL)"
class_option :skip_gemfile, :type => :boolean, :default => false,
:desc => "Don't create a Gemfile"
class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false,
:desc => "Skip Git ignores and keeps"
class_option :skip_active_record, :type => :boolean, :aliases => "-O", :default => false,
:desc => "Skip Active Record files"
class_option :database, :type => :string, :aliases => "-d", :default => "sqlite3",
:desc => "Preconfigure for selected database (options: #{DATABASES.join('/')})"
class_option :javascript, :type => :string, :aliases => "-j", :default => "prototype",
:desc => "Preconfigure for selected javascript library (options: #{JAVASCRIPTS.join('/')})"
class_option :skip_javascript, :type => :boolean, :aliases => "-J", :default => false,
:desc => "Skip javascript files"
class_option :dev, :type => :boolean, :default => false,
:desc => "Setup the #{name} with Gemfile pointing to your Rails checkout"
class_option :edge, :type => :boolean, :default => false,
:desc => "Setup the #{name} with Gemfile pointing to Rails repository"
class_option :skip_test_unit, :type => :boolean, :aliases => "-T", :default => false,
:desc => "Skip Test::Unit files"
class_option :help, :type => :boolean, :aliases => "-h", :group => :rails,
:desc => "Show this help message and quit"
end
def initialize(*args)
@original_wd = Dir.pwd
super
end
protected
def builder
@builder ||= begin
if path = options[:builder]
if URI(path).is_a?(URI::HTTP)
contents = open(path, "Accept" => "application/x-thor-template") {|io| io.read }
else
contents = open(File.expand_path(path, @original_wd)) {|io| io.read }
end
prok = eval("proc { #{contents} }", TOPLEVEL_BINDING, path, 1)
instance_eval(&prok)
end
builder_class = get_builder_class
builder_class.send(:include, ActionMethods)
builder_class.new(self)
end
end
def build(meth, *args)
builder.send(meth, *args) if builder.respond_to?(meth)
end
def create_root
self.destination_root = File.expand_path(app_path, destination_root)
valid_const?
empty_directory '.'
set_default_accessors!
FileUtils.cd(destination_root) unless options[:pretend]
end
def apply_rails_template
apply rails_template if rails_template
rescue Thor::Error, LoadError, Errno::ENOENT => e
raise Error, "The template [#{rails_template}] could not be loaded. Error: #{e}"
end
def set_default_accessors!
self.rails_template = case options[:template]
when /^http:\/\//
options[:template]
when String
File.expand_path(options[:template], Dir.pwd)
else
options[:template]
end
end
def database_gemfile_entry
entry = ""
unless options[:skip_active_record]
entry = "gem '#{gem_for_database}'"
entry << ", :require => '#{require_for_database}'" if require_for_database
end
entry
end
def rails_gemfile_entry
if options.dev?
<<-GEMFILE
gem 'rails', :path => '#{Rails::Generators::RAILS_DEV_PATH}'
gem 'arel', :git => 'git://github.com/rails/arel.git'
gem "rack", :git => "git://github.com/rack/rack.git"
GEMFILE
elsif options.edge?
<<-GEMFILE
gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'arel', :git => 'git://github.com/rails/arel.git'
gem "rack", :git => "git://github.com/rack/rack.git"
GEMFILE
else
<<-GEMFILE
gem 'rails', '#{Rails::VERSION::STRING}'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
# gem 'arel', :git => 'git://github.com/rails/arel.git'
# gem "rack", :git => "git://github.com/rack/rack.git"
GEMFILE
end
end
def gem_for_database
# %w( mysql oracle postgresql sqlite3 frontbase ibm_db )
case options[:database]
when "oracle" then "ruby-oci8"
when "postgresql" then "pg"
when "sqlite3" then "sqlite3-ruby"
when "frontbase" then "ruby-frontbase"
when "mysql" then "mysql2"
else options[:database]
end
end
def require_for_database
case options[:database]
when "sqlite3" then "sqlite3"
end
end
def bundle_if_dev_or_edge
bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle')
run "#{bundle_command} install" if dev_or_edge?
end
def dev_or_edge?
options.dev? || options.edge?
end
end
end
end

View File

@@ -1,3 +1,4 @@
<% without_namespacing do -%>
<%%= form_for(@<%= singular_table_name %>) do |f| %>
<%% if @<%= singular_table_name %>.errors.any? %>
<div id="error_explanation">
@@ -21,3 +22,4 @@
<%%= f.submit %>
</div>
<%% end %>
<% end -%>

View File

@@ -1,6 +1,8 @@
<% without_namespacing do -%>
<h1>Editing <%= singular_table_name %></h1>
<%%= render 'form' %>
<%%= link_to 'Show', @<%= singular_table_name %> %> |
<%%= link_to 'Back', <%= index_helper %>_path %>
<% end -%>

View File

@@ -1,3 +1,4 @@
<% without_namespacing do -%>
<h1>Listing <%= plural_table_name %></h1>
<table>
@@ -25,3 +26,4 @@
<br />
<%%= link_to 'New <%= human_name %>', new_<%= singular_table_name %>_path %>
<% end -%>

View File

@@ -1,5 +1,7 @@
<% without_namespacing do -%>
<h1>New <%= singular_table_name %></h1>
<%%= render 'form' %>
<%%= link_to 'Back', <%= index_helper %>_path %>
<% end -%>

View File

@@ -1,3 +1,4 @@
<% without_namespacing do -%>
<p id="notice"><%%= notice %></p>
<% for attribute in attributes -%>
@@ -10,3 +11,4 @@
<%%= link_to 'Edit', edit_<%= singular_table_name %>_path(@<%= singular_table_name %>) %> |
<%%= link_to 'Back', <%= index_helper %>_path %>
<% end -%>

View File

@@ -30,9 +30,15 @@ module Rails
end
end
def without_namespacing(&block)
inside_namespace do
concat(capture(&block))
end
end
def indent(content, multiplier = 2)
spaces = " " * multiplier
content.each_line.map {|line| "#{spaces}#{line}" }.join("\n")
content = content.each_line.map {|line| "#{spaces}#{line}" }.join
end
def wrap_with_namespace(content)

View File

@@ -1,9 +1,4 @@
require 'digest/md5'
require 'active_support/secure_random'
require 'rails/version' unless defined?(Rails::VERSION)
require 'rbconfig'
require 'open-uri'
require 'uri'
require 'rails/generators/app_base'
module Rails
module ActionMethods
@@ -158,60 +153,16 @@ module Rails
RESERVED_NAMES = %w[application destroy benchmarker profiler
plugin runner test]
class AppGenerator < Base
DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db )
JAVASCRIPTS = %w( prototype jquery )
attr_accessor :rails_template
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 :javascript, :type => :string, :aliases => "-j", :default => "prototype",
:desc => "Preconfigure for selected javascript library (options: #{JAVASCRIPTS.join('/')})"
class_option :builder, :type => :string, :aliases => "-b",
:desc => "Path to an application builder (can be a filesystem path or URL)"
class_option :template, :type => :string, :aliases => "-m",
:desc => "Path to an application template (can be a filesystem path or URL)"
class_option :dev, :type => :boolean, :default => false,
:desc => "Setup the application with Gemfile pointing to your Rails checkout"
class_option :edge, :type => :boolean, :default => false,
:desc => "Setup the application with Gemfile pointing to Rails repository"
class_option :skip_gemfile, :type => :boolean, :default => false,
:desc => "Don't create a Gemfile"
class_option :skip_active_record, :type => :boolean, :aliases => "-O", :default => false,
:desc => "Skip Active Record files"
class_option :skip_test_unit, :type => :boolean, :aliases => "-T", :default => false,
:desc => "Skip Test::Unit files"
class_option :skip_javascript, :type => :boolean, :aliases => "-J", :default => false,
:desc => "Skip javascript files"
class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false,
:desc => "Skip Git ignores and keeps"
class AppGenerator < AppBase
add_shared_options_for "application"
# Add bin/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)
raise Error, "Options should be given after the application name. For details run: rails --help" if args[0].blank?
@original_wd = Dir.pwd
super
if !options[:skip_active_record] && !DATABASES.include?(options[:database])
@@ -223,14 +174,7 @@ module Rails
end
end
def create_root
self.destination_root = File.expand_path(app_path, destination_root)
valid_app_const?
empty_directory '.'
set_default_accessors!
FileUtils.cd(destination_root) unless options[:pretend]
end
public_task :create_root
def create_root_files
build(:readme)
@@ -309,16 +253,7 @@ module Rails
build(:leftovers)
end
def apply_rails_template
apply rails_template if rails_template
rescue Thor::Error, LoadError, Errno::ENOENT => e
raise Error, "The template [#{rails_template}] could not be loaded. Error: #{e}"
end
def bundle_if_dev_or_edge
bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle')
run "#{bundle_command} install" if dev_or_edge?
end
public_task :apply_rails_template, :bundle_if_dev_or_edge
protected
@@ -326,40 +261,6 @@ module Rails
"rails new #{self.arguments.map(&:usage).join(' ')} [options]"
end
def builder
@builder ||= begin
if path = options[:builder]
if URI(path).is_a?(URI::HTTP)
contents = open(path, "Accept" => "application/x-thor-template") {|io| io.read }
else
contents = open(File.expand_path(path, @original_wd)) {|io| io.read }
end
prok = eval("proc { #{contents} }", TOPLEVEL_BINDING, path, 1)
instance_eval(&prok)
end
builder_class = defined?(::AppBuilder) ? ::AppBuilder : Rails::AppBuilder
builder_class.send(:include, ActionMethods)
builder_class.new(self)
end
end
def build(meth, *args)
builder.send(meth, *args) if builder.respond_to?(meth)
end
def set_default_accessors!
self.rails_template = case options[:template]
when /^http:\/\//
options[:template]
when String
File.expand_path(options[:template], Dir.pwd)
else
options[:template]
end
end
# Define file as an alias to create_file for backwards compatibility.
def file(*args, &block)
create_file(*args, &block)
@@ -388,7 +289,7 @@ module Rails
@app_const ||= "#{app_const_base}::Application"
end
def valid_app_const?
def valid_const?
if app_const =~ /^\d/
raise Error, "Invalid application name #{app_name}. Please give a name which does not start with numbers."
elsif RESERVED_NAMES.include?(app_name)
@@ -402,28 +303,6 @@ module Rails
ActiveSupport::SecureRandom.hex(64)
end
def dev_or_edge?
options.dev? || options.edge?
end
def gem_for_database
# %w( mysql oracle postgresql sqlite3 frontbase ibm_db )
case options[:database]
when "oracle" then "ruby-oci8"
when "postgresql" then "pg"
when "sqlite3" then "sqlite3-ruby"
when "frontbase" then "ruby-frontbase"
when "mysql" then "mysql2"
else options[:database]
end
end
def require_for_database
case options[:database]
when "sqlite3" then "sqlite3"
end
end
def mysql_socket
@mysql_socket ||= [
"/tmp/mysql.sock", # default
@@ -442,6 +321,10 @@ module Rails
empty_directory(destination, config)
create_file("#{destination}/.gitkeep") unless options[:skip_git]
end
def get_builder_class
defined?(::AppBuilder) ? ::AppBuilder : Rails::AppBuilder
end
end
end
end

View File

@@ -1,25 +1,8 @@
source 'http://rubygems.org'
<%- if options.dev? -%>
gem 'rails', :path => '<%= Rails::Generators::RAILS_DEV_PATH %>'
gem 'arel', :git => 'git://github.com/rails/arel.git'
gem "rack", :git => "git://github.com/rack/rack.git"
<%- elsif options.edge? -%>
gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'arel', :git => 'git://github.com/rails/arel.git'
gem "rack", :git => "git://github.com/rack/rack.git"
<%- else -%>
gem 'rails', '<%= Rails::VERSION::STRING %>'
<%= rails_gemfile_entry -%>
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
# gem 'arel', :git => 'git://github.com/rails/arel.git'
# gem "rack", :git => "git://github.com/rack/rack.git"
<%- end -%>
<% unless options[:skip_active_record] -%>
gem '<%= gem_for_database %>'<% if require_for_database %>, :require => '<%= require_for_database %>'<% end %>
<% end -%>
<%= database_gemfile_entry -%>
# Use unicorn as the web server
# gem 'unicorn'

View File

@@ -0,0 +1,10 @@
Description:
The 'rails plugin new' command creates a skeleton for developing any
kind of Rails extension with ability to run tests using dummy Rails
application.
Example:
rails plugin new ~/Code/Ruby/blog
This generates a skeletal Rails plugin in ~/Code/Ruby/blog.
See the README in the newly created plugin to get going.

View File

@@ -0,0 +1,246 @@
require 'active_support/core_ext/hash/slice'
require "rails/generators/rails/app/app_generator"
module Rails
class PluginBuilder
def rakefile
template "Rakefile"
end
def app
directory "app" if options[:mountable]
end
def readme
copy_file "README.rdoc"
end
def gemfile
template "Gemfile"
end
def license
template "MIT-LICENSE"
end
def gemspec
template "%name%.gemspec"
end
def gitignore
copy_file "gitignore", ".gitignore"
end
def lib
template "lib/%name%.rb"
template "lib/tasks/%name%_tasks.rake"
if full?
template "lib/%name%/engine.rb"
end
end
def config
template "config/routes.rb" if mountable?
end
def test
template "test/test_helper.rb"
template "test/%name%_test.rb"
append_file "Rakefile", <<-EOF
#{rakefile_test_tasks}
task :default => :test
EOF
if full?
template "test/integration/navigation_test.rb"
end
end
def generate_test_dummy(force = false)
opts = (options || {}).slice(:skip_active_record, :skip_javascript, :database, :javascript)
opts[:force] = force
invoke Rails::Generators::AppGenerator,
[ File.expand_path(dummy_path, destination_root) ], opts
end
def test_dummy_config
template "rails/boot.rb", "#{dummy_path}/config/boot.rb", :force => true
template "rails/application.rb", "#{dummy_path}/config/application.rb", :force => true
if mountable?
template "rails/routes.rb", "#{dummy_path}/config/routes.rb", :force => true
end
end
def test_dummy_clean
inside dummy_path do
remove_file ".gitignore"
remove_file "db/seeds.rb"
remove_file "doc"
remove_file "Gemfile"
remove_file "lib/tasks"
remove_file "public/images/rails.png"
remove_file "public/index.html"
remove_file "public/robots.txt"
remove_file "README"
remove_file "test"
remove_file "vendor"
end
end
def script(force = false)
directory "script", :force => force do |content|
"#{shebang}\n" + content
end
chmod "script", 0755, :verbose => false
end
end
module Generators
class PluginNewGenerator < AppBase
add_shared_options_for "plugin"
alias_method :plugin_path, :app_path
class_option :dummy_path, :type => :string, :default => "test/dummy",
:desc => "Create dummy application at given path"
class_option :full, :type => :boolean, :default => false,
:desc => "Generate rails engine with integration tests"
class_option :mountable, :type => :boolean, :default => false,
:desc => "Generate mountable isolated application"
def initialize(*args)
raise Error, "Options should be given after the plugin name. For details run: rails plugin --help" if args[0].blank?
super
end
public_task :create_root
def create_root_files
build(:readme)
build(:rakefile)
build(:gemspec)
build(:license)
build(:gitignore) unless options[:skip_git]
build(:gemfile) unless options[:skip_gemfile]
end
def create_app_files
build(:app)
end
def create_config_files
build(:config)
end
def create_lib_files
build(:lib)
end
def create_script_files
build(:script)
end
def create_test_files
build(:test) unless options[:skip_test_unit]
end
def create_test_dummy_files
return if options[:skip_test_unit]
create_dummy_app
end
def finish_template
build(:leftovers)
end
public_task :apply_rails_template, :bundle_if_dev_or_edge
protected
def create_dummy_app(path = nil)
dummy_path(path) if path
say_status :vendor_app, dummy_path
mute do
build(:generate_test_dummy)
store_application_definition!
build(:test_dummy_config)
build(:test_dummy_clean)
# ensure that script/rails has proper dummy_path
build(:script, true)
end
end
def full?
options[:full] || options[:mountable]
end
def mountable?
options[:mountable]
end
def self.banner
"rails plugin new #{self.arguments.map(&:usage).join(' ')} [options]"
end
def name
@name ||= File.basename(destination_root)
end
def camelized
@camelized ||= name.gsub(/\W/, '_').squeeze('_').camelize
end
def valid_const?
if camelized =~ /^\d/
raise Error, "Invalid plugin name #{name}. Please give a name which does not start with numbers."
elsif RESERVED_NAMES.include?(name)
raise Error, "Invalid plugin name #{name}. Please give a name which does not match one of the reserved rails words."
elsif Object.const_defined?(camelized)
raise Error, "Invalid plugin name #{name}, constant #{camelized} is already in use. Please choose another application name."
end
end
def application_definition
@application_definition ||= begin
dummy_application_path = File.expand_path("#{dummy_path}/config/application.rb", destination_root)
unless options[:pretend] || !File.exists?(dummy_application_path)
contents = File.read(dummy_application_path)
contents[(contents.index("module Dummy"))..-1]
end
end
end
alias :store_application_definition! :application_definition
def get_builder_class
defined?(::PluginBuilder) ? ::PluginBuilder : Rails::PluginBuilder
end
def rakefile_test_tasks
<<-RUBY
require 'rake/testtask'
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
t.verbose = false
end
RUBY
end
def dummy_path(path = nil)
@dummy_path = path if path
@dummy_path || options[:dummy_path]
end
def mute(&block)
shell.mute(&block)
end
end
end
end

View File

@@ -0,0 +1,9 @@
# Provide a simple gemspec so you can easily use your
# project in your rails apps through git.
Gem::Specification.new do |s|
s.name = "<%= name %>"
s.summary = "Insert <%= camelized %> summary."
s.description = "Insert <%= camelized %> description."
s.files = Dir["lib/**/*"] + ["MIT-LICENSE", "Rakefile", "README.rdoc"]
s.version = "0.0.1"
end

View File

@@ -0,0 +1,11 @@
source "http://rubygems.org"
<%= rails_gemfile_entry -%>
<% if full? -%>
<%= database_gemfile_entry -%>
<% end -%>
if RUBY_VERSION < '1.9'
gem "ruby-debug", ">= 0.10.3"
end

View File

@@ -0,0 +1,20 @@
Copyright <%= Date.today.year %> YOURNAME
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.

View File

@@ -0,0 +1,3 @@
= <%= camelized %>
This project rocks and uses MIT-LICENSE.

View File

@@ -0,0 +1,18 @@
# encoding: UTF-8
require 'rubygems'
begin
require 'bundler/setup'
rescue LoadError
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end
require 'rake'
require 'rake/rdoctask'
Rake::RDocTask.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = '<%= camelized %>'
rdoc.options << '--line-numbers' << '--inline-source'
rdoc.rdoc_files.include('README.rdoc')
rdoc.rdoc_files.include('lib/**/*.rb')
end

View File

@@ -0,0 +1,4 @@
module <%= camelized %>
class ApplicationController < ActiveController::Base
end
end

View File

@@ -0,0 +1,4 @@
module <%= camelized %>
module ApplicationHelper
end
end

View File

@@ -0,0 +1,3 @@
<%= camelized %>::Engine.routes.draw do
end

View File

@@ -0,0 +1,6 @@
.bundle/
log/*.log
pkg/
test/dummy/db/*.sqlite3
test/dummy/log/*.log
test/dummy/tmp/

View File

@@ -0,0 +1,6 @@
<% if full? -%>
require "<%= name %>/engine"
<% end -%>
module <%= camelized %>
end

View File

@@ -0,0 +1,7 @@
module <%= camelized %>
class Engine < Rails::Engine
<% if mountable? -%>
isolate_namespace <%= camelized %>
<% end -%>
end
end

View File

@@ -0,0 +1,4 @@
# desc "Explaining what the task does"
# task :<%= name %> do
# # Task goes here
# end

View File

@@ -0,0 +1,16 @@
require File.expand_path('../boot', __FILE__)
<% unless options[:skip_active_record] -%>
require 'rails/all'
<% else -%>
# require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "active_resource/railtie"
require "rails/test_unit/railtie"
<% end -%>
Bundler.require
require "<%= name %>"
<%= application_definition %>

View File

@@ -0,0 +1,10 @@
require 'rubygems'
gemfile = File.expand_path('../../../../Gemfile', __FILE__)
if File.exist?(gemfile)
ENV['BUNDLE_GEMFILE'] = gemfile
require 'bundler'
Bundler.setup
end
$:.unshift File.expand_path('../../../../lib', __FILE__)

View File

@@ -0,0 +1,4 @@
Rails.application.routes.draw do
mount <%= camelized %>::Engine => "/<%= name %>"
end

View File

@@ -0,0 +1,5 @@
#!/usr/bin/env ruby
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
ENGINE_PATH = File.expand_path('../..', __FILE__)
load File.expand_path('../../<%= dummy_path %>/script/rails', __FILE__)

View File

@@ -0,0 +1,7 @@
require 'test_helper'
class <%= camelized %>Test < ActiveSupport::TestCase
test "truth" do
assert_kind_of Module, <%= camelized %>
end
end

View File

@@ -0,0 +1,11 @@
require 'test_helper'
class NavigationTest < ActionDispatch::IntegrationTest
fixtures :all
# Replace this with your real tests.
test "the truth" do
assert true
end
end

View File

@@ -0,0 +1,17 @@
# Configure Rails Envinronment
ENV["RAILS_ENV"] = "test"
require File.expand_path("../dummy/config/environment.rb", __FILE__)
require "rails/test_help"
Rails.backtrace_cleaner.remove_silencers!
<% if full? && !options[:skip_active_record] -%>
# Run any available migration from application
ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__)
# and from engine
ActiveRecord::Migrator.migrate File.expand_path("../../db/migrate/", __FILE__)
<% end -%>
# Load support files
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }

View File

@@ -16,9 +16,9 @@ module Rails
def add_resource_route
return if options[:actions].present?
route_config = class_path.collect{|namespace| "namespace :#{namespace} do " }.join(" ")
route_config = regular_class_path.collect{|namespace| "namespace :#{namespace} do " }.join(" ")
route_config << "resources :#{file_name.pluralize}"
route_config << " end" * class_path.size
route_config << " end" * regular_class_path.size
route route_config
end
end

View File

@@ -1,3 +1,4 @@
<% module_namespacing do -%>
class <%= controller_class_name %>Controller < ApplicationController
# GET <%= route_url %>
# GET <%= route_url %>.xml
@@ -81,3 +82,4 @@ class <%= controller_class_name %>Controller < ApplicationController
end
end
end
<% end -%>

View File

@@ -34,7 +34,7 @@ module Rails
attr_reader :controller_name
def controller_class_path
@class_path
class_path
end
def controller_file_name
@@ -46,7 +46,7 @@ module Rails
end
def controller_class_name
@controller_class_name ||= (controller_class_path + [controller_file_name]).map!{ |m| m.camelize }.join('::')
(controller_class_path + [controller_file_name]).map!{ |m| m.camelize }.join('::')
end
def controller_i18n_scope

View File

@@ -1,5 +1,6 @@
require 'test_helper'
<% module_namespacing do -%>
class <%= controller_class_name %>ControllerTest < ActionController::TestCase
setup do
@<%= singular_table_name %> = <%= table_name %>(:one)
@@ -47,3 +48,4 @@ class <%= controller_class_name %>ControllerTest < ActionController::TestCase
assert_redirected_to <%= index_helper %>_path
end
end
<% end -%>

View File

@@ -0,0 +1,7 @@
class AppBuilder
def gitignore
create_file ".gitignore", <<-R.strip
foobar
R
end
end

View File

@@ -0,0 +1,7 @@
class AppBuilder < Rails::AppBuilder
def gitignore
create_file ".gitignore", <<-R.strip
foobar
R
end
end

View File

@@ -0,0 +1 @@
create_dummy_app("spec/dummy")

View File

@@ -0,0 +1,2 @@
class PluginBuilder
end

View File

@@ -0,0 +1,7 @@
class PluginBuilder
def gitignore
create_file ".gitignore", <<-R.strip
foobar
R
end
end

View File

@@ -0,0 +1,19 @@
class PluginBuilder < Rails::PluginBuilder
def test
create_file "spec/spec_helper.rb"
append_file "Rakefile", <<-EOF
# spec tasks in rakefile
task :default => :spec
EOF
end
def generate_test_dummy
dummy_path("spec/dummy")
super
end
def skip_test_unit?
true
end
end

View File

@@ -0,0 +1,7 @@
class PluginBuilder < Rails::PluginBuilder
def gitignore
create_file ".gitignore", <<-R.strip
foobar
R
end
end

View File

@@ -1,7 +0,0 @@
class AppBuilder
def configru
create_file "config.ru", <<-R.strip
run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] }
R
end
end

View File

@@ -1,7 +0,0 @@
class AppBuilder < Rails::AppBuilder
def configru
create_file "config.ru", <<-R.strip
run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] }
R
end
end

View File

@@ -1,6 +1,7 @@
require 'abstract_unit'
require 'generators/generators_test_helper'
require 'rails/generators/rails/app/app_generator'
require 'generators/shared_generator_tests.rb'
DEFAULT_APP_FILES = %w(
.gitignore
@@ -40,36 +41,10 @@ DEFAULT_APP_FILES = %w(
class AppGeneratorTest < Rails::Generators::TestCase
include GeneratorsTestHelper
arguments [destination_root]
include SharedGeneratorTests
def setup
Rails.application = TestApp::Application
super
Rails::Generators::AppGenerator.instance_variable_set('@desc', nil)
@bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle')
Kernel::silence_warnings do
Thor::Base.shell.send(:attr_accessor, :always_force)
@shell = Thor::Base.shell.new
@shell.send(:always_force=, true)
end
end
def teardown
super
Rails::Generators::AppGenerator.instance_variable_set('@desc', nil)
Rails.application = TestApp::Application.instance
end
def test_application_skeleton_is_created
run_generator
DEFAULT_APP_FILES.each{ |path| assert_file path }
end
def test_application_generate_pretend
run_generator ["testapp", "--pretend"]
DEFAULT_APP_FILES.each{ |path| assert_no_file path }
def default_files
::DEFAULT_APP_FILES
end
def test_application_controller_and_layout_files
@@ -78,36 +53,11 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_no_file "public/stylesheets/application.css"
end
def test_options_before_application_name_raises_an_error
content = capture(:stderr){ run_generator(["--skip-active-record", destination_root]) }
assert_equal "Options should be given after the application name. For details run: rails --help\n", content
end
def test_name_collision_raises_an_error
reserved_words = %w[application destroy plugin runner test]
reserved_words.each do |reserved|
content = capture(:stderr){ run_generator [File.join(destination_root, reserved)] }
assert_equal "Invalid application name #{reserved}. Please give a name which does not match one of the reserved rails words.\n", content
end
end
def test_invalid_database_option_raises_an_error
content = capture(:stderr){ run_generator([destination_root, "-d", "unknown"]) }
assert_match /Invalid value for \-\-database option/, content
end
def test_invalid_application_name_raises_an_error
content = capture(:stderr){ run_generator [File.join(destination_root, "43-things")] }
assert_equal "Invalid application name 43-things. Please give a name which does not start with numbers.\n", content
end
def test_application_name_raises_an_error_if_name_already_used_constant
%w{ String Hash Class Module Set Symbol }.each do |ruby_class|
content = capture(:stderr){ run_generator [File.join(destination_root, ruby_class)] }
assert_equal "Invalid application name #{ruby_class}, constant #{ruby_class} is already in use. Please choose another application name.\n", content
end
end
def test_invalid_application_name_is_fixed
run_generator [File.join(destination_root, "things-43")]
assert_file "things-43/config/environment.rb", /Things43::Application\.initialize!/
@@ -188,18 +138,6 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_file "test"
end
def test_test_unit_is_removed_from_frameworks_if_skip_test_unit_is_given
run_generator [destination_root, "--skip-test-unit"]
assert_file "config/application.rb" do |file|
assert_match /config.generators.test_framework = false/, file
end
end
def test_test_unit_is_skipped_if_required
run_generator [destination_root, "--skip-test-unit"]
assert_no_file "test"
end
def test_javascript_is_skipped_if_required
run_generator [destination_root, "--skip-javascript"]
assert_file "config/application.rb", /^\s+config\.action_view\.javascript_expansions\[:defaults\]\s+=\s+%w\(\)/
@@ -224,36 +162,11 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_file "public/javascripts/rails.js", /jQuery/
end
def test_shebang_is_added_to_rails_file
run_generator [destination_root, "--ruby", "foo/bar/baz"]
assert_file "script/rails", /#!foo\/bar\/baz/
end
def test_shebang_when_is_the_same_as_default_use_env
run_generator [destination_root, "--ruby", Thor::Util.ruby_command]
assert_file "script/rails", /#!\/usr\/bin\/env/
end
def test_template_from_dir_pwd
FileUtils.cd(Rails.root)
assert_match /It works from file!/, run_generator([destination_root, "-m", "lib/template.rb"])
end
def test_template_raises_an_error_with_invalid_path
content = capture(:stderr){ run_generator([destination_root, "-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([destination_root], :template => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template)
assert_match /It works!/, silence(:stdout){ generator.invoke_all }
end
def test_usage_read_from_file
File.expects(:read).returns("USAGE FROM FILE")
assert_equal "USAGE FROM FILE", Rails::Generators::AppGenerator.desc
@@ -273,19 +186,6 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_file 'lib/test_file.rb', 'heres test data'
end
def test_dev_option
generator([destination_root], :dev => true).expects(:run).with("#{@bundle_command} install")
silence(:stdout){ generator.invoke_all }
rails_path = File.expand_path('../../..', Rails.root)
assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:path\s+=>\s+["']#{Regexp.escape(rails_path)}["']$/
end
def test_edge_option
generator([destination_root], :edge => true).expects(:run).with("#{@bundle_command} install")
silence(:stdout){ generator.invoke_all }
assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:git\s+=>\s+["']#{Regexp.escape("git://github.com/rails/rails.git")}["']$/
end
protected
def action(*args, &block)
@@ -299,61 +199,20 @@ class CustomAppGeneratorTest < Rails::Generators::TestCase
tests Rails::Generators::AppGenerator
arguments [destination_root]
def setup
Rails.application = TestApp::Application
super
Rails::Generators::AppGenerator.instance_variable_set('@desc', nil)
@bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle')
end
def teardown
super
Rails::Generators::AppGenerator.instance_variable_set('@desc', nil)
Object.class_eval { remove_const :AppBuilder if const_defined?(:AppBuilder) }
Rails.application = TestApp::Application.instance
end
def test_builder_option_with_empty_app_builder
FileUtils.cd(Rails.root)
run_generator([destination_root, "-b", "#{Rails.root}/lib/empty_builder.rb"])
DEFAULT_APP_FILES.each{ |path| assert_no_file path }
end
def test_builder_option_with_simple_app_builder
FileUtils.cd(Rails.root)
run_generator([destination_root, "-b", "#{Rails.root}/lib/simple_builder.rb"])
(DEFAULT_APP_FILES - ['config.ru']).each{ |path| assert_no_file path }
assert_file "config.ru", %[run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] }]
end
def test_builder_option_with_relative_path
here = File.expand_path(File.dirname(__FILE__))
FileUtils.cd(here)
run_generator([destination_root, "-b", "../fixtures/lib/simple_builder.rb"])
(DEFAULT_APP_FILES - ['config.ru']).each{ |path| assert_no_file path }
assert_file "config.ru", %[run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] }]
end
def test_builder_option_with_tweak_app_builder
FileUtils.cd(Rails.root)
run_generator([destination_root, "-b", "#{Rails.root}/lib/tweak_builder.rb"])
DEFAULT_APP_FILES.each{ |path| assert_file path }
assert_file "config.ru", %[run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] }]
end
def test_builder_option_with_http
path = "http://gist.github.com/103208.txt"
template = "class AppBuilder; end"
template.instance_eval "def read; self; end" # Make the string respond to read
generator([destination_root], :builder => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template)
capture(:stdout) { generator.invoke_all }
DEFAULT_APP_FILES.each{ |path| assert_no_file path }
end
include SharedCustomGeneratorTests
protected
def default_files
::DEFAULT_APP_FILES
end
def builders_dir
"app_builders"
end
def builder_class
:AppBuilder
end
def action(*args, &block)
silence(:stdout){ generator.send(*args, &block) }

View File

@@ -3,6 +3,7 @@ require 'rails/generators/rails/controller/controller_generator'
require 'rails/generators/rails/model/model_generator'
require 'rails/generators/rails/observer/observer_generator'
require 'rails/generators/mailer/mailer_generator'
require 'rails/generators/rails/scaffold/scaffold_generator'
class NamespacedGeneratorTestCase < Rails::Generators::TestCase
def setup
@@ -202,3 +203,155 @@ class NamespacedMailerGeneratorTest < NamespacedGeneratorTestCase
assert_file "app/views/test_app/notifier"
end
end
class NamespacedScaffoldGeneratorTest < NamespacedGeneratorTestCase
include GeneratorsTestHelper
arguments %w(product_line title:string price:integer)
tests Rails::Generators::ScaffoldGenerator
setup :copy_routes
def test_scaffold_on_invoke
run_generator
# Model
assert_file "app/models/test_app/product_line.rb", /module TestApp\n class ProductLine < ActiveRecord::Base/
assert_file "test/unit/test_app/product_line_test.rb", /module TestApp\n class ProductLineTest < ActiveSupport::TestCase/
assert_file "test/fixtures/test_app/product_lines.yml"
assert_migration "db/migrate/create_test_app_product_lines.rb"
# Route
assert_file "config/routes.rb" do |route|
assert_match(/resources :product_lines$/, route)
end
# Controller
assert_file "app/controllers/test_app/product_lines_controller.rb" do |content|
assert_match(/module TestApp\n class ProductLinesController < ApplicationController/, content)
end
assert_file "test/functional/test_app/product_lines_controller_test.rb",
/module TestApp\n class ProductLinesControllerTest < ActionController::TestCase/
# Views
%w(
index
edit
new
show
_form
).each { |view| assert_file "app/views/test_app/product_lines/#{view}.html.erb" }
assert_no_file "app/views/layouts/test_app/product_lines.html.erb"
# Helpers
assert_file "app/helpers/test_app/product_lines_helper.rb"
assert_file "test/unit/helpers/test_app/product_lines_helper_test.rb"
# Stylesheets
assert_file "public/stylesheets/scaffold.css"
end
def test_scaffold_on_revoke
run_generator
run_generator ["product_line"], :behavior => :revoke
# Model
assert_no_file "app/models/test_app/product_line.rb"
assert_no_file "test/unit/test_app/product_line_test.rb"
assert_no_file "test/fixtures/test_app/product_lines.yml"
assert_no_migration "db/migrate/create_test_app_product_lines.rb"
# Route
assert_file "config/routes.rb" do |route|
assert_no_match(/resources :product_lines$/, route)
end
# Controller
assert_no_file "app/controllers/test_app/product_lines_controller.rb"
assert_no_file "test/functional/test_app/product_lines_controller_test.rb"
# Views
assert_no_file "app/views/test_app/product_lines"
assert_no_file "app/views/test_app/layouts/product_lines.html.erb"
# Helpers
assert_no_file "app/helpers/test_app/product_lines_helper.rb"
assert_no_file "test/unit/helpers/test_app/product_lines_helper_test.rb"
# Stylesheets (should not be removed)
assert_file "public/stylesheets/scaffold.css"
end
def test_scaffold_with_namespace_on_invoke
run_generator [ "admin/role", "name:string", "description:string" ]
# Model
assert_file "app/models/test_app/admin.rb", /module TestApp\n module Admin/
assert_file "app/models/test_app/admin/role.rb", /module TestApp\n class Admin::Role < ActiveRecord::Base/
assert_file "test/unit/test_app/admin/role_test.rb", /module TestApp\n class Admin::RoleTest < ActiveSupport::TestCase/
assert_file "test/fixtures/test_app/admin/roles.yml"
assert_migration "db/migrate/create_test_app_admin_roles.rb"
# Route
assert_file "config/routes.rb" do |route|
assert_match(/namespace :admin do resources :roles end$/, route)
end
# Controller
assert_file "app/controllers/test_app/admin/roles_controller.rb" do |content|
assert_match(/module TestApp\n class Admin::RolesController < ApplicationController/, content)
end
assert_file "test/functional/test_app/admin/roles_controller_test.rb",
/module TestApp\n class Admin::RolesControllerTest < ActionController::TestCase/
# Views
%w(
index
edit
new
show
_form
).each { |view| assert_file "app/views/test_app/admin/roles/#{view}.html.erb" }
assert_no_file "app/views/layouts/admin/roles.html.erb"
# Helpers
assert_file "app/helpers/test_app/admin/roles_helper.rb"
assert_file "test/unit/helpers/test_app/admin/roles_helper_test.rb"
# Stylesheets
assert_file "public/stylesheets/scaffold.css"
end
def test_scaffold_with_namespace_on_revoke
run_generator [ "admin/role", "name:string", "description:string" ]
run_generator [ "admin/role" ], :behavior => :revoke
# Model
assert_file "app/models/test_app/admin.rb" # ( should not be remove )
assert_no_file "app/models/test_app/admin/role.rb"
assert_no_file "test/unit/test_app/admin/role_test.rb"
assert_no_file "test/fixtures/test_app/admin/roles.yml"
assert_no_migration "db/migrate/create_test_app_admin_roles.rb"
# Route
assert_file "config/routes.rb" do |route|
assert_no_match(/namespace :admin do resources :roles end$/, route)
end
# Controller
assert_no_file "app/controllers/test_app/admin/roles_controller.rb"
assert_no_file "test/functional/test_app/admin/roles_controller_test.rb"
# Views
assert_no_file "app/views/test_app/admin/roles"
assert_no_file "app/views/layouts/test_app/admin/roles.html.erb"
# Helpers
assert_no_file "app/helpers/test_app/admin/roles_helper.rb"
assert_no_file "test/unit/helpers/test_app/admin/roles_helper_test.rb"
# Stylesheets (should not be removed)
assert_file "public/stylesheets/scaffold.css"
end
end

View File

@@ -0,0 +1,192 @@
require 'abstract_unit'
require 'generators/generators_test_helper'
require 'rails/generators/rails/plugin_new/plugin_new_generator'
require 'generators/shared_generator_tests.rb'
DEFAULT_PLUGIN_FILES = %w(
.gitignore
Gemfile
Rakefile
bukkits.gemspec
MIT-LICENSE
lib
lib/bukkits.rb
lib/tasks/bukkits_tasks.rake
script/rails
test/bukkits_test.rb
test/test_helper.rb
test/dummy
)
class PluginNewGeneratorTest < Rails::Generators::TestCase
include GeneratorsTestHelper
destination File.join(Rails.root, "tmp/bukkits")
arguments [destination_root]
include SharedGeneratorTests
def default_files
::DEFAULT_PLUGIN_FILES
end
def test_invalid_plugin_name_raises_an_error
content = capture(:stderr){ run_generator [File.join(destination_root, "43-things")] }
assert_equal "Invalid plugin name 43-things. Please give a name which does not start with numbers.\n", content
end
def test_invalid_plugin_name_is_fixed
run_generator [File.join(destination_root, "things-43")]
assert_file "things-43/lib/things-43.rb", /module Things43/
end
def test_generating_test_files
run_generator
assert_file "test/test_helper.rb"
assert_file "test/bukkits_test.rb", /assert_kind_of Module, Bukkits/
end
def test_generating_test_files_in_full_mode
run_generator [destination_root, "--full"]
assert_directory "test/integration/"
assert_file "test/integration/navigation_test.rb", /ActionDispatch::IntegrationTest/
end
def test_ensure_that_plugin_options_are_not_passed_to_app_generator
FileUtils.cd(Rails.root)
assert_no_match /It works from file!.*It works_from_file/, run_generator([destination_root, "-m", "lib/template.rb"])
end
def test_ensure_that_test_dummy_can_be_generated_from_a_template
FileUtils.cd(Rails.root)
run_generator([destination_root, "-m", "lib/create_test_dummy_template.rb", "--skip-test-unit"])
assert_file "spec/dummy"
assert_no_file "test"
end
def test_database_entry_is_assed_by_default_in_full_mode
run_generator([destination_root, "--full"])
assert_file "test/dummy/config/database.yml", /sqlite/
assert_file "Gemfile", /^gem\s+["']sqlite3-ruby["'],\s+:require\s+=>\s+["']sqlite3["']$/
end
def test_config_another_database
run_generator([destination_root, "-d", "mysql", "--full"])
assert_file "test/dummy/config/database.yml", /mysql/
assert_file "Gemfile", /^gem\s+["']mysql2["']$/
end
def test_active_record_is_removed_from_frameworks_if_skip_active_record_is_given
run_generator [destination_root, "--skip-active-record"]
assert_file "test/dummy/config/application.rb", /#\s+require\s+["']active_record\/railtie["']/
end
def test_ensure_that_skip_active_record_option_is_passed_to_app_generator
run_generator [destination_root, "--skip_active_record"]
assert_no_file "test/dummy/config/database.yml"
assert_no_match /ActiveRecord/, File.read(File.join(destination_root, "test/test_helper.rb"))
end
def test_ensure_that_database_option_is_passed_to_app_generator
run_generator [destination_root, "--database", "postgresql"]
assert_file "test/dummy/config/database.yml", /postgres/
end
def test_ensure_that_javascript_option_is_passed_to_app_generator
run_generator [destination_root, "--javascript", "jquery"]
assert_file "test/dummy/public/javascripts/jquery.js"
end
def test_ensure_that_skip_javascript_option_is_passed_to_app_generator
run_generator [destination_root, "--skip_javascript"]
assert_no_file "test/dummy/public/javascripts/prototype.js"
end
def test_template_from_dir_pwd
FileUtils.cd(Rails.root)
assert_match /It works from file!/, run_generator([destination_root, "-m", "lib/template.rb"])
end
def test_ensure_that_tests_works
run_generator
FileUtils.cd destination_root
`bundle install`
assert_match /1 tests, 1 assertions, 0 failures, 0 errors/, `bundle exec rake test`
end
def test_ensure_that_tests_works_in_full_mode
run_generator [destination_root, "--full"]
FileUtils.cd destination_root
`bundle install`
assert_match /2 tests, 2 assertions, 0 failures, 0 errors/, `bundle exec rake test`
end
def test_creating_engine_in_full_mode
run_generator [destination_root, "--full"]
assert_file "lib/bukkits/engine.rb", /module Bukkits\n class Engine < Rails::Engine\n end\nend/
assert_file "lib/bukkits.rb", /require "bukkits\/engine"/
end
def test_being_quiet_while_creating_dummy_application
assert_no_match /create\s+config\/application.rb/, run_generator
end
def test_create_mountable_application_with_mountable_option
run_generator [destination_root, "--mountable"]
assert_file "config/routes.rb", /Bukkits::Engine.routes.draw do/
assert_file "lib/bukkits/engine.rb", /isolate_namespace Bukkits/
assert_file "test/dummy/config/routes.rb", /mount Bukkits::Engine => "\/bukkits"/
assert_file "app/controllers/bukkits/application_controller.rb", /module Bukkits\n class ApplicationController < ActiveController::Base/
assert_file "app/helpers/bukkits/application_helper.rb", /module Bukkits\n module ApplicationHelper/
end
def test_passing_dummy_path_as_a_parameter
run_generator [destination_root, "--dummy_path", "spec/dummy"]
assert_file "spec/dummy"
assert_file "spec/dummy/config/application.rb"
assert_no_file "test/dummy"
end
protected
def action(*args, &block)
silence(:stdout){ generator.send(*args, &block) }
end
end
class CustomPluginGeneratorTest < Rails::Generators::TestCase
include GeneratorsTestHelper
tests Rails::Generators::PluginNewGenerator
destination File.join(Rails.root, "tmp/bukkits")
arguments [destination_root]
include SharedCustomGeneratorTests
def test_overriding_test_framework
FileUtils.cd(destination_root)
run_generator([destination_root, "-b", "#{Rails.root}/lib/plugin_builders/spec_builder.rb"])
assert_file 'spec/spec_helper.rb'
assert_file 'spec/dummy'
assert_file 'Rakefile', /task :default => :spec/
assert_file 'Rakefile', /# spec tasks in rakefile/
assert_file 'script/rails', %r{spec/dummy}
end
protected
def default_files
::DEFAULT_PLUGIN_FILES
end
def builder_class
:PluginBuilder
end
def builders_dir
"plugin_builders"
end
def action(*args, &block)
silence(:stdout){ generator.send(*args, &block) }
end
end

View File

@@ -0,0 +1,187 @@
module SharedGeneratorTests
def setup
Rails.application = TestApp::Application
super
Rails::Generators::AppGenerator.instance_variable_set('@desc', nil)
@bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle')
Kernel::silence_warnings do
Thor::Base.shell.send(:attr_accessor, :always_force)
@shell = Thor::Base.shell.new
@shell.send(:always_force=, true)
end
end
def teardown
super
Rails::Generators::AppGenerator.instance_variable_set('@desc', nil)
Rails.application = TestApp::Application.instance
end
def test_skeleton_is_created
run_generator
default_files.each{ |path| assert_file path }
end
def test_plugin_new_generate_pretend
run_generator ["testapp", "--pretend"]
default_files.each{ |path| assert_no_file path }
end
def test_invalid_database_option_raises_an_error
content = capture(:stderr){ run_generator([destination_root, "-d", "unknown"]) }
assert_match /Invalid value for \-\-database option/, content
end
def test_test_unit_is_skipped_if_required
run_generator [destination_root, "--skip-test-unit"]
assert_no_file "test"
end
def test_options_before_application_name_raises_an_error
content = capture(:stderr){ run_generator(["--pretend", destination_root]) }
assert_match /Options should be given after the \w+ name. For details run: rails( plugin)? --help\n/, content
end
def test_name_collision_raises_an_error
reserved_words = %w[application destroy plugin runner test]
reserved_words.each do |reserved|
content = capture(:stderr){ run_generator [File.join(destination_root, reserved)] }
assert_match /Invalid \w+ name #{reserved}. Please give a name which does not match one of the reserved rails words.\n/, content
end
end
def test_name_raises_an_error_if_name_already_used_constant
%w{ String Hash Class Module Set Symbol }.each do |ruby_class|
content = capture(:stderr){ run_generator [File.join(destination_root, ruby_class)] }
assert_match /Invalid \w+ name #{ruby_class}, constant #{ruby_class} is already in use. Please choose another \w+ name.\n/, content
end
end
def test_shebang_is_added_to_rails_file
run_generator [destination_root, "--ruby", "foo/bar/baz"]
assert_file "script/rails", /#!foo\/bar\/baz/
end
def test_shebang_when_is_the_same_as_default_use_env
run_generator [destination_root, "--ruby", Thor::Util.ruby_command]
assert_file "script/rails", /#!\/usr\/bin\/env/
end
def test_template_raises_an_error_with_invalid_path
content = capture(:stderr){ run_generator([destination_root, "-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([destination_root], :template => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template)
assert_match /It works!/, silence(:stdout){ generator.invoke_all }
end
def test_dev_option
generator([destination_root], :dev => true).expects(:run).with("#{@bundle_command} install")
silence(:stdout){ generator.invoke_all }
rails_path = File.expand_path('../../..', Rails.root)
assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:path\s+=>\s+["']#{Regexp.escape(rails_path)}["']$/
end
def test_edge_option
generator([destination_root], :edge => true).expects(:run).with("#{@bundle_command} install")
silence(:stdout){ generator.invoke_all }
assert_file 'Gemfile', %r{^gem\s+["']rails["'],\s+:git\s+=>\s+["']#{Regexp.escape("git://github.com/rails/rails.git")}["']$}
end
def test_template_raises_an_error_with_invalid_path
content = capture(:stderr){ run_generator([destination_root, "-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([destination_root], :template => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template)
assert_match /It works!/, silence(:stdout){ generator.invoke_all }
end
def test_dev_option
generator([destination_root], :dev => true).expects(:run).with("#{@bundle_command} install")
silence(:stdout){ generator.invoke_all }
rails_path = File.expand_path('../../..', Rails.root)
assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:path\s+=>\s+["']#{Regexp.escape(rails_path)}["']$/
end
def test_edge_option
generator([destination_root], :edge => true).expects(:run).with("#{@bundle_command} install")
silence(:stdout){ generator.invoke_all }
assert_file 'Gemfile', %r{^gem\s+["']rails["'],\s+:git\s+=>\s+["']#{Regexp.escape("git://github.com/rails/rails.git")}["']$}
end
end
module SharedCustomGeneratorTests
def setup
Rails.application = TestApp::Application
super
Rails::Generators::AppGenerator.instance_variable_set('@desc', nil)
@bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle')
end
def teardown
super
Rails::Generators::AppGenerator.instance_variable_set('@desc', nil)
Object.class_eval do
remove_const :AppBuilder if const_defined?(:AppBuilder)
remove_const :PluginBuilder if const_defined?(:PluginBuilder)
end
Rails.application = TestApp::Application.instance
end
def test_builder_option_with_empty_app_builder
FileUtils.cd(destination_root)
run_generator([destination_root, "-b", "#{Rails.root}/lib/#{builders_dir}/empty_builder.rb"])
default_files.each{ |path| assert_no_file path }
end
def test_builder_option_with_simple_plugin_builder
FileUtils.cd(destination_root)
run_generator([destination_root, "-b", "#{Rails.root}/lib/#{builders_dir}/simple_builder.rb"])
(default_files - ['.gitignore']).each{ |path| assert_no_file path }
assert_file ".gitignore", "foobar"
end
def test_builder_option_with_relative_path
here = File.expand_path(File.dirname(__FILE__))
FileUtils.cd(here)
run_generator([destination_root, "-b", "../fixtures/lib/#{builders_dir}/simple_builder.rb"])
FileUtils.cd(destination_root)
(default_files - ['.gitignore']).each{ |path| assert_no_file path }
assert_file ".gitignore", "foobar"
end
def test_builder_option_with_tweak_plugin_builder
FileUtils.cd(destination_root)
run_generator([destination_root, "-b", "#{Rails.root}/lib/#{builders_dir}/tweak_builder.rb"])
default_files.each{ |path| assert_file path }
assert_file ".gitignore", "foobar"
end
def test_builder_option_with_http
path = "http://gist.github.com/103208.txt"
template = "class #{builder_class}; end"
template.instance_eval "def read; self; end" # Make the string respond to read
generator([destination_root], :builder => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template)
capture(:stdout) { generator.invoke_all }
default_files.each{ |path| assert_no_file path }
end
end

View File

@@ -685,5 +685,25 @@ module RailtiesTest
assert_equal :haml , generators[:template_engine]
assert_equal :rspec , generators[:test_framework]
end
test "engine should get default generators with ability to overwrite them" do
@plugin.write "lib/bukkits.rb", <<-RUBY
module Bukkits
class Engine < ::Rails::Engine
config.generators.test_framework :rspec
end
end
RUBY
boot_rails
require "#{rails_root}/config/environment"
generators = Bukkits::Engine.config.generators.options[:rails]
assert_equal :active_record, generators[:orm]
assert_equal :rspec , generators[:test_framework]
app_generators = Rails.application.config.generators.options[:rails]
assert_equal :test_unit , app_generators[:test_framework]
end
end
end