rails 2.0.5 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rails might be problematic. Click here for more details.

Files changed (84) hide show
  1. data/CHANGELOG +115 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README +67 -14
  4. data/Rakefile +9 -19
  5. data/bin/dbconsole +3 -0
  6. data/bin/rails +0 -0
  7. data/builtin/rails_info/rails/info.rb +5 -5
  8. data/configs/apache.conf +0 -0
  9. data/configs/databases/frontbase.yml +2 -2
  10. data/configs/databases/mysql.yml +2 -2
  11. data/configs/databases/oracle.yml +3 -3
  12. data/configs/databases/postgresql.yml +2 -2
  13. data/configs/databases/sqlite2.yml +2 -2
  14. data/configs/databases/sqlite3.yml +2 -2
  15. data/configs/initializers/new_rails_defaults.rb +15 -0
  16. data/configs/routes.rb +6 -0
  17. data/dispatches/dispatch.fcgi +0 -0
  18. data/dispatches/dispatch.rb +0 -0
  19. data/environments/boot.rb +1 -0
  20. data/environments/development.rb +0 -1
  21. data/environments/environment.rb +15 -7
  22. data/environments/production.rb +3 -0
  23. data/environments/test.rb +1 -1
  24. data/fresh_rakefile +0 -0
  25. data/helpers/application.rb +5 -0
  26. data/html/images/rails.png +0 -0
  27. data/html/index.html +6 -9
  28. data/html/javascripts/controls.js +1 -1
  29. data/html/javascripts/dragdrop.js +1 -1
  30. data/html/javascripts/effects.js +1 -1
  31. data/lib/commands/console.rb +2 -2
  32. data/lib/commands/dbconsole.rb +65 -0
  33. data/lib/commands/generate.rb +0 -0
  34. data/lib/commands/performance/profiler.rb +1 -1
  35. data/lib/commands/performance/request.rb +0 -0
  36. data/lib/commands/plugin.rb +28 -1
  37. data/lib/commands/server.rb +2 -2
  38. data/lib/commands/servers/lighttpd.rb +1 -1
  39. data/lib/commands/servers/mongrel.rb +9 -9
  40. data/lib/commands/servers/new_mongrel.rb +16 -0
  41. data/lib/commands/servers/webrick.rb +1 -1
  42. data/lib/console_app.rb +2 -2
  43. data/lib/dispatcher.rb +1 -1
  44. data/lib/fcgi_handler.rb +32 -16
  45. data/lib/initializer.rb +273 -59
  46. data/lib/rails/gem_builder.rb +21 -0
  47. data/lib/rails/gem_dependency.rb +124 -0
  48. data/lib/rails/mongrel_server/commands.rb +342 -0
  49. data/lib/rails/mongrel_server/handler.rb +55 -0
  50. data/lib/rails/plugin.rb +42 -11
  51. data/lib/rails/plugin/loader.rb +3 -1
  52. data/lib/rails/plugin/locator.rb +22 -1
  53. data/lib/rails/version.rb +2 -2
  54. data/lib/rails_generator/base.rb +1 -1
  55. data/lib/rails_generator/commands.rb +63 -47
  56. data/lib/rails_generator/generators/applications/app/app_generator.rb +5 -7
  57. data/lib/rails_generator/generators/components/controller/templates/controller.rb +1 -4
  58. data/lib/rails_generator/generators/components/controller/templates/functional_test.rb +1 -1
  59. data/lib/rails_generator/generators/components/integration_test/templates/integration_test.rb +1 -1
  60. data/lib/rails_generator/generators/components/mailer/mailer_generator.rb +2 -6
  61. data/lib/rails_generator/generators/components/mailer/templates/mailer.rb +8 -6
  62. data/lib/rails_generator/generators/components/mailer/templates/unit_test.rb +1 -1
  63. data/lib/rails_generator/generators/components/migration/USAGE +4 -4
  64. data/lib/rails_generator/generators/components/model/templates/unit_test.rb +1 -1
  65. data/lib/rails_generator/generators/components/observer/templates/unit_test.rb +1 -1
  66. data/lib/rails_generator/generators/components/plugin/templates/Rakefile +0 -0
  67. data/lib/rails_generator/generators/components/resource/templates/functional_test.rb +1 -1
  68. data/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb +2 -1
  69. data/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb +1 -1
  70. data/lib/rails_generator/generators/components/scaffold/templates/style.css +0 -20
  71. data/lib/rails_generator/generators/components/scaffold/templates/view_edit.html.erb +3 -4
  72. data/lib/rails_generator/generators/components/scaffold/templates/view_new.html.erb +3 -4
  73. data/lib/rails_generator/lookup.rb +6 -2
  74. data/lib/rails_generator/options.rb +7 -0
  75. data/lib/rails_generator/scripts.rb +8 -5
  76. data/lib/rails_generator/secret_key_generator.rb +12 -8
  77. data/lib/source_annotation_extractor.rb +40 -0
  78. data/lib/tasks/databases.rake +52 -27
  79. data/lib/tasks/framework.rake +22 -29
  80. data/lib/tasks/gems.rake +64 -0
  81. data/lib/tasks/misc.rake +47 -0
  82. data/lib/tasks/testing.rake +1 -1
  83. data/lib/test_help.rb +8 -0
  84. metadata +19 -15
