railties 3.0.0.beta3 → 3.0.0.beta4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/CHANGELOG +5 -0
  2. data/README +118 -123
  3. data/guides/source/3_0_release_notes.textile +13 -11
  4. data/guides/source/action_controller_overview.textile +2 -2
  5. data/guides/source/action_mailer_basics.textile +70 -26
  6. data/guides/source/action_view_overview.textile +1 -1
  7. data/guides/source/active_record_basics.textile +9 -1
  8. data/guides/source/active_record_querying.textile +2 -2
  9. data/guides/source/active_support_core_extensions.textile +377 -9
  10. data/guides/source/activerecord_validations_callbacks.textile +98 -55
  11. data/guides/source/association_basics.textile +1 -1
  12. data/guides/source/caching_with_rails.textile +1 -1
  13. data/guides/source/command_line.textile +23 -23
  14. data/guides/source/configuring.textile +1 -3
  15. data/guides/source/contribute.textile +27 -28
  16. data/guides/source/credits.html.erb +4 -4
  17. data/guides/source/debugging_rails_applications.textile +2 -2
  18. data/guides/source/form_helpers.textile +7 -6
  19. data/guides/source/generators.textile +19 -29
  20. data/guides/source/getting_started.textile +106 -49
  21. data/guides/source/i18n.textile +27 -27
  22. data/guides/source/index.html.erb +18 -8
  23. data/guides/source/initialization.textile +140 -514
  24. data/guides/source/layout.html.erb +6 -4
  25. data/guides/source/layouts_and_rendering.textile +5 -5
  26. data/guides/source/migrations.textile +7 -3
  27. data/guides/source/nested_model_forms.textile +2 -2
  28. data/guides/source/performance_testing.textile +11 -12
  29. data/guides/source/plugins.textile +30 -30
  30. data/guides/source/rails_application_templates.textile +3 -3
  31. data/guides/source/rails_on_rack.textile +3 -66
  32. data/guides/source/routing.textile +10 -4
  33. data/guides/source/security.textile +1 -1
  34. data/guides/source/testing.textile +55 -52
  35. data/guides/w3c_validator.rb +67 -0
  36. data/lib/rails.rb +1 -0
  37. data/lib/rails/application.rb +49 -13
  38. data/lib/rails/application/bootstrap.rb +7 -6
  39. data/lib/rails/application/configuration.rb +24 -47
  40. data/lib/rails/application/finisher.rb +8 -3
  41. data/lib/rails/backtrace_cleaner.rb +11 -12
  42. data/lib/rails/commands.rb +54 -54
  43. data/lib/rails/commands/application.rb +7 -2
  44. data/lib/rails/commands/{performance/benchmarker.rb → benchmarker.rb} +0 -0
  45. data/lib/rails/commands/dbconsole.rb +4 -3
  46. data/lib/rails/commands/destroy.rb +1 -0
  47. data/lib/rails/commands/generate.rb +1 -0
  48. data/lib/rails/commands/{performance/profiler.rb → profiler.rb} +0 -0
  49. data/lib/rails/commands/runner.rb +4 -2
  50. data/lib/rails/configuration.rb +36 -0
  51. data/lib/rails/engine.rb +24 -24
  52. data/lib/rails/engine/configuration.rb +0 -1
  53. data/lib/rails/generators.rb +48 -10
  54. data/lib/rails/generators/actions.rb +5 -3
  55. data/lib/rails/generators/base.rb +23 -17
  56. data/lib/rails/generators/erb/scaffold/templates/_form.html.erb +9 -8
  57. data/lib/rails/generators/erb/scaffold/templates/show.html.erb +1 -1
  58. data/lib/rails/generators/generated_attribute.rb +7 -6
  59. data/lib/rails/generators/rails/app/USAGE +2 -2
  60. data/lib/rails/generators/rails/app/app_generator.rb +242 -97
  61. data/lib/rails/generators/rails/app/templates/Gemfile +3 -0
  62. data/lib/rails/generators/rails/app/templates/README +167 -130
  63. data/lib/rails/generators/rails/app/templates/Rakefile +0 -3
  64. data/lib/rails/generators/rails/app/templates/config/boot.rb +9 -2
  65. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml +5 -5
  66. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +4 -0
  67. data/lib/rails/generators/rails/app/templates/script/rails +2 -5
  68. data/lib/rails/generators/rails/generator/templates/%file_name%_generator.rb.tt +1 -3
  69. data/lib/rails/generators/rails/stylesheets/templates/scaffold.css +5 -9
  70. data/lib/rails/generators/test_case.rb +12 -0
  71. data/lib/rails/generators/test_unit/integration/templates/integration_test.rb +1 -1
  72. data/lib/rails/generators/test_unit/performance/templates/performance_test.rb +1 -1
  73. data/lib/rails/info.rb +0 -33
  74. data/lib/rails/log_subscriber.rb +13 -6
  75. data/lib/rails/rack/logger.rb +4 -3
  76. data/lib/rails/railtie.rb +4 -0
  77. data/lib/rails/railtie/configuration.rb +21 -4
  78. data/lib/rails/tasks/documentation.rake +2 -0
  79. data/lib/rails/tasks/framework.rake +22 -0
  80. data/lib/rails/tasks/middleware.rake +1 -1
  81. data/lib/rails/tasks/routes.rake +5 -1
  82. data/lib/rails/test_help.rb +3 -1
  83. data/lib/rails/test_unit/testing.rake +3 -1
  84. data/lib/rails/version.rb +1 -1
  85. metadata +12 -19
  86. data/lib/rails/application/metal_loader.rb +0 -50
  87. data/lib/rails/dispatcher.rb +0 -24
  88. data/lib/rails/generators/rails/mailer/USAGE +0 -15
  89. data/lib/rails/generators/rails/mailer/mailer_generator.rb +0 -14
  90. data/lib/rails/generators/rails/mailer/templates/mailer.rb +0 -16
  91. data/lib/rails/generators/rails/metal/USAGE +0 -8
  92. data/lib/rails/generators/rails/metal/metal_generator.rb +0 -11
  93. data/lib/rails/generators/rails/metal/templates/metal.rb +0 -12
