railties 4.0.13 → 4.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +155 -385
  3. data/README.rdoc +1 -1
  4. data/bin/rails +1 -1
  5. data/lib/rails.rb +11 -13
  6. data/lib/rails/all.rb +1 -0
  7. data/lib/rails/api/task.rb +9 -12
  8. data/lib/rails/app_rails_loader.rb +2 -2
  9. data/lib/rails/application.rb +154 -149
  10. data/lib/rails/application/configuration.rb +1 -14
  11. data/lib/rails/application/default_middleware_stack.rb +99 -0
  12. data/lib/rails/application/finisher.rb +2 -0
  13. data/lib/rails/application_controller.rb +16 -0
  14. data/lib/rails/cli.rb +1 -2
  15. data/lib/rails/commands.rb +2 -94
  16. data/lib/rails/commands/application.rb +2 -28
  17. data/lib/rails/commands/commands_tasks.rb +174 -0
  18. data/lib/rails/commands/console.rb +2 -2
  19. data/lib/rails/commands/dbconsole.rb +1 -1
  20. data/lib/rails/commands/plugin.rb +23 -0
  21. data/lib/rails/commands/runner.rb +1 -1
  22. data/lib/rails/commands/server.rb +46 -30
  23. data/lib/rails/configuration.rb +4 -1
  24. data/lib/rails/console/helpers.rb +6 -0
  25. data/lib/rails/engine.rb +29 -18
  26. data/lib/rails/engine/commands.rb +1 -1
  27. data/lib/rails/engine/railties.rb +0 -8
  28. data/lib/rails/generators.rb +4 -3
  29. data/lib/rails/generators/actions.rb +1 -1
  30. data/lib/rails/generators/active_model.rb +0 -8
  31. data/lib/rails/generators/app_base.rb +213 -74
  32. data/lib/rails/generators/base.rb +17 -16
  33. data/lib/rails/generators/erb/scaffold/templates/_form.html.erb +1 -1
  34. data/lib/rails/generators/erb/scaffold/templates/index.html.erb +1 -3
  35. data/lib/rails/generators/migration.rb +18 -26
  36. data/lib/rails/generators/named_base.rb +4 -7
  37. data/lib/rails/generators/rails/app/app_generator.rb +91 -5
  38. data/lib/rails/generators/rails/app/templates/Gemfile +20 -15
  39. data/lib/rails/generators/rails/app/templates/Rakefile +1 -1
  40. data/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt +2 -0
  41. data/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css +5 -3
  42. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +5 -1
  43. data/lib/rails/generators/rails/app/templates/config/application.rb +2 -0
  44. data/lib/rails/generators/rails/app/templates/config/databases/frontbase.yml +7 -10
  45. data/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml +11 -31
  46. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml +25 -29
  47. data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml +8 -10
  48. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml +8 -11
  49. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml +6 -3
  50. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml +8 -22
  51. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml +7 -9
  52. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml +9 -12
  53. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml +8 -8
  54. data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml +7 -17
  55. data/lib/rails/generators/rails/app/templates/config/environment.rb +1 -1
  56. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +2 -5
  57. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +1 -1
  58. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +1 -4
  59. data/lib/rails/generators/rails/app/templates/config/initializers/session_store.rb.tt +1 -1
  60. data/lib/rails/generators/rails/app/templates/config/routes.rb +1 -1
  61. data/lib/rails/generators/rails/app/templates/config/{initializers/secret_token.rb.tt → secrets.yml} +10 -2
  62. data/lib/rails/generators/rails/app/templates/public/404.html +20 -11
  63. data/lib/rails/generators/rails/app/templates/public/422.html +20 -11
  64. data/lib/rails/generators/rails/app/templates/public/500.html +19 -10
  65. data/lib/rails/generators/rails/controller/USAGE +1 -0
  66. data/lib/rails/generators/rails/controller/controller_generator.rb +35 -1
  67. data/lib/rails/generators/rails/generator/USAGE +1 -0
  68. data/lib/rails/generators/rails/generator/generator_generator.rb +2 -0
  69. data/lib/rails/generators/rails/model/USAGE +5 -5
  70. data/lib/rails/generators/rails/{plugin_new → plugin}/USAGE +0 -0
  71. data/lib/rails/generators/rails/{plugin_new/plugin_new_generator.rb → plugin/plugin_generator.rb} +10 -4
  72. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/%name%.gemspec +1 -0
  73. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/Gemfile +16 -1
  74. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/MIT-LICENSE +0 -0
  75. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/README.rdoc +0 -0
  76. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/Rakefile +0 -0
  77. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/app/controllers/%name%/application_controller.rb.tt +0 -0
  78. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/app/helpers/%name%/application_helper.rb.tt +0 -0
  79. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/app/mailers/.empty_directory +0 -0
  80. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/app/models/.empty_directory +0 -0
  81. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/app/views/layouts/%name%/application.html.erb.tt +0 -0
  82. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/bin/rails.tt +0 -4
  83. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/config/routes.rb +0 -0
  84. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/gitignore +0 -0
  85. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/lib/%name%.rb +0 -0
  86. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/lib/%name%/engine.rb +0 -0
  87. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/lib/%name%/version.rb +0 -0
  88. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/lib/tasks/%name%_tasks.rake +0 -0
  89. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/rails/application.rb +1 -0
  90. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/rails/boot.rb +0 -0
  91. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/rails/javascripts.js +0 -0
  92. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/rails/routes.rb +0 -0
  93. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/rails/stylesheets.css +5 -3
  94. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/test/%name%_test.rb +0 -0
  95. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/test/integration/navigation_test.rb +0 -0
  96. data/lib/rails/generators/rails/{plugin_new → plugin}/templates/test/test_helper.rb +0 -0
  97. data/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb +1 -1
  98. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb +2 -2
  99. data/lib/rails/generators/resource_helpers.rb +20 -5
  100. data/lib/rails/generators/test_unit/generator/generator_generator.rb +26 -0
  101. data/lib/rails/generators/test_unit/generator/templates/generator_test.rb +16 -0
  102. data/lib/rails/generators/test_unit/mailer/mailer_generator.rb +8 -1
  103. data/lib/rails/generators/test_unit/mailer/templates/preview.rb +11 -0
  104. data/lib/rails/generators/testing/assertions.rb +1 -1
  105. data/lib/rails/generators/testing/behaviour.rb +3 -13
  106. data/lib/rails/info.rb +5 -3
  107. data/lib/rails/info_controller.rb +5 -15
  108. data/lib/rails/mailers_controller.rb +73 -0
  109. data/lib/rails/paths.rb +13 -18
  110. data/lib/rails/rack/debugger.rb +2 -2
  111. data/lib/rails/rack/logger.rb +1 -1
  112. data/lib/rails/railtie.rb +38 -2
  113. data/lib/rails/source_annotation_extractor.rb +2 -2
  114. data/lib/rails/tasks.rb +0 -2
  115. data/lib/rails/tasks/documentation.rake +0 -5
  116. data/lib/rails/tasks/engine.rake +1 -1
  117. data/lib/rails/tasks/framework.rake +2 -12
  118. data/lib/rails/templates/layouts/application.html.erb +2 -2
  119. data/lib/rails/templates/rails/mailers/email.html.erb +98 -0
  120. data/lib/rails/templates/rails/mailers/index.html.erb +8 -0
  121. data/lib/rails/templates/rails/mailers/mailer.html.erb +6 -0
  122. data/lib/rails/test_help.rb +4 -1
  123. data/lib/rails/test_unit/sub_test_task.rb +44 -3
  124. data/lib/rails/test_unit/testing.rake +9 -111
  125. data/lib/rails/version.rb +3 -3
  126. data/lib/rails/welcome_controller.rb +4 -3
  127. metadata +99 -76
  128. data/lib/rails/commands/plugin_new.rb +0 -9
  129. data/lib/rails/generators/actions/create_migration.rb +0 -68