@@ -1,10 +1,7 @@
1
1
  class <%= class_name %>Controller < ApplicationController
2
- <% if options[:scaffold] -%>
3
- scaffold :<%= singular_name %>
4
- <% end -%>
5
2
  <% for action in actions -%>
6
-
7
3
  def <%= action %>
8
4
  end
5
+
9
6
  <% end -%>
10
7
  end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../test_helper'
1
+ require 'test_helper'
2
2
 
3
3
  class <%= class_name %>ControllerTest < ActionController::TestCase
4
4
  # Replace this with your real tests.
@@ -1,4 +1,4 @@
1
- require "#{File.dirname(__FILE__)}<%= '/..' * class_nesting_depth %>/../test_helper"
1
+ require 'test_helper'
2
2
 
3
3
  class <%= class_name %>Test < ActionController::IntegrationTest
4
4
  # fixtures :your, :models
@@ -11,12 +11,8 @@ class MailerGenerator < Rails::Generator::NamedBase
11
11
  m.directory File.join('test/fixtures', file_path)
12
12
 
13
13
  # Mailer class and unit test.
14
- m.template "mailer.rb", File.join('app/models',
15
- class_path,
16
- "#{file_name}.rb")
17
- m.template "unit_test.rb", File.join('test/unit',
18
- class_path,
19
- "#{file_name}_test.rb")
14
+ m.template "mailer.rb", File.join('app/models', class_path, "#{file_name}.rb")
15
+ m.template "unit_test.rb", File.join('test/unit', class_path, "#{file_name}_test.rb")
20
16
 
21
17
  # View template and fixture for each action.
22
18
  actions.each do |action|
@@ -1,13 +1,15 @@
1
1
  class <%= class_name %> < ActionMailer::Base
2
+
2
3
  <% for action in actions -%>
3
4
 
4
5
  def <%= action %>(sent_at = Time.now)
5
- @subject = '<%= class_name %>#<%= action %>'
6
- @body = {}
7
- @recipients = ''
8
- @from = ''
9
- @sent_on = sent_at
10
- @headers = {}
6
+ subject '<%= class_name %>#<%= action %>'
7
+ recipients ''
8
+ from ''
9
+ sent_on sent_at
10
+
11
+ body :greeting => 'Hi,'
11
12
  end
12
13
  <% end -%>
14
+
13
15
  end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../test_helper'
1
+ require 'test_helper'
2
2
 
3
3
  class <%= class_name %>Test < ActionMailer::TestCase
4
4
  tests <%= class_name %>
@@ -2,7 +2,7 @@ Description:
2
2
  Stubs out a new database migration. Pass the migration name, either
3
3
  CamelCased or under_scored, and an optional list of attribute pairs as arguments.
4
4
 
5
- A migration class is generated in db/migrate prefixed by the latest migration number.
5
+ A migration class is generated in db/migrate prefixed by a timestamp of the current date and time.
6
6
 
7
7
  You can name your migration in either of these formats to generate add/remove