@@ -1,6 +1,7 @@
1
1
  require 'rails/railtie'
2
2
  require 'active_support/core_ext/module/delegation'
3
3
  require 'pathname'
4
+ require 'rbconfig'
4
5
 
5
6
  module Rails
6
7
  # Rails::Engine allows you to wrap a specific Rails application and share it accross
@@ -24,7 +25,7 @@ module Rails
24
25
  # end
25
26
  #
26
27
  # Then ensure that this file is loaded at the top of your config/application.rb (or in
27
- # your Gemfile) and it will automatically load models, controllers, helpers and metals
28
+ # your Gemfile) and it will automatically load models, controllers and helpers
28
29
  # inside app, load routes at "config/routes.rb", load locales at "config/locales/*",
29
30
  # load tasks at "lib/tasks/*".
30
31
  #
@@ -41,10 +42,10 @@ module Rails
41
42
  # config.load_paths << File.expand_path("../lib/some/path", __FILE__)
42
43
  #
43
44
  # initializer "my_engine.add_middleware" do |app|
44
- # app.middlewares.use MyEngine::Middleware
45
+ # app.middleware.use MyEngine::Middleware
45
46
  # end
46
47
  # end
47
- #
48
+ #
48
49
  # == Paths
49
50
  #
50
51
  # Since Rails 3.0, both your Application and Engines do not have hardcoded paths.
@@ -72,7 +73,6 @@ module Rails
72
73
  # paths.app.controllers = "app/controllers"
73
74
  # paths.app.helpers = "app/helpers"
74
75
  # paths.app.models = "app/models"
75
- # paths.app.metals = "app/metal"
76
76
  # paths.app.views = "app/views"
77
77
  # paths.lib = "lib"
78
78
  # paths.lib.tasks = "lib/tasks"
@@ -119,20 +119,29 @@ module Rails
119
119
  root = File.exist?("#{root_path}/#{flag}") ? root_path : default
120
120
  raise "Could not find root path for #{self}" unless root
121
121
 
122
- RUBY_PLATFORM =~ /(:?mswin|mingw)/ ?
122
+ Config::CONFIG['host_os'] =~ /mswin|mingw/ ?
123
123
  Pathname.new(root).expand_path : Pathname.new(root).realpath
124
124
  end
125
125
  end
126
126
 
127
- delegate :middleware, :paths, :root, :to => :config
127
+ delegate :paths, :root, :to => :config
128
128
 
129
129
  def load_tasks
130
130
  super
131
131
  config.paths.lib.tasks.to_a.sort.each { |ext| load(ext) }
132
132
  end
133
133
 
134
+ def eager_load!
135
+ config.eager_load_paths.each do |load_path|
136
+ matcher = /\A#{Regexp.escape(load_path)}\/(.*)\.rb\Z/
137
+ Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
138
+ require_dependency file.sub(matcher, '\1')
139
+ end
140
+ end
141
+ end
142
+
134
143
  # Add configured load paths to ruby load paths and remove duplicates.
135
- initializer :set_load_path, :before => :bootstrap_load_path do
144
+ initializer :set_load_path, :before => :bootstrap_hook do
136
145
  config.load_paths.reverse_each do |path|
137
146
  $LOAD_PATH.unshift(path) if File.directory?(path)
138
147
  end
@@ -141,7 +150,10 @@ module Rails
141
150
 
142
151
  # Set the paths from which Rails will automatically load source files,
143
152
  # and the load_once paths.