@@ -94,8 +94,8 @@ module Rails
94
94
  require 'debugger'
95
95
  puts "=> Debugger enabled"
96
96
  rescue LoadError
97
- puts "You're missing the 'debugger' gem. Add it to your Gemfile, bundle, and try again."
98
- exit
97
+ puts "You're missing the 'debugger' gem. Add it to your Gemfile, bundle it and try again."
98
+ exit(1)
99
99
  end
100
100
  end
101
101
  end
@@ -44,7 +44,7 @@ module Rails
44
44
 
45
45
  find_cmd_and_exec(['mysql', 'mysql5'], *args)
46
46
 
47
- when "postgresql", "postgres"
47
+ when "postgresql", "postgres", "postgis"
48
48
  ENV['PGUSER'] = config["username"] if config["username"]
49
49
  ENV['PGHOST'] = config["host"] if config["host"]
50
50
  ENV['PGPORT'] = config["port"].to_s if config["port"]
@@ -0,0 +1,23 @@
1
+ if ARGV.first != "new"
2
+ ARGV[0] = "--help"
3
+ else
4
+ ARGV.shift
5
+ unless ARGV.delete("--no-rc")
6
+ customrc = ARGV.index{ |x| x.include?("--rc=") }
7
+ railsrc = if customrc
8
+ File.expand_path(ARGV.delete_at(customrc).gsub(/--rc=/, ""))
9
+ else
10
+ File.join(File.expand_path("~"), '.railsrc')
11
+ end
12
+ if File.exist?(railsrc)
13
+ extra_args_string = File.read(railsrc)
14
+ extra_args = extra_args_string.split(/\n+/).map {|l| l.split}.flatten
15
+ puts "Using #{extra_args.join(" ")} from #{railsrc}"
16
+ ARGV.insert(1, *extra_args)
17
+ end
18
+ end
19
+ end
20
+
21
+ require 'rails/generators'
22
+ require 'rails/generators/rails/plugin/plugin_generator'
23
+ Rails::Generators::PluginGenerator.start
@@ -48,7 +48,7 @@ if code_or_file.nil?
48
48
  exit 1
49
49
  elsif File.exist?(code_or_file)
50
50
  $0 = code_or_file
51
- eval(File.read(code_or_file), nil, code_or_file)
51
+ Kernel.load code_or_file
52
52
  else
53
53
  eval(code_or_file, binding, __FILE__, __LINE__)
54
54
  end
@@ -1,6 +1,7 @@
1
1
  require 'fileutils'
2
2
  require 'optparse'