8
8
  column lines from supplied attributes: AddColumnsToTable or RemoveColumnsFromTable
@@ -10,12 +10,12 @@ Description:
10
10
  Example:
11
11
  `./script/generate migration AddSslFlag`
12
12
 
13
- With 4 existing migrations, this creates the AddSslFlag migration in
14
- db/migrate/005_add_ssl_flag.rb
13
+ If the current date is May 14, 2008 and the current time 09:09:12, this creates the AddSslFlag migration
14
+ db/migrate/20080514090912_add_ssl_flag.rb
15
15
 
16
16
  `./script/generate migration AddTitleBodyToPost title:string body:text published:boolean`
17
17
 
18
- This will create the AddTitleBodyToPost in db/migrate/005_add_title_body_to_post.rb with
18
+ This will create the AddTitleBodyToPost in db/migrate/20080514090912_add_title_body_to_post.rb with
19
19
  this in the Up migration:
20
20
 
21
21
  add_column :posts, :title, :string
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../test_helper'
1
+ require 'test_helper'
2
2
 
3
3
  class <%= class_name %>Test < ActiveSupport::TestCase
4
4
  # Replace this with your real tests.
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../test_helper'
1
+ require 'test_helper'
2
2
 
3
3
  class <%= class_name %>ObserverTest < Test::Unit::TestCase
4
4
  # Replace this with your real tests.
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../test_helper'
1
+ require 'test_helper'
2
2
 
3
3
  class <%= controller_class_name %>ControllerTest < ActionController::TestCase
4
4
  # Replace this with your real tests.
@@ -34,7 +34,7 @@ class ScaffoldGenerator < Rails::Generator::NamedBase
34
34
  m.class_collisions(controller_class_path, "#{controller_class_name}Controller", "#{controller_class_name}Helper")
35
35
  m.class_collisions(class_path, "#{class_name}")
36
36
 
37
- # Controller, helper, views, and test directories.
37
+ # Controller, helper, views, test and stylesheets directories.
38
38
  m.directory(File.join('app/models', class_path))
39
39
  m.directory(File.join('app/controllers', controller_class_path))
40
40
  m.directory(File.join('app/helpers', controller_class_path))
@@ -42,6 +42,7 @@ class ScaffoldGenerator < Rails::Generator::NamedBase
42
42
  m.directory(File.join('app/views/layouts', controller_class_path))
43
43
  m.directory(File.join('test/functional', controller_class_path))
44
44
  m.directory(File.join('test/unit', class_path))
45
+ m.directory(File.join('public/stylesheets', class_path))
45
46
 
46
47
  for action in scaffold_views