144
- initializer :set_autoload_paths, :before => :bootstrap_load_path do |app|
153
+ #
154
+ # This needs to be an initializer, since it needs to run once
155
+ # per engine and get the engine as a block parameter
156
+ initializer :set_autoload_paths, :before => :bootstrap_hook do |app|
145
157
  ActiveSupport::Dependencies.load_paths.unshift(*config.load_paths)
146
158
 
147
159
  if reloadable?(app)
@@ -166,7 +178,7 @@ module Rails
166
178
  paths.app.controllers.to_a.each do |load_path|
167
179
  load_path = File.expand_path(load_path)
168
180
  Dir["#{load_path}/*/**/*_controller.rb"].collect do |path|
169
- namespace = File.dirname(path).sub(/#{load_path}\/?/, '')
181
+ namespace = File.dirname(path).sub(/#{Regexp.escape(load_path)}\/?/, '')
170
182
  app.routes.controller_namespaces << namespace unless namespace.empty?
171
183
  end
172
184
  end
@@ -189,27 +201,15 @@ module Rails
189
201
  end
190
202
  end
191
203
 
192
- initializer :add_metals do |app|
193
- app.metal_loader.paths.unshift(*paths.app.metals.to_a)
194
- end
195
-
196
204
  initializer :load_config_initializers do
197
205
  paths.config.initializers.to_a.sort.each do |initializer|
198
206
  load(initializer)
199
207
  end
200
208
  end
201
209
 
202
- initializer :load_app_classes do |app|
203
- next if $rails_rake_task
204
-
205
- if app.config.cache_classes
206
- config.eager_load_paths.each do |load_path|
207
- matcher = /\A#{Regexp.escape(load_path)}\/(.*)\.rb\Z/
208
- Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
209
- require_dependency file.sub(matcher, '\1')
210
- end
211
- end
212
- end
210
+ initializer :engines_blank_point do
211
+ # We need this initializer so all extra initializers added in engines are
212
+ # consistently executed after all the initializers above across all engines.
213
213
  end
214
214
 
215
215
  protected
@@ -19,7 +19,6 @@ module Rails
19
19
  paths.app.helpers "app/helpers", :eager_load => true
20
20
  paths.app.models "app/models", :eager_load => true
21
21
  paths.app.mailers "app/mailers", :eager_load => true
22
- paths.app.metals "app/metal", :eager_load => true
23
22
  paths.app.views "app/views"
24
23
  paths.lib "lib", :load_path => true
25
24
  paths.lib.tasks "lib/tasks", :glob => "**/*.rake"
@@ -68,6 +68,7 @@ module Rails
68
68
  options.deep_merge! config.options
69
69
  fallbacks.merge! config.fallbacks
70
70
  templates_path.concat config.templates
71
+ templates_path.uniq!
71
72
  end
72
73
 
73
74
  def self.templates_path
@@ -166,6 +167,42 @@ module Rails
166
167
  end
167
168
  end
168
169
 
170
+ def self.hidden_namespaces
171
+ @hidden_namespaces ||= begin
172
+ orm = options[:rails][:orm]
173
+ test = options[:rails][:test_framework]
174
+ template = options[:rails][:template_engine]
175
+
176
+ [
177
+ "rails",
178
+ "#{orm}:migration",
179
+ "#{orm}:model",
180
+ "#{orm}:observer",
181
+ "#{orm}:session_migration",
182
+ "#{test}:controller",
183
+ "#{test}:helper",
184
+ "#{test}:integration",
185
+ "#{test}:mailer",
186
+ "#{test}:model",
187
+ "#{test}:observer",
188
+ "#{test}:scaffold",
189
+ "#{test}:view",
190
+ "#{test}:performance",
191
+ "#{test}:plugin",
192
+ "#{template}:controller",
193
+ "#{template}:scaffold",
194
+ "#{template}:mailer"
195
+ ]
196
+ end
197
+ end
198
+
199
+ class << self
200
+ def hide_namespaces(*namespaces)
201
+ hidden_namespaces.concat(namespaces)
202
+ end
203
+ alias hide_namespace hide_namespaces
204
+ end
205
+
169
206
  # Show help message with available generators.
170
207
  def self.help(command = 'generate')
171
208
  lookup!
@@ -197,9 +234,7 @@ module Rails
197
234
  rails.delete("app")
198
235
  print_list("rails", rails)
199
236
 
200
- groups.delete("active_record") if options[:rails][:orm] == :active_record
201
- groups.delete("test_unit") if options[:rails][:test_framework] == :test_unit
202
- groups.delete("erb") if options[:rails][:template_engine] == :erb
237
+ hidden_namespaces.each {|n| groups.delete(n.to_s) }
203
238
 
204
239
  groups.sort.each { |b, n| print_list(b, n) }
205
240
  end
@@ -208,9 +243,17 @@ module Rails
208
243
 
209
244
  # Prints a list of generators.
210
245
  def self.print_list(base, namespaces) #:nodoc:
246
+ namespaces = namespaces.reject do |n|
247
+ hidden_namespaces.include?(n)
248
+ end
249
+
211
250
  return if namespaces.empty?
212
251
  puts "#{base.camelize}:"
213
- namespaces.each { |namespace| puts(" #{namespace}") }
252
+
253
+ namespaces.each do |namespace|
254
+ puts(" #{namespace}")
255
+ end
256
+
214
257
  puts
215
258
  end
216
259
 
@@ -290,10 +333,5 @@ module Rails
290
333
  paths.uniq!
291
334
  paths
292
335
  end
293
-
294
336
  end
295
- end
296
-
297
- # If the application was already defined, configure generators,
298
- # otherwise you have to configure it by hand.
299
- Rails::Generators.configure! if Rails.respond_to?(:application) && Rails.application
337
+ end
@@ -1,5 +1,6 @@
1
1
  require 'open-uri'
2
2
  require 'active_support/deprecation'
3
+ require 'rbconfig'
3
4
 
4
5
  module Rails
5
6
  module Generators
@@ -53,7 +54,8 @@ module Rails
53
54
  name, version = args
54
55
 
55
56
  # Deal with deprecated options
56
- { :env => :only, :lib => :require_as }.each do |old, new|
57
+ { :env => :group, :only => :group,
58
+ :lib => :require, :require_as => :require }.each do |old, new|
57
59
  next unless options[old]
58
60
  options[new] = options.delete(old)
59
61
  ActiveSupport::Deprecation.warn "#{old.inspect} option in gem is deprecated, use #{new.inspect} instead"
@@ -240,7 +242,7 @@ module Rails
240
242
  def rake(command, options={})
241
243
  log :rake, command
242
244
  env = options[:env] || 'development'
243
- sudo = options[:sudo] && RUBY_PLATFORM !~ /mswin|mingw/ ? 'sudo ' : ''
245
+ sudo = options[:sudo] && Config::CONFIG['host_os'] !~ /mswin|mingw/ ? 'sudo ' : ''
244
246
  in_root { run("#{sudo}#{extify(:rake)} #{command} RAILS_ENV=#{env}", :verbose => false) }
245
247
  end
246
248
 
@@ -307,7 +309,7 @@ module Rails
307
309
  # Add an extension to the given name based on the platform.
308
310
  #
309
311
  def extify(name)
310
- if RUBY_PLATFORM =~ /mswin|mingw/
312
+ if Config::CONFIG['host_os'] =~ /mswin|mingw/
311
313
  "#{name}.bat"
312
314
  else
313
315
  name
@@ -20,24 +20,19 @@ module Rails
20
20
 
21
21
  add_runtime_options!
22
22
 
23
- # Automatically sets the source root based on the class name.
24
- #
25
- def self.source_root
26
- @_rails_source_root ||= begin
27
- if base_name && generator_name
28
- File.expand_path(File.join(base_name, generator_name, 'templates'), File.dirname(__FILE__))
29
- end
30
- end
23
+ # Returns the source root for this generator using default_source_root as default.
24
+ def self.source_root(path=nil)
25
+ @_source_root = path if path
26
+ @_source_root ||= default_source_root
31
27
  end
32
28
 
33
29
  # Tries to get the description from a USAGE file one folder above the source
34
30
  # root otherwise uses a default description.
35
- #
36
31
  def self.desc(description=nil)
37
32
  return super if description
38
- usage = File.expand_path(File.join(source_root, "..", "USAGE"))
33
+ usage = source_root && File.expand_path("../USAGE", source_root)
39
34
 
40
- @desc ||= if File.exist?(usage)
35
+ @desc ||= if usage && File.exist?(usage)
41
36
  File.read(usage)
42
37
  else
43
38
  "Description:\n Create #{base_name.humanize.downcase} files for #{generator_name} generator."
@@ -47,7 +42,6 @@ module Rails
47
42
  # Convenience method to get the namespace from the class name. It's the
48
43
  # same as Thor default except that the Generator at the end of the class
49
44
  # is removed.
50
- #
51
45
  def self.namespace(name=nil)
52
46
  return super if name
53
47
  @namespace ||= super.sub(/_generator$/, '').sub(/:generators:/, ':')
@@ -200,7 +194,6 @@ module Rails
200
194
  end
201
195
 
202
196
  # Make class option aware of Rails::Generators.options and Rails::Generators.aliases.
203
- #
204
197
  def self.class_option(name, options={}) #:nodoc:
205
198
  options[:desc] = "Indicates when to generate #{name.to_s.humanize.downcase}" unless options.key?(:desc)
206
199
  options[:aliases] = default_aliases_for_option(name, options)
@@ -208,14 +201,27 @@ module Rails
208
201
  super(name, options)
209
202
  end
210
203
 
204
+ # Returns the default source root for a given generator. This is used internally
205
+ # by rails to set its generators source root. If you want to customize your source
206
+ # root, you should use source_root.
207
+ def self.default_source_root
208
+ return unless base_name && generator_name
209
+ path = File.expand_path(File.join(base_name, generator_name, 'templates'), base_root)
210
+ path if File.exists?(path)
211
+ end
212
+
213
+ # Returns the base root for a common set of generators. This is used to dynamically
214
+ # guess the default source root.
215
+ def self.base_root
216
+ File.dirname(__FILE__)
217
+ end
218
+
211
219
  # Cache source root and add lib/generators/base/generator/templates to
212
220
  # source paths.
213
- #
214
221
  def self.inherited(base) #:nodoc:
215
222
  super
216
223
 
217
- # Cache source root, we need to do this, since __FILE__ is a relative value
218
- # and can point to wrong directions when inside an specified directory.
224
+ # Invoke source_root so the default_source_root is set.
219
225
  base.source_root
220
226
 
221
227
  if base.name && base.name !~ /Base$/
@@ -282,7 +288,7 @@ module Rails
282
288
  end
283
289
 
284
290
  # Removes the namespaces and get the generator name. For example,
285
- # Rails::Generators::MetalGenerator will return "metal" as generator name.
291
+ # Rails::Generators::ModelGenerator will return "model" as generator name.
286
292
  #
287
293
  def self.generator_name
288
294
  @generator_name ||= begin
@@ -1,13 +1,14 @@
1
1
  <%%= form_for(@<%= singular_name %>) do |f| %>
2
2
  <%% if @<%= singular_name %>.errors.any? %>
3
- <div id="errorExplanation">
4
- <h2><%%= pluralize(@<%= singular_name %>.errors.count, "error") %> prohibited this <%= singular_name %> from being saved:</h2>
5
- <ul>
6
- <%% @<%= singular_name %>.errors.full_messages.each do |msg| %>
7
- <li><%%= msg %></li>
8
- <%% end %>
9
- </ul>
10
- </div>
3
+ <div id="error_explanation">
4
+ <h2><%%= pluralize(@<%= singular_name %>.errors.count, "error") %> prohibited this <%= singular_name %> from being saved:</h2>
5
+
6
+ <ul>
7
+ <%% @<%= singular_name %>.errors.full_messages.each do |msg| %>
8
+ <li><%%= msg %></li>
9
+ <%% end %>
10
+ </ul>
11
+ </div>
11
12
  <%% end %>
12
13
 
13
14
  <% for attribute in attributes -%>
@@ -1,4 +1,4 @@
1
- <p class="notice"><%%= notice %></p>
1
+ <p id="notice"><%%= notice %></p>
2
2
 
3
3
  <% for attribute in attributes -%>
4
4
  <p>
@@ -9,12 +9,13 @@ module Rails
9
9
 
10
10
  def field_type
11
11
  @field_type ||= case type
12
- when :integer, :float, :decimal then :text_field
13
- when :datetime, :timestamp, :time then :datetime_select
14
- when :date then :date_select
15
- when :string then :text_field
16
- when :text then :text_area
17
- when :boolean then :check_box
12
+ when :integer, :float, :decimal then :text_field
13
+ when :time then :time_select
14
+ when :datetime, :timestamp then :datetime_select
15
+ when :date then :date_select
16
+ when :string then :text_field
17
+ when :text then :text_area
18
+ when :boolean then :check_box
18
19
  else
19
20
  :text_field
20
21
  end
@@ -1,9 +1,9 @@
1
1
  Description:
2
- The 'rails' command creates a new Rails application with a default
2
+ The 'rails new' command creates a new Rails application with a default
3
3
  directory structure and configuration at the path you specify.
4
4
 
5
5
  Example:
6
- rails ~/Code/Ruby/weblog
6
+ rails new ~/Code/Ruby/weblog
7
7
 
8
8
  This generates a skeletal Rails installation in ~/Code/Ruby/weblog.
9
9
  See the README in the newly created application to get going.
@@ -1,87 +1,62 @@
1
1
  require 'digest/md5'
2
2
  require 'active_support/secure_random'
3
3
  require 'rails/version' unless defined?(Rails::VERSION)
4
+ require 'rbconfig'
5
+ require 'open-uri'
6
+ require 'uri'
4
7
 
5
- module Rails::Generators
6
- # We need to store the RAILS_DEV_PATH in a constant, otherwise the path
7
- # can change in Ruby 1.8.7 when we FileUtils.cd.
8
- RAILS_DEV_PATH = File.expand_path("../../../../../..", File.dirname(__FILE__))
8
+ module Rails
9
+ module ActionMethods
10
+ attr_reader :options
9
11
 
10
- RESERVED_NAMES = %w[generate console server dbconsole
11
- application destroy benchmarker profiler
12
- plugin runner test]
13
-
14
- class AppGenerator < Base
15
- DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db )
16
-
17
- attr_accessor :rails_template
18
- add_shebang_option!
19
-
20
- argument :app_path, :type => :string
21
-
22
- class_option :database, :type => :string, :aliases => "-d", :default => "sqlite3",
23
- :desc => "Preconfigure for selected database (options: #{DATABASES.join('/')})"
24
-
25
- class_option :template, :type => :string, :aliases => "-m",
26
- :desc => "Path to an application template (can be a filesystem path or URL)."
27
-
28
- class_option :dev, :type => :boolean, :default => false,
29
- :desc => "Setup the application with Gemfile pointing to your Rails checkout"
30
-
31
- class_option :edge, :type => :boolean, :default => false,
32
- :desc => "Setup the application with Gemfile pointing to Rails repository"
33
-
34
- class_option :skip_gemfile, :type => :boolean, :default => false,
35
- :desc => "Don't create a Gemfile"
36
-
37
- class_option :skip_activerecord, :type => :boolean, :aliases => "-O", :default => false,
38
- :desc => "Skip ActiveRecord files"
39
-
40
- class_option :skip_testunit, :type => :boolean, :aliases => "-T", :default => false,
41
- :desc => "Skip TestUnit files"
42
-
43
- class_option :skip_prototype, :type => :boolean, :aliases => "-J", :default => false,
44
- :desc => "Skip Prototype files"
45
-
46
- class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false,
47
- :desc => "Skip Git ignores and keeps"
48
-
49
- # Add bin/rails options
50
- class_option :version, :type => :boolean, :aliases => "-v", :group => :rails,
51
- :desc => "Show Rails version number and quit"
12
+ def initialize(generator)
13
+ @generator = generator
14
+ @options = generator.options
15
+ end
52
16
 
53
- class_option :help, :type => :boolean, :aliases => "-h", :group => :rails,
54
- :desc => "Show this help message and quit"
17
+ private
18
+ %w(template copy_file directory empty_directory inside
19
+ empty_directory_with_gitkeep create_file chmod shebang).each do |method|
20
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
21
+ def #{method}(*args, &block)
22
+ @generator.send(:#{method}, *args, &block)
23
+ end
24
+ RUBY
25
+ end
55
26
 
56
- def initialize(*args)
57
- super
58
- if !options[:skip_activerecord] && !DATABASES.include?(options[:database])
59
- raise Error, "Invalid value for --database option. Supported for preconfiguration are: #{DATABASES.join(", ")}."
27
+ # TODO: Remove once this is fully in place
28
+ def method_missing(meth, *args, &block)
29
+ STDERR.puts "Calling #{meth} with #{args.inspect} with #{block}"
30
+ @generator.send(meth, *args, &block)
60
31
  end
32
+ end
33
+
34
+ class AppBuilder
35
+ def rakefile
36
+ template "Rakefile"
61
37
  end
62
38
 
63
- def create_root
64
- self.destination_root = File.expand_path(app_path, destination_root)
65
- valid_app_const?
39
+ def readme
40
+ copy_file "README"
41
+ end
66
42
 
67
- empty_directory '.'
68
- set_default_accessors!
69
- FileUtils.cd(destination_root)
43
+ def gemfile
44
+ template "Gemfile"
70
45
  end
71
46
 
72
- def create_root_files
73
- copy_file "README"
74
- copy_file "gitignore", ".gitignore" unless options[:skip_git]
75
- template "Rakefile"
47
+ def configru
76
48
  template "config.ru"
77
- template "Gemfile" unless options[:skip_gemfile]
78
49
  end
79
50
 
80
- def create_app_files
51
+ def gitignore
52
+ copy_file "gitignore", ".gitignore"
53
+ end
54
+
55
+ def app
81
56
  directory 'app'
82
57
  end
83
58
 
84
- def create_config_files
59
+ def config
85
60
  empty_directory "config"
86
61
 
87
62
  inside "config" do
@@ -95,29 +70,24 @@ module Rails::Generators
95
70
  end
96
71
  end
97
72
 
98
- def create_boot_file
99
- template "config/boot.rb"
100
- end
101
-
102
- def create_activerecord_files
103
- return if options[:skip_activerecord]
104
- template "config/databases/#{options[:database]}.yml", "config/database.yml"
73
+ def database_yml
74
+ template "config/databases/#{@options[:database]}.yml", "config/database.yml"
105
75
  end
106
76
 
107
- def create_db_files
77
+ def db
108
78
  directory "db"
109
79
  end
110
80
 
111
- def create_doc_files
81
+ def doc
112
82
  directory "doc"
113
83
  end
114
84
 
115
- def create_lib_files
85
+ def lib
116
86
  empty_directory "lib"
117
87
  empty_directory_with_gitkeep "lib/tasks"
118
88
  end
119
89
 
120
- def create_log_files
90
+ def log
121
91
  empty_directory "log"
122
92
 
123
93
  inside "log" do
@@ -128,19 +98,19 @@ module Rails::Generators
128
98
  end
129
99
  end
130
100
 
131
- def create_public_files
132
- directory "public", "public", :recursive => false # Do small steps, so anyone can overwrite it.
101
+ def public_directory
102
+ directory "public", "public", :recursive => false
133
103
  end
134
104
 
135
- def create_public_image_files
105
+ def images
136
106
  directory "public/images"
137
107
  end
138
108
 
139
- def create_public_stylesheets_files
109
+ def stylesheets
140
110
  empty_directory_with_gitkeep "public/stylesheets"
141
111
  end
142
112
 
143
- def create_prototype_files
113
+ def javascripts
144
114
  unless options[:skip_prototype]
145
115
  directory "public/javascripts"
146
116
  else
@@ -148,19 +118,18 @@ module Rails::Generators
148
118
  end
149
119
  end
150
120
 
151
- def create_script_files
121
+ def script
152
122
  directory "script" do |content|
153
123
  "#{shebang}\n" + content
154
124
  end
155
125
  chmod "script", 0755, :verbose => false
156
126
  end
157
127
 
158
- def create_test_files
159
- return if options[:skip_testunit]
128
+ def test
160
129
  directory "test"
161
130
  end
162
131
 
163
- def create_tmp_files
132
+ def tmp
164
133
  empty_directory "tmp"
165
134
 
166
135
  inside "tmp" do
@@ -170,25 +139,200 @@ module Rails::Generators
170
139
  end
171
140
  end
172
141
 
173
- def create_vendor_files
142
+ def vendor_plugins
174
143
  empty_directory_with_gitkeep "vendor/plugins"
175
144
  end
145
+ end
176
146
 
177
- def apply_rails_template
178
- apply rails_template if rails_template
179
- rescue Thor::Error, LoadError, Errno::ENOENT => e
180
- raise Error, "The template [#{rails_template}] could not be loaded. Error: #{e}"
181
- end
147
+ module Generators
148
+ # We need to store the RAILS_DEV_PATH in a constant, otherwise the path
149
+ # can change in Ruby 1.8.7 when we FileUtils.cd.
150
+ RAILS_DEV_PATH = File.expand_path("../../../../../..", File.dirname(__FILE__))
182
151
 
183
- def bundle_if_dev_or_edge
184
- bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle')
185
- run "#{bundle_command} install" if dev_or_edge?
186
- end
152
+ RESERVED_NAMES = %w[application destroy benchmarker profiler
153
+ plugin runner test]
154
+
155
+ class AppGenerator < Base
156
+ DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db )
157
+
158
+ attr_accessor :rails_template
159
+ add_shebang_option!
160
+
161
+ argument :app_path, :type => :string
162
+
163
+ class_option :database, :type => :string, :aliases => "-d", :default => "sqlite3",
164
+ :desc => "Preconfigure for selected database (options: #{DATABASES.join('/')})"
165
+
166
+ class_option :builder, :type => :string, :aliases => "-b",
167
+ :desc => "Path to an application builder (can be a filesystem path or URL)"
168
+
169
+ class_option :template, :type => :string, :aliases => "-m",
170
+ :desc => "Path to an application template (can be a filesystem path or URL)."
171
+
172
+ class_option :dev, :type => :boolean, :default => false,
173
+ :desc => "Setup the application with Gemfile pointing to your Rails checkout"
174
+
175
+ class_option :edge, :type => :boolean, :default => false,
176
+ :desc => "Setup the application with Gemfile pointing to Rails repository"
177
+
178
+ class_option :skip_gemfile, :type => :boolean, :default => false,
179
+ :desc => "Don't create a Gemfile"
180
+
181
+ class_option :skip_activerecord, :type => :boolean, :aliases => "-O", :default => false,
182
+ :desc => "Skip ActiveRecord files"
183
+
184
+ class_option :skip_testunit, :type => :boolean, :aliases => "-T", :default => false,
185
+ :desc => "Skip TestUnit files"
186
+
187
+ class_option :skip_prototype, :type => :boolean, :aliases => "-J", :default => false,
188
+ :desc => "Skip Prototype files"
189
+
190
+ class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false,
191
+ :desc => "Skip Git ignores and keeps"
192
+
193
+ # Add bin/rails options
194
+ class_option :version, :type => :boolean, :aliases => "-v", :group => :rails,
195
+ :desc => "Show Rails version number and quit"
196
+
197
+ class_option :help, :type => :boolean, :aliases => "-h", :group => :rails,
198
+ :desc => "Show this help message and quit"
199
+
200
+ def initialize(*args)
201
+ raise Error, "Options should be given after the application name. For details run: rails --help" if args[0].blank?
202
+
203
+ @original_wd = Dir.pwd
204
+
205
+ super
206
+
207
+ if !options[:skip_activerecord] && !DATABASES.include?(options[:database])
208
+ raise Error, "Invalid value for --database option. Supported for preconfiguration are: #{DATABASES.join(", ")}."
209
+ end
210
+ end
211
+
212
+ def create_root
213
+ self.destination_root = File.expand_path(app_path, destination_root)
214
+ valid_app_const?
215
+
216
+ empty_directory '.'
217
+ set_default_accessors!
218
+ FileUtils.cd(destination_root)
219
+ end
220
+
221
+ def create_root_files
222
+ build(:readme)
223
+ build(:rakefile)
224
+ build(:configru)
225
+ build(:gitignore) unless options[:skip_git]
226
+ build(:gemfile) unless options[:skip_gemfile]
227
+ end
228
+
229
+ def create_app_files
230
+ build(:app)
231
+ end
232
+
233
+ def create_config_files
234
+ build(:config)
235
+ end
236
+
237
+ def create_boot_file
238
+ template "config/boot.rb"
239
+ end
240
+
241
+ def create_activerecord_files
242
+ return if options[:skip_activerecord]
243
+ build(:database_yml)
244
+ end
245
+
246
+ def create_db_files
247
+ build(:db)
248
+ end
249
+
250
+ def create_doc_files
251
+ build(:doc)
252
+ end
253
+
254
+ def create_lib_files
255
+ build(:lib)
256
+ end
257
+
258
+ def create_log_files
259
+ build(:log)
260
+ end
261
+
262
+ def create_public_files
263
+ build(:public_directory)
264
+ end
265
+
266
+ def create_public_image_files
267
+ build(:images)
268
+ end
269
+
270
+ def create_public_stylesheets_files
271
+ build(:stylesheets)
272
+ end
273
+
274
+ def create_prototype_files
275
+ build(:javascripts)
276
+ end
277
+
278
+ def create_script_files
279
+ build(:script)
280
+ end
281
+
282
+ def create_test_files
283
+ build(:test) unless options[:skip_testunit]
284
+ end
285
+
286
+ def create_tmp_files
287
+ build(:tmp)
288
+ end
289
+
290
+ def create_vendor_files
291
+ build(:vendor_plugins)
292
+ end
293
+
294
+ def finish_template
295
+ build(:leftovers)
296
+ end
297
+
298
+ def apply_rails_template
299
+ apply rails_template if rails_template
300
+ rescue Thor::Error, LoadError, Errno::ENOENT => e
301
+ raise Error, "The template [#{rails_template}] could not be loaded. Error: #{e}"
302
+ end
303
+
304
+ def bundle_if_dev_or_edge
305
+ bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle')
306
+ run "#{bundle_command} install" if dev_or_edge?
307
+ end
187
308
 
188
309
  protected
189
310
 
190
311
  def self.banner
191
- "rails #{self.arguments.map(&:usage).join(' ')} [options]"
312
+ "rails new #{self.arguments.map(&:usage).join(' ')} [options]"
313
+ end
314
+
315
+ def builder
316
+ @builder ||= begin
317
+ if path = options[:builder]
318
+ if URI(path).is_a?(URI::HTTP)
319
+ contents = open(path, "Accept" => "application/x-thor-template") {|io| io.read }
320
+ else
321
+ contents = open(File.expand_path(path, @original_wd)) {|io| io.read }
322
+ end
323
+
324
+ prok = eval("proc { #{contents} }", TOPLEVEL_BINDING, path, 1)
325
+ instance_eval(&prok)
326
+ end
327
+
328
+ builder_class = defined?(::AppBuilder) ? ::AppBuilder : Rails::AppBuilder
329
+ builder_class.send(:include, ActionMethods)
330
+ builder_class.new(self)
331
+ end
332
+ end
333
+
334
+ def build(meth, *args)
335
+ builder.send(meth, *args) if builder.respond_to?(meth)
192
336
  end
193
337
 
194
338
  def set_default_accessors!
@@ -265,12 +409,13 @@ module Rails::Generators
265
409
  "/opt/local/var/run/mysql4/mysqld.sock", # mac + darwinports + mysql4
266
410
  "/opt/local/var/run/mysql5/mysqld.sock", # mac + darwinports + mysql5
267
411
  "/opt/lampp/var/mysql/mysql.sock" # xampp for linux
268
- ].find { |f| File.exist?(f) } unless RUBY_PLATFORM =~ /(:?mswin|mingw)/
412
+ ].find { |f| File.exist?(f) } unless Config::CONFIG['host_os'] =~ /mswin|mingw/
269
413
  end
270
414
 
271
415
  def empty_directory_with_gitkeep(destination, config = {})
272
416
  empty_directory(destination, config)
273
417
  create_file("#{destination}/.gitkeep") unless options[:skip_git]
274
418
  end
419
+ end
275
420
  end
276
421
  end