3
3
  require 'action_dispatch'
4
+ require 'rails'
4
5
 
5
6
  module Rails
6
7
  class Server < ::Rack::Server
@@ -21,7 +22,7 @@ module Rails
21
22
  opts.on("-e", "--environment=name", String,
22
23
  "Specifies the environment to run this server under (test/development/production).",
23
24
  "Default: development") { |v| options[:environment] = v }
24
- opts.on("-P","--pid=pid",String,
25
+ opts.on("-P", "--pid=pid", String,
25
26
  "Specifies the PID file.",
26
27
  "Default: tmp/pids/server.pid") { |v| options[:pid] = v }
27
28
 
@@ -32,7 +33,8 @@ module Rails
32
33
 
33
34
  opt_parser.parse! args
34
35
 
35
- options[:server] = args.shift
36
+ options[:log_stdout] = options[:daemonize].blank? && (options[:environment] || Rails.env) == "development"
37
+ options[:server] = args.shift
36
38
  options
37
39
  end
38
40
  end
@@ -59,27 +61,10 @@ module Rails
59
61
  end
60
62
 
61
63
  def start
62
- url = "#{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}"
63
- puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
64
- puts "=> Rails #{Rails.version} application starting in #{Rails.env} on #{url}"
65
- puts "=> Run `rails server -h` for more startup options"
64
+ print_boot_information
66
65
  trap(:INT) { exit }
67
- puts "=> Ctrl-C to shutdown server" unless options[:daemonize]
68
-
69
- #Create required tmp directories if not found
70
- %w(cache pids sessions sockets).each do |dir_to_make|
71
- FileUtils.mkdir_p(File.join(Rails.root, 'tmp', dir_to_make))
72
- end
73
-
74
- unless options[:daemonize]
75
- wrapped_app # touch the app so the logger is set up
76
-
77
- console = ActiveSupport::Logger.new($stdout)
78
- console.formatter = Rails.logger.formatter
79
- console.level = Rails.logger.level
80
-
81
- Rails.logger.extend(ActiveSupport::Logger.broadcast(console))
82
- end
66
+ create_tmp_directories
67
+ log_to_stdout if options[:log_stdout]
83
68
 
84
69
  super
85
70
  ensure
@@ -90,7 +75,7 @@ module Rails
90
75
 
91
76
  def middleware
92
77
  middlewares = []
93
- middlewares << [Rails::Rack::Debugger] if options[:debugger]
78
+ middlewares << [Rails::Rack::Debugger] if options[:debugger]
94
79
  middlewares << [::Rack::ContentLength]
95
80
 
96
81
  # FIXME: add Rack::Lock in the case people are using webrick.
@@ -110,14 +95,45 @@ module Rails
110
95
 
111
96
  def default_options
112
97
  super.merge({
113
- Port: 3000,
114
- DoNotReverseLookup: true,
115
- environment: (ENV['RAILS_ENV'] || ENV['RACK_ENV'] || "development").dup,
116
- daemonize: false,
117
- debugger: false,
118
- pid: File.expand_path("tmp/pids/server.pid"),
119
- config: File.expand_path("config.ru")
98
+ Port: 3000,
99
+ DoNotReverseLookup: true,
100
+ environment: (ENV['RAILS_ENV'] || ENV['RACK_ENV'] || "development").dup,
101
+ daemonize: false,
102
+ debugger: false,
103
+ pid: File.expand_path("tmp/pids/server.pid"),
104
+ config: File.expand_path("config.ru")
120
105
  })
121
106
  end
107
+
108
+ private
109
+
110
+ def print_boot_information
111
+ url = "#{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}"
112
+ puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
113
+ puts "=> Rails #{Rails.version} application starting in #{Rails.env} on #{url}"
114
+ puts "=> Run `rails server -h` for more startup options"
115
+
116
+ if options[:Host].to_s.match(/0\.0\.0\.0/)
117
+ puts "=> Notice: server is listening on all interfaces (#{options[:Host]}). Consider using 127.0.0.1 (--binding option)"
118
+ end
119
+
120
+ puts "=> Ctrl-C to shutdown server" unless options[:daemonize]
121
+ end
122
+
123
+ def create_tmp_directories
124
+ %w(cache pids sessions sockets).each do |dir_to_make|
125
+ FileUtils.mkdir_p(File.join(Rails.root, 'tmp', dir_to_make))
126
+ end
127
+ end
128
+
129
+ def log_to_stdout
130
+ wrapped_app # touch the app so the logger is set up
131
+
132
+ console = ActiveSupport::Logger.new($stdout)
133
+ console.formatter = Rails.logger.formatter
134
+ console.level = Rails.logger.level
135
+
136
+ Rails.logger.extend(ActiveSupport::Logger.broadcast(console))
137
+ end
122
138
  end
123
139
  end
@@ -1,4 +1,3 @@
1
- require 'active_support/deprecation'
2
1
  require 'active_support/ordered_options'
3
2
  require 'active_support/core_ext/object'
4
3
  require 'rails/paths'
@@ -60,6 +59,10 @@ module Rails
60
59
  @operations << [__method__, args, block]
61
60
  end
62
61
 
62
+ def unshift(*args, &block)
63
+ @operations << [__method__, args, block]
64
+ end
65
+
63
66
  def merge_into(other) #:nodoc:
64
67
  @operations.each do |operation, args, block|
65
68
  other.send(operation, *args, &block)
@@ -1,9 +1,15 @@
1
1
  module Rails
2
2
  module ConsoleMethods
3
+ # Gets the helper methods available to the controller.
4
+ #
5
+ # This method assumes an +ApplicationController+ exists, and it extends +ActionController::Base+
3
6
  def helper
4
7
  @helper ||= ApplicationController.helpers
5
8
  end
6
9
 
10
+ # Gets a new instance of a controller object.
11
+ #
12
+ # This method assumes an +ApplicationController+ exists, and it extends +ActionController::Base+
7
13
  def controller
8
14
  @controller ||= ApplicationController.new
9
15
  end
@@ -124,7 +124,7 @@ module Rails
124
124
  #
125
125
  # Now you can mount your engine in application's routes just like that:
126
126
  #
127
- # MyRailsApp::Application.routes.draw do
127
+ # Rails.application.routes.draw do
128
128
  # mount MyEngine::Engine => "/engine"
129
129
  # end
130
130
  #
@@ -154,7 +154,7 @@ module Rails
154
154
  # Note that now there can be more than one router in your application, and it's better to avoid
155
155
  # passing requests through many routers. Consider this situation:
156
156
  #
157
- # MyRailsApp::Application.routes.draw do
157
+ # Rails.application.routes.draw do
158
158
  # mount MyEngine::Engine => "/blog"
159
159
  # get "/blog/omg" => "main#omg"
160
160
  # end
@@ -164,7 +164,7 @@ module Rails
164
164
  # and if there is no such route in +Engine+'s routes, it will be dispatched to <tt>main#omg</tt>.
165
165
  # It's much better to swap that:
166
166
  #
167
- # MyRailsApp::Application.routes.draw do
167
+ # Rails.application.routes.draw do
168
168
  # get "/blog/omg" => "main#omg"
169
169
  # mount MyEngine::Engine => "/blog"
170
170
  # end
@@ -251,7 +251,7 @@ module Rails
251
251
  # created to allow you to do that. Consider such a scenario:
252
252
  #
253
253
  # # config/routes.rb
254
- # MyApplication::Application.routes.draw do
254
+ # Rails.application.routes.draw do
255
255
  # mount MyEngine::Engine => "/my_engine", as: "my_engine"
256
256
  # get "/foo" => "foo#index"
257
257
  # end
@@ -260,7 +260,7 @@ module Rails
260
260
  #
261
261
  # class FooController < ApplicationController
262
262
  # def index
263
- # my_engine.root_url #=> /my_engine/
263
+ # my_engine.root_url # => /my_engine/
264
264
  # end
265
265
  # end
266
266
  #
@@ -269,7 +269,7 @@ module Rails
269
269
  # module MyEngine
270
270
  # class BarController
271
271
  # def index
272
- # main_app.foo_path #=> /foo
272
+ # main_app.foo_path # => /foo
273
273
  # end
274
274
  # end
275
275
  # end
@@ -351,8 +351,13 @@ module Rails
351
351
  Rails::Railtie::Configuration.eager_load_namespaces << base
352
352
 
353
353
  base.called_from = begin
354
- # Remove the line number from backtraces making sure we don't leave anything behind
355
- call_stack = caller.map { |p| p.sub(/:\d+.*/, '') }
354
+ call_stack = if Kernel.respond_to?(:caller_locations)
355
+ caller_locations.map(&:path)
356
+ else
357
+ # Remove the line number from backtraces making sure we don't leave anything behind
358
+ caller.map { |p| p.sub(/:\d+.*/, '') }
359
+ end
360
+
356
361
  File.dirname(call_stack.detect { |p| p !~ %r[railties[\w.-]*/lib/rails|rack[\w.-]*/lib/rack] })
357
362
  end
358
363
  end
@@ -447,7 +452,7 @@ module Rails
447
452
  self
448
453
  end
449
454
 
450
- # Load rails generators and invoke the registered hooks.
455
+ # Load Rails generators and invoke the registered hooks.
451
456
  # Check <tt>Rails::Railtie.generators</tt> for more info.
452
457
  def load_generators(app=self)
453
458
  require "rails/generators"
@@ -460,7 +465,7 @@ module Rails
460
465
  # files inside eager_load paths.
461
466
  def eager_load!
462
467
  config.eager_load_paths.each do |load_path|
463
- matcher = /\A#{Regexp.escape(load_path)}\/(.*)\.rb\Z/
468
+ matcher = /\A#{Regexp.escape(load_path.to_s)}\/(.*)\.rb\Z/
464
469
  Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
465
470
  require_dependency file.sub(matcher, '\1')
466
471
  end
@@ -564,10 +569,10 @@ module Rails
564
569
  end
565
570
 
566
571
  initializer :add_routing_paths do |app|
567
- routing_paths = self.paths["config/routes.rb"].existent
572
+ paths = self.paths["config/routes.rb"].existent
568
573
 
569
- if routes? || routing_paths.any?
570
- app.routes_reloader.paths.unshift(*routing_paths)
574
+ if routes? || paths.any?
575
+ app.routes_reloader.paths.unshift(*paths)
571
576
  app.routes_reloader.route_sets << routes
572
577
  end
573
578
  end
@@ -606,7 +611,7 @@ module Rails
606
611
 
607
612
  initializer :load_config_initializers do
608
613
  config.paths["config/initializers"].existent.sort.each do |initializer|
609
- load(initializer)
614
+ load_config_initializer(initializer)
610
615
  end
611
616
  end
612
617
 
@@ -634,17 +639,23 @@ module Rails
634
639
  end
635
640
  end
636
641
 
642
+ def routes? #:nodoc:
643
+ @routes
644
+ end
645
+
637
646
  protected
638
647
 
648
+ def load_config_initializer(initializer)
649
+ ActiveSupport::Notifications.instrument('load_config_initializer.railties', initializer: initializer) do
650
+ load(initializer)
651
+ end
652
+ end
653
+
639
654
  def run_tasks_blocks(*) #:nodoc:
640
655
  super
641
656
  paths["lib/tasks"].existent.sort.each { |ext| load(ext) }
642
657
  end
643
658
 
644
- def routes? #:nodoc:
645
- @routes
646
- end
647
-
648
659
  def has_migrations? #:nodoc:
649
660
  paths["db/migrate"].existent.any?
650
661
  end
@@ -27,7 +27,7 @@ else
27
27
  puts <<-EOT
28
28
  Usage: rails COMMAND [ARGS]
29
29
 
30
- The common rails commands available for engines are:
30
+ The common Rails commands available for engines are:
31
31
  generate Generate new code (short-cut alias: "g")
32
32
  destroy Undo code generated with "generate" (short-cut alias: "d")
33
33
 
@@ -9,10 +9,6 @@ module Rails
9
9
  ::Rails::Engine.subclasses.map(&:instance)
10
10
  end
11
11
 
12
- def self.engines
13
- @engines ||= ::Rails::Engine.subclasses.map(&:instance)
14
- end
15
-
16
12
  def each(*args, &block)
17
13
  _all.each(*args, &block)
18
14
  end
@@ -20,10 +16,6 @@ module Rails
20
16
  def -(others)
21
17
  _all - others
22
18
  end
23
-
24
- delegate :engines, to: "self.class"
25
19
  end
26
20
  end
27
21
  end
28
-
29
- ActiveSupport::Deprecation.deprecate_methods(Rails::Engine::Railties, :engines)
@@ -1,6 +1,8 @@
1
1
  activesupport_path = File.expand_path('../../../../activesupport/lib', __FILE__)
2
2
  $:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path)