47
48
  m.template(
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../test_helper'
1
+ require 'test_helper'
2
2
 
3
3
  class <%= controller_class_name %>ControllerTest < ActionController::TestCase
4
4
  def test_should_get_index
@@ -52,23 +52,3 @@ a:hover { color: #fff; background-color:#000; }
52
52
  list-style: square;
53
53
  }
54
54
 
55
- div.uploadStatus {
56
- margin: 5px;
57
- }
58
-
59
- div.progressBar {
60
- margin: 5px;
61
- }
62
-
63
- div.progressBar div.border {
64
- background-color: #fff;
65
- border: 1px solid gray;
66
- width: 100%;
67
- }
68
-
69
- div.progressBar div.background {
70
- background-color: #333;
71
- height: 18px;
72
- width: 0%;
73
- }
74
-
@@ -1,14 +1,13 @@
1
1
  <h1>Editing <%= singular_name %></h1>
2
2
 
3
- <%%= error_messages_for :<%= singular_name %> %>
4
-
5
3
  <%% form_for(@<%= singular_name %>) do |f| %>
4
+ <%%= f.error_messages %>
5
+
6
6
  <% for attribute in attributes -%>
7
7
  <p>
8
- <b><%= attribute.column.human_name %></b><br />
8
+ <%%= f.label :<%= attribute.name %> %><br />
9
9
  <%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
10
10
  </p>
11
-
12
11
  <% end -%>
13
12
  <p>
14
13
  <%%= f.submit "Update" %>
@@ -1,14 +1,13 @@
1
1
  <h1>New <%= singular_name %></h1>
2
2
 
3
- <%%= error_messages_for :<%= singular_name %> %>
4
-
5
3
  <%% form_for(@<%= singular_name %>) do |f| %>
4
+ <%%= f.error_messages %>
5
+
6
6
  <% for attribute in attributes -%>
7
7
  <p>
8
- <b><%= attribute.column.human_name %></b><br />
8
+ <%%= f.label :<%= attribute.name %> %><br />
9
9
  <%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
10
10
  </p>
11
-
12
11
  <% end -%>
13
12
  <p>
14
13
  <%%= f.submit "Create" %>
@@ -1,3 +1,5 @@
1
+ require 'pathname'
2
+
1
3
  require File.dirname(__FILE__) + '/spec'
2
4
 
3
5
  class Object
@@ -104,8 +106,10 @@ module Rails
104
106
  if defined? ::RAILS_ROOT
105
107
  sources << PathSource.new(:lib, "#{::RAILS_ROOT}/lib/generators")
106
108
  sources << PathSource.new(:vendor, "#{::RAILS_ROOT}/vendor/generators")
107
- sources << PathSource.new(:plugins, "#{::RAILS_ROOT}/vendor/plugins/*/**/generators")
108
- sources << PathSource.new(:plugins, "#{::RAILS_ROOT}/vendor/plugins/*/**/rails_generators")
109
+ Rails.configuration.plugin_paths.each do |path|
110
+ relative_path = Pathname.new(File.expand_path(path)).relative_path_from(Pathname.new(::RAILS_ROOT))
111
+ sources << PathSource.new(:"plugins (#{relative_path})", "#{path}/**/{,rails_}generators")
112
+ end
109
113
  end
110
114
  sources << PathSource.new(:user, "#{Dir.user_home}/.rails/generators")
111
115
  if Object.const_defined?(:Gem)
@@ -136,6 +136,13 @@ module Rails
136
136
  opt
137
137
  end
138
138
  end
139
+ opt.on('-g', '--git', 'Modify files with git. (Note: git must be in path)') do
140
+ options[:git] = `git status`.inject({:new => {}, :modified => {}}) do |opt, e|
141
+ opt[:new][e.chomp[14..-1]] = true if e =~ /new file:/
142
+ opt[:modified][e.chomp[14..-1]] = true if e =~ /modified:/
143
+ opt
144
+ end
145
+ end
139
146
  end
140
147
 
141
148
  end
@@ -43,18 +43,21 @@ module Rails
43
43
 
44
44
  def usage_message
45
45
  usage = "\nInstalled Generators\n"
46
- Rails::Generator::Base.sources.inject({}) do |mem, source|
46
+ Rails::Generator::Base.sources.inject([]) do |mem, source|
47
+ # Using an association list instead of a hash to preserve order,
48
+ # for esthetic reasons more than anything else.
47
49
  label = source.label.to_s.capitalize
48
- mem[label] ||= []
49
- mem[label] |= source.names
50
+ pair = mem.assoc(label)
51
+ mem << (pair = [label, []]) if pair.nil?
52
+ pair[1] |= source.names
50
53
  mem
51
- end.each_pair do |label, names|
54
+ end.each do |label, names|
52
55
  usage << " #{label}: #{names.join(', ')}\n" unless names.empty?
53
56
  end
54
57
 
55
58
  usage << <<end_blurb
56
59
 
57
- More are available at http://rubyonrails.org/show/Generators
60
+ More are available at http://wiki.rubyonrails.org/rails/pages/AvailableGenerators
58
61
  1. Download, for example, login_generator.zip
59
62
  2. Unzip to directory #{Dir.user_home}/.rails/generators/login
60
63
  to use the generator with all your Rails apps
@@ -1,11 +1,10 @@
1
- # A class for creating random secret keys. This class will do its best to create a
2
- # random secret key that's as secure as possible, using whatever methods are
3
- # available on the current platform. For example:
4
- #
5
- # generator = Rails::SecretKeyGenerator("some unique identifier, such as the application name")
6
- # generator.generate_secret # => "f3f1be90053fa851... (some long string)"
7
-
8
1
  module Rails
2
+ # A class for creating random secret keys. This class will do its best to create a
3
+ # random secret key that's as secure as possible, using whatever methods are
4
+ # available on the current platform. For example:
5
+ #
6
+ # generator = Rails::SecretKeyGenerator("some unique identifier, such as the application name")
7
+ # generator.generate_secret # => "f3f1be90053fa851... (some long string)"
9
8
  class SecretKeyGenerator
10
9
  GENERATORS = [ :secure_random, :win32_api, :urandom, :openssl, :prng ].freeze
11
10
 
@@ -77,7 +76,12 @@ module Rails
77
76
  OpenSSL::Random.seed(rand(0).to_s + Time.now.usec.to_s)
78
77
  end
79
78
  data = OpenSSL::BN.rand(2048, -1, false).to_s
80
- return OpenSSL::Digest::SHA512.new(data).hexdigest
79
+
80
+ if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00908000
81
+ OpenSSL::Digest::SHA512.new(data).hexdigest
82
+ else
83
+ generate_secret_with_prng
84
+ end
81
85
  end
82
86
 
83
87
  # Generate a random secret key with /dev/urandom.
@@ -1,5 +1,26 @@
1
+ # Implements the logic behind the rake tasks for annotations like
2
+ #
3
+ # rake notes
4
+ # rake notes:optimize
5
+ #
6
+ # and friends. See <tt>rake -T notes</tt> and <tt>railties/lib/tasks/annotations.rake</tt>.
7
+ #
8
+ # Annotation objects are triplets <tt>:line</tt>, <tt>:tag</tt>, <tt>:text</tt> that
9
+ # represent the line where the annotation lives, its tag, and its text. Note
10
+ # the filename is not stored.
11
+ #
12
+ # Annotations are looked for in comments and modulus whitespace they have to
13
+ # start with the tag optionally followed by a colon. Everything up to the end
14
+ # of the line (or closing ERb comment tag) is considered to be their text.
1
15
  class SourceAnnotationExtractor
2
16
  class Annotation < Struct.new(:line, :tag, :text)
17
+
18
+ # Returns a representation of the annotation that looks like this:
19
+ #
20
+ # [126] [TODO] This algorithm is simple and clearly correct, make it faster.
21
+ #
22
+ # If +options+ has a flag <tt>:tag</tt> the tag is shown as in the example above.
23
+ # Otherwise the string contains just line and text.
3
24
  def to_s(options={})
4
25
  s = "[%3d] " % line
5
26
  s << "[#{tag}] " if options[:tag]
@@ -7,6 +28,12 @@ class SourceAnnotationExtractor
7
28
  end
8
29
  end
9
30
 
31
+ # Prints all annotations with tag +tag+ under the root directories +app+, +lib+,
32
+ # and +test+ (recursively). Only filenames with extension +.builder+, +.rb+,
33
+ # +.rxml+, +.rjs+, +.rhtml+, or +.erb+ are taken into account. The +options+
34
+ # hash is passed to each annotation's +to_s+.
35
+ #
36
+ # This class method is the single entry point for the rake tasks.
10
37
  def self.enumerate(tag, options={})
11
38
  extractor = new(tag)
12
39
  extractor.display(extractor.find, options)
@@ -18,10 +45,18 @@ class SourceAnnotationExtractor
18
45
  @tag = tag
19
46
  end
20
47
 
48
+ # Returns a hash that maps filenames under +dirs+ (recursively) to arrays
49
+ # with their annotations. Only files with annotations are included, and only
50
+ # those with extension +.builder+, +.rb+, +.rxml+, +.rjs+, +.rhtml+, and +.erb+
51
+ # are taken into account.
21
52
  def find(dirs=%w(app lib test))
22
53
  dirs.inject({}) { |h, dir| h.update(find_in(dir)) }
23
54
  end
24
55
 
56
+ # Returns a hash that maps filenames under +dir+ (recursively) to arrays
57
+ # with their annotations. Only files with annotations are included, and only
58
+ # those with extension +.builder+, +.rb+, +.rxml+, +.rjs+, +.rhtml+, and +.erb+
59
+ # are taken into account.
25
60
  def find_in(dir)
26
61
  results = {}
27
62
 
@@ -40,6 +75,9 @@ class SourceAnnotationExtractor
40
75
  results
41
76
  end
42
77
 
78
+ # If +file+ is the filename of a file that contains annotations this method returns
79
+ # a hash with a single entry that maps +file+ to an array of its annotations.
80
+ # Otherwise it returns an empty hash.
43
81
  def extract_annotations_from(file, pattern)
44
82
  lineno = 0
45
83
  result = File.readlines(file).inject([]) do |list, line|
@@ -50,6 +88,8 @@ class SourceAnnotationExtractor
50
88
  result.empty? ? {} : { file => result }
51
89
  end
52
90
 
91
+ # Prints the mapping from filenames to annotations in +results+ ordered by filename.
92
+ # The +options+ hash is passed to each annotation's +to_s+.
53
93
  def display(results, options={})
54
94
  results.keys.sort.each do |file|
55
95
  puts "#{file}:"
@@ -5,13 +5,13 @@ namespace :db do
5
5
  ActiveRecord::Base.configurations.each_value do |config|
6
6
  # Skip entries that don't have a database key, such as the first entry here:
7
7
  #
8
- # defaults: &defaults
9
- # adapter: mysql
8
+ # defaults: &defaults
9
+ # adapter: mysql
10
10
  # username: root
11
- # password:
11
+ # password:
12
12
  # host: localhost
13
- #
14
- # development:
13
+ #
14
+ # development:
15
15
  # database: blog_development
16
16
  # <<: *defaults
17
17
  next unless config['database']
@@ -36,21 +36,29 @@ namespace :db do
36
36
  @charset = ENV['CHARSET'] || 'utf8'
37
37
  @collation = ENV['COLLATION'] || 'utf8_general_ci'
38
38
  begin
39
- ActiveRecord::Base.establish_connection(config.merge({'database' => nil}))
40
- ActiveRecord::Base.connection.create_database(config['database'], {:charset => @charset, :collation => @collation})
39
+ ActiveRecord::Base.establish_connection(config.merge('database' => nil))
40
+ ActiveRecord::Base.connection.create_database(config['database'], :charset => (config['charset'] || @charset), :collation => (config['collation'] || @collation))
41
41
  ActiveRecord::Base.establish_connection(config)
42
42
  rescue
43
- $stderr.puts "Couldn't create database for #{config.inspect}"
43
+ $stderr.puts "Couldn't create database for #{config.inspect}, charset: #{config['charset'] || @charset}, collation: #{config['collation'] || @collation} (if you set the charset manually, make sure you have a matching collation)"
44
44
  end
45
45
  when 'postgresql'
46
- `createdb "#{config['database']}" -E utf8`
46
+ @encoding = config[:encoding] || ENV['CHARSET'] || 'utf8'
47
+ begin
48
+ ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
49
+ ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => @encoding))
50
+ ActiveRecord::Base.establish_connection(config)
51
+ rescue
52
+ $stderr.puts $!, *($!.backtrace)
53
+ $stderr.puts "Couldn't create database for #{config.inspect}"
54
+ end
47
55
  when 'sqlite'
48
56
  `sqlite "#{config['database']}"`
49
57
  when 'sqlite3'
50
58
  `sqlite3 "#{config['database']}"`
51
59
  end
52
60
  else
53
- p "#{config['database']} already exists"
61
+ $stderr.puts "#{config['database']} already exists"
54
62
  end
55
63
  end
56
64
 
@@ -68,7 +76,12 @@ namespace :db do
68
76
 
69
77
  desc 'Drops the database for the current RAILS_ENV'
70
78
  task :drop => :environment do
71
- drop_database(ActiveRecord::Base.configurations[RAILS_ENV || 'development'])
79
+ config = ActiveRecord::Base.configurations[RAILS_ENV || 'development']
80
+ begin
81
+ drop_database(config)
82
+ rescue Exception => e
83
+ puts "Couldn't drop #{config['database']} : #{e.inspect}"
84
+ end
72
85
  end
73
86
 
74
87
  def local_database?(config, &block)
@@ -93,13 +106,29 @@ namespace :db do
93
106
 
94
107
  desc 'Resets your database using your migrations for the current environment'
95
108
  task :reset => ["db:drop", "db:create", "db:migrate"]
109
+
110
+ desc 'Runs the "up" for a given migration VERSION.'
111
+ task :up => :environment do
112
+ version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
113
+ raise "VERSION is required" unless version
114
+ ActiveRecord::Migrator.run(:up, "db/migrate/", version)
115
+ Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
116
+ end
117
+
118
+ desc 'Runs the "down" for a given migration VERSION.'
119
+ task :down => :environment do
120
+ version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
121
+ raise "VERSION is required" unless version
122
+ ActiveRecord::Migrator.run(:down, "db/migrate/", version)
123
+ Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
124
+ end
96
125
  end