3
3
 
4
+ require 'thor/group'
5
+
4
6
  require 'active_support'
5
7
  require 'active_support/core_ext/object/blank'
6
8
  require 'active_support/core_ext/kernel/singleton_class'
@@ -9,12 +11,11 @@ require 'active_support/core_ext/hash/deep_merge'
9
11
  require 'active_support/core_ext/module/attribute_accessors'
10
12
  require 'active_support/core_ext/string/inflections'
11
13
 
12
- require 'rails/generators/base'
13
-
14
14
  module Rails
15
15
  module Generators
16
16
  autoload :Actions, 'rails/generators/actions'
17
17
  autoload :ActiveModel, 'rails/generators/active_model'
18
+ autoload :Base, 'rails/generators/base'
18
19
  autoload :Migration, 'rails/generators/migration'
19
20
  autoload :NamedBase, 'rails/generators/named_base'
20
21
  autoload :ResourceHelpers, 'rails/generators/resource_helpers'
@@ -225,7 +226,7 @@ module Rails
225
226
  rails = groups.delete("rails")
226
227
  rails.map! { |n| n.sub(/^rails:/, '') }
227
228
  rails.delete("app")
228
- rails.delete("plugin_new")
229
+ rails.delete("plugin")
229
230
  print_list("rails", rails)
230
231
 
231
232
  hidden_namespaces.each { |n| groups.delete(n.to_s) }
@@ -86,7 +86,7 @@ module Rails
86
86
  # end
87
87
  def environment(data=nil, options={}, &block)
88
88
  sentinel = /class [a-z_:]+ < Rails::Application/i
89
- env_file_sentinel = /::Application\.configure do/
89
+ env_file_sentinel = /Rails\.application\.configure do/
90
90
  data = block.call if !data && block_given?
91
91
 
92
92
  in_root do
@@ -1,5 +1,3 @@
1
- require 'active_support/deprecation'
2
-
3
1
  module Rails
4
2
  module Generators
5
3
  # ActiveModel is a class to be implemented by each ORM to allow Rails to
@@ -65,12 +63,6 @@ module Rails
65
63
  "#{name}.update(#{params})"
66
64
  end
67
65
 
68
- def update_attributes(*args) # :nodoc:
69
- ActiveSupport::Deprecation.warn("Calling '@orm_instance.update_attributes' " \
70
- "is deprecated, please use '@orm_instance.update' instead.")
71
- update(*args)
72
- end
73
-
74
66
  # POST create
75
67
  # PATCH/PUT update
76
68
  def errors
@@ -1,10 +1,10 @@
1
1
  require 'digest/md5'
2
- require 'securerandom'
3
2
  require 'active_support/core_ext/string/strip'
4
3
  require 'rails/version' unless defined?(Rails::VERSION)