97
126
 
98
127
  desc 'Rolls the schema back to the previous version. Specify the number of steps with STEP=n'
99
128
  task :rollback => :environment do
100
129
  step = ENV['STEP'] ? ENV['STEP'].to_i : 1
101
- version = ActiveRecord::Migrator.current_version - step
102
- ActiveRecord::Migrator.migrate('db/migrate/', version)
130
+ ActiveRecord::Migrator.rollback('db/migrate/', step)
131
+ Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
103
132
  end
104
133
 
105
134
  desc 'Drops and recreates the database from db/schema.rb for the current environment.'
@@ -144,7 +173,7 @@ namespace :db do
144
173
  pending_migrations.each do |pending_migration|
145
174
  puts ' %4d %s' % [pending_migration.version, pending_migration.name]
146
175
  end
147
- abort "Run `rake db:migrate` to update your database then try again."
176
+ abort %{Run "rake db:migrate" to update your database then try again.}
148
177
  end
149
178
  end
150
179
  end
@@ -158,21 +187,21 @@ namespace :db do
158
187
  Fixtures.create_fixtures('test/fixtures', File.basename(fixture_file, '.*'))
159
188
  end
160
189
  end
161
-
190
+
162
191
  desc "Search for a fixture given a LABEL or ID."
163
192
  task :identify => :environment do