5
- require 'rbconfig'
6
4
  require 'open-uri'
7
5
  require 'uri'
6
+ require 'rails/generators'
7
+ require 'active_support/core_ext/array/extract_options'
8
8
 
9
9
  module Rails
10
10
  module Generators
@@ -18,6 +18,10 @@ module Rails
18
18
 
19
19
  argument :app_path, type: :string
20
20
 
21
+ def self.strict_args_position
22
+ false
23
+ end
24
+
21
25
  def self.add_shared_options_for(name)
22
26
  class_option :template, type: :string, aliases: '-m',
23
27
  desc: "Path to some #{name} template (can be a filesystem path or URL)"
@@ -37,9 +41,15 @@ module Rails
37
41
  class_option :skip_active_record, type: :boolean, aliases: '-O', default: false,
38
42
  desc: 'Skip Active Record files'
39
43
 
44
+ class_option :skip_action_view, type: :boolean, aliases: '-V', default: false,
45
+ desc: 'Skip Action View files'
46
+
40
47
  class_option :skip_sprockets, type: :boolean, aliases: '-S', default: false,
41
48
  desc: 'Skip Sprockets files'
42
49
 
50
+ class_option :skip_spring, type: :boolean, default: false,
51
+ desc: "Don't install Spring application preloader"
52
+
43
53
  class_option :database, type: :string, aliases: '-d', default: 'sqlite3',
44
54
  desc: "Preconfigure for selected database (options: #{DATABASES.join('/')})"
45
55
 
@@ -69,13 +79,49 @@ module Rails
69
79
  end
70
80
 
71
81
  def initialize(*args)
72
- @original_wd = Dir.pwd
82
+ @original_wd = Dir.pwd
83
+ @gem_filter = lambda { |gem| true }
84
+ @extra_entries = []
73
85
  super
74
86
  convert_database_option_for_jruby
75
87
  end
76
88
 
77
89
  protected
78
90
 
91
+ def gemfile_entry(name, *args)
92
+ options = args.extract_options!
93
+ version = args.first
94
+ github = options[:github]
95
+ path = options[:path]
96
+
97
+ if github
98
+ @extra_entries << GemfileEntry.github(name, github)
99
+ elsif path
100
+ @extra_entries << GemfileEntry.path(name, path)
101
+ else
102
+ @extra_entries << GemfileEntry.version(name, version)
103
+ end
104
+ self
105
+ end
106
+
107
+ def gemfile_entries
108
+ [ rails_gemfile_entry,
109
+ database_gemfile_entry,
110
+ assets_gemfile_entry,
111
+ javascript_gemfile_entry,
112
+ jbuilder_gemfile_entry,
113
+ sdoc_gemfile_entry,
114
+ platform_dependent_gemfile_entry,
115
+ spring_gemfile_entry,
116
+ @extra_entries].flatten.find_all(&@gem_filter)
117
+ end
118
+
119
+ def add_gem_entry_filter
120
+ @gem_filter = lambda { |next_filter, entry|
121
+ yield(entry) && next_filter.call(entry)
122
+ }.curry[@gem_filter]
123
+ end
124
+
79
125
  def builder
80
126
  @builder ||= begin
81
127
  builder_class = get_builder_class
@@ -89,21 +135,81 @@ module Rails
89
135
  end
90
136
 
91
137
  def create_root
92
- self.destination_root = File.expand_path(app_path, destination_root)
93
138
  valid_const?
94
139
 
95
140
  empty_directory '.'
96
- set_default_accessors!
97
141
  FileUtils.cd(destination_root) unless options[:pretend]
98
142
  end
99
143
 
144
+ class TemplateRecorder < ::BasicObject # :nodoc:
145
+ attr_reader :gems
146
+
147
+ def initialize(target)
148
+ @target = target
149
+ # unfortunately, instance eval has access to these ivars
150
+ @app_const = target.send :app_const if target.respond_to?(:app_const, true)
151
+ @app_const_base = target.send :app_const_base if target.respond_to?(:app_const_base, true)
152
+ @app_name = target.send :app_name if target.respond_to?(:app_name, true)
153
+ @commands = []
154
+ @gems = []
155
+ end
156
+
157
+ def gemfile_entry(*args)
158
+ @target.send :gemfile_entry, *args
159
+ end
160
+
161
+ def add_gem_entry_filter(*args, &block)
162
+ @target.send :add_gem_entry_filter, *args, &block
163
+ end
164
+
165
+ def method_missing(name, *args, &block)
166
+ @commands << [name, args, block]
167
+ end
168
+
169
+ def respond_to_missing?(method, priv = false)
170
+ super || @target.respond_to?(method, priv)
171
+ end
172
+
173
+ def replay!
174
+ @commands.each do |name, args, block|
175
+ @target.send name, *args, &block
176
+ end
177
+ end
178
+ end
179
+
100
180
  def apply_rails_template
101
- apply rails_template if rails_template
181
+ @recorder = TemplateRecorder.new self
182
+
183
+ apply(rails_template, target: @recorder) if rails_template
102
184
  rescue Thor::Error, LoadError, Errno::ENOENT => e
103
185
  raise Error, "The template [#{rails_template}] could not be loaded. Error: #{e}"
104
186
  end
105
187
 
188
+ def replay_template
189
+ @recorder.replay! if @recorder
190
+ end
191
+
192
+ def apply(path, config={})
193
+ verbose = config.fetch(:verbose, true)
194
+ target = config.fetch(:target, self)
195
+ is_uri = path =~ /^https?\:\/\//
196
+ path = find_in_source_paths(path) unless is_uri
197
+
198
+ say_status :apply, path, verbose
199
+ shell.padding += 1 if verbose
200
+
201
+ if is_uri
202
+ contents = open(path, "Accept" => "application/x-thor-template") {|io| io.read }
203
+ else
204
+ contents = open(path) {|io| io.read }
205
+ end
206
+
207
+ target.instance_eval(contents, path)
208
+ shell.padding -= 1 if verbose
209
+ end
210
+
106
211
  def set_default_accessors!
212
+ self.destination_root = File.expand_path(app_path, destination_root)
107
213
  self.rails_template = case options[:template]
108
214
  when /^https?:\/\//
109
215
  options[:template]
@@ -115,37 +221,52 @@ module Rails
115
221
  end
116
222
 
117
223
  def database_gemfile_entry
118
- options[:skip_active_record] ? "" :
119
- <<-GEMFILE.strip_heredoc
120
- # Use #{options[:database]} as the database for Active Record
121
- gem '#{gem_for_database}'
122
- GEMFILE
224
+ return [] if options[:skip_active_record]
225
+ GemfileEntry.version gem_for_database, nil,
226
+ "Use #{options[:database]} as the database for Active Record"
123
227
  end
124
228
 
125
229
  def include_all_railties?
126
- !options[:skip_active_record] && !options[:skip_test_unit] && !options[:skip_sprockets]
230
+ !options[:skip_active_record] && !options[:skip_action_view] && !options[:skip_test_unit] && !options[:skip_sprockets]
127
231
  end
128
232
 
129
233
  def comment_if(value)
130
234
  options[value] ? '# ' : ''
131
235
  end
132
236
 
237
+ class GemfileEntry < Struct.new(:name, :version, :comment, :options, :commented_out)
238
+ def initialize(name, version, comment, options = {}, commented_out = false)
239
+ super
240
+ end
241
+
242
+ def self.github(name, github, comment = nil)
243
+ new(name, nil, comment, github: github)
244
+ end
245
+
246
+ def self.version(name, version, comment = nil)
247
+ new(name, version, comment)
248
+ end
249
+
250
+ def self.path(name, path, comment = nil)
251
+ new(name, nil, comment, path: path)
252
+ end
253
+
254
+ def padding(max_width)
255
+ ' ' * (max_width - name.length + 2)
256
+ end
257
+ end
258
+
133
259
  def rails_gemfile_entry
134
260
  if options.dev?
135
- <<-GEMFILE.strip_heredoc
136
- gem 'rails', path: '#{Rails::Generators::RAILS_DEV_PATH}'
137
- gem 'arel', github: 'rails/arel', branch: '4-0-stable'
138
- GEMFILE
261
+ [GemfileEntry.path('rails', Rails::Generators::RAILS_DEV_PATH),
262
+ GemfileEntry.github('arel', 'rails/arel')]
139
263
  elsif options.edge?
140
- <<-GEMFILE.strip_heredoc
141
- gem 'rails', github: 'rails/rails', branch: '4-0-stable'
142
- gem 'arel', github: 'rails/arel', branch: '4-0-stable'
143
- GEMFILE
264
+ [GemfileEntry.github('rails', 'rails/rails'),
265
+ GemfileEntry.github('arel', 'rails/arel')]
144
266
  else
145
- <<-GEMFILE.strip_heredoc
146
- # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
147
- gem 'rails', '#{Rails::VERSION::STRING}'
148
- GEMFILE
267
+ [GemfileEntry.version('rails',
268
+ Rails::VERSION::STRING,
269
+ "Bundle edge Rails instead: gem 'rails', github: 'rails/rails'")]
149
270
  end
150
271
  end
151
272
 
@@ -177,77 +298,81 @@ module Rails
177
298
  end
178
299
 
179
300
  def assets_gemfile_entry
180
- return if options[:skip_sprockets]
301
+ return [] if options[:skip_sprockets]
181
302
 
182
- gemfile = if options.dev? || options.edge?
183
- <<-GEMFILE.strip_heredoc
184
- # Use latest 2.1 version of sprockets-rails
185
- gem 'sprockets-rails', github: 'rails/sprockets-rails', branch: "2-1-stable"
303
+ gems = []
304
+ if options.dev? || options.edge?
305
+ gems << GemfileEntry.github('sprockets-rails', 'rails/sprockets-rails',
306
+ 'Use edge version of sprockets-rails')
307
+ gems << GemfileEntry.github('sass-rails', 'rails/sass-rails',
308
+ 'Use SCSS for stylesheets')
309
+ else
310
+ gems << GemfileEntry.version('sass-rails',
311
+ '~> 4.0.0.rc1',
312
+ 'Use SCSS for stylesheets')
313
+ end
186
314
 
187
- # Use SCSS for stylesheets
188
- gem 'sass-rails', github: 'rails/sass-rails'
315
+ gems << GemfileEntry.version('uglifier',
316
+ '>= 1.3.0',
317
+ 'Use Uglifier as compressor for JavaScript assets')
189
318
 