164
193
  require "active_record/fixtures"
165
194
 
166
195
  label, id = ENV["LABEL"], ENV["ID"]
167
196
  raise "LABEL or ID required" if label.blank? && id.blank?
168
-
197
+
169
198
  puts %Q(The fixture ID for "#{label}" is #{Fixtures.identify(label)}.) if label
170
-
199
+
171
200
  Dir["#{RAILS_ROOT}/test/fixtures/**/*.yml"].each do |file|
172
201
  if data = YAML::load(ERB.new(IO.read(file)).result)
173
202
  data.keys.each do |key|
174
203
  key_id = Fixtures.identify(key)
175
-
204
+
176
205
  if key == label || key_id == id.to_i
177
206
  puts "#{file}: #{key} (#{key_id})"
178
207
  end
@@ -285,14 +314,9 @@ namespace :db do
285
314
  ActiveRecord::Base.establish_connection(:test)
286
315
  ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"])
287
316
  when "postgresql"
288
- ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
289
- ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
290
- ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
291
- enc_option = "-E #{abcs["test"]["encoding"]}" if abcs["test"]["encoding"]
292
-
293
317
  ActiveRecord::Base.clear_active_connections!
294
- `dropdb -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
295
- `createdb #{enc_option} -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
318
+ drop_database(abcs['test'])
319
+ create_database(abcs['test'])
296
320
  when "sqlite","sqlite3"
297
321
  dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"]
298
322
  File.delete(dbfile) if File.exist?(dbfile)
@@ -344,7 +368,8 @@ def drop_database(config)
344
368
  when /^sqlite/
345
369
  FileUtils.rm(File.join(RAILS_ROOT, config['database']))
346
370
  when 'postgresql'
347
- `dropdb "#{config['database']}"`
371
+ ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
372
+ ActiveRecord::Base.connection.drop_database config['database']
348
373
  end
349
374
  end
350
375
 
@@ -359,4 +384,4 @@ end
359
384
 
360
385
  def firebird_db_string(config)
361
386
  FireRuby::Database.db_string_for(config.symbolize_keys)
362
- end
387
+ end