190
- # Use Uglifier as compressor for JavaScript assets
191
- gem 'uglifier', '>= 1.3.0'
192
- GEMFILE
193
- else
194
- <<-GEMFILE.strip_heredoc
195
- # Use SCSS for stylesheets
196
- gem 'sass-rails', '~> 4.0.2'
319
+ gems
320
+ end
197
321
 
198
- # Use Uglifier as compressor for JavaScript assets
199
- gem 'uglifier', '>= 1.3.0'
200
- GEMFILE
322
+ def platform_dependent_gemfile_entry
323
+ gems = []
324
+ if RUBY_ENGINE == 'rbx'
325
+ gems << GemfileEntry.version('rubysl', nil)
201
326
  end
327
+ gems
328
+ end
202
329
 
203
- if options[:skip_javascript]
204
- gemfile += <<-GEMFILE
205
- #{coffee_gemfile_entry}
206
- #{javascript_runtime_gemfile_entry}
207
- GEMFILE
208
- end
330
+ def jbuilder_gemfile_entry
331
+ comment = 'Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder'
332
+ GemfileEntry.version('jbuilder', '~> 1.2', comment)
333
+ end
209
334
 
210
- gemfile.gsub(/^[ \t]+/, '')
335
+ def sdoc_gemfile_entry
336
+ comment = 'bundle exec rake doc:rails generates the API under doc/api.'
337
+ GemfileEntry.new('sdoc', nil, comment, { group: :doc, require: false })
211
338
  end
212
339
 
213
340
  def coffee_gemfile_entry
341
+ comment = 'Use CoffeeScript for .js.coffee assets and views'
214
342
  if options.dev? || options.edge?
215
- <<-GEMFILE
216
- # Use CoffeeScript for .js.coffee assets and views
217
- gem 'coffee-rails', github: 'rails/coffee-rails'
218
- GEMFILE
343
+ GemfileEntry.github 'coffee-rails', 'rails/coffee-rails', comment
219
344
  else
220
- <<-GEMFILE
221
- # Use CoffeeScript for .js.coffee assets and views
222
- gem 'coffee-rails', '~> 4.0.0'
223
- GEMFILE
345
+ GemfileEntry.version 'coffee-rails', '~> 4.0.0', comment
224
346
  end
225
347
  end
226
348
 
227
349
  def javascript_gemfile_entry
228
- unless options[:skip_javascript]
229
- <<-GEMFILE.gsub(/^[ \t]+/, '')
230
- #{coffee_gemfile_entry}
231
- #{javascript_runtime_gemfile_entry}
232
- # Use #{options[:javascript]} as the JavaScript library
233
- gem '#{options[:javascript]}-rails'
234
-
235
- # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
236
- gem 'turbolinks'
237
- GEMFILE
350
+ if options[:skip_javascript]
351
+ []
352
+ else
353
+ gems = [coffee_gemfile_entry, javascript_runtime_gemfile_entry]
354
+ gems << GemfileEntry.version("#{options[:javascript]}-rails", nil,
355
+ "Use #{options[:javascript]} as the JavaScript library")
356
+
357
+ gems << GemfileEntry.version("turbolinks", nil,
358
+ "Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks")
359
+ gems
238
360
  end
239
361
  end
240
362
 
241
363
  def javascript_runtime_gemfile_entry
242
- runtime = if defined?(JRUBY_VERSION)
243
- "gem 'therubyrhino'"
364
+ comment = 'See https://github.com/sstephenson/execjs#readme for more supported runtimes'
365
+ if defined?(JRUBY_VERSION)
366
+ GemfileEntry.version 'therubyrhino', nil, comment
244
367
  else
245
- "# gem 'therubyracer', platforms: :ruby"
368
+ GemfileEntry.new 'therubyracer', nil, comment, { platforms: :ruby }, true
246
369
  end
247
- <<-GEMFILE
248
- # See https://github.com/sstephenson/execjs#readme for more supported runtimes
249
- #{runtime}
250
- GEMFILE
370
+ end
371
+
372
+ def spring_gemfile_entry
373
+ return [] unless spring_install?
374
+ comment = 'Spring speeds up development by keeping your application running in the background. Read more: https://github.com/jonleighton/spring'
375
+ GemfileEntry.new('spring', nil, comment, group: :development)
251
376
  end
252
377
 
253
378
  def bundle_command(command)
@@ -273,8 +398,22 @@ module Rails
273
398
  end
274
399
  end
275
400
 
401
+ def bundle_install?
402
+ !(options[:skip_gemfile] || options[:skip_bundle] || options[:pretend])
403
+ end
404
+
405
+ def spring_install?
406
+ !options[:skip_spring] && Process.respond_to?(:fork)
407
+ end
408
+
276
409
  def run_bundle
277
- bundle_command('install') unless options[:skip_gemfile] || options[:skip_bundle] || options[:pretend]
410
+ bundle_command('install') if bundle_install?
411
+ end
412
+
413
+ def generate_spring_binstubs
414
+ if bundle_install? && spring_install?
415
+ bundle_command("exec spring binstub --all")
416
+ end
278
417
  end
279
418
 
280
419
  def empty_directory_with_keep_file(destination, config = {})