rails 1.2.6 → 2.0.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 (148) hide show
  1. data/CHANGELOG +491 -12
  2. data/MIT-LICENSE +1 -1
  3. data/README +17 -25
  4. data/Rakefile +41 -18
  5. data/bin/about +1 -1
  6. data/bin/console +1 -1
  7. data/bin/destroy +1 -1
  8. data/bin/generate +1 -1
  9. data/bin/performance/request +3 -0
  10. data/bin/plugin +1 -1
  11. data/bin/runner +1 -1
  12. data/bin/server +1 -1
  13. data/builtin/rails_info/rails/info.rb +2 -2
  14. data/configs/apache.conf +1 -1
  15. data/configs/databases/mysql.yml +9 -3
  16. data/configs/databases/postgresql.yml +16 -12
  17. data/configs/initializers/inflections.rb +10 -0
  18. data/configs/initializers/mime_types.rb +5 -0
  19. data/configs/routes.rb +23 -11
  20. data/doc/README_FOR_APP +1 -1
  21. data/environments/boot.rb +95 -26
  22. data/environments/development.rb +2 -5
  23. data/environments/environment.rb +24 -25
  24. data/environments/test.rb +4 -1
  25. data/helpers/application.rb +5 -2
  26. data/helpers/test_helper.rb +10 -0
  27. data/html/422.html +30 -0
  28. data/html/500.html +1 -1
  29. data/html/index.html +2 -2
  30. data/html/javascripts/controls.js +484 -354
  31. data/html/javascripts/dragdrop.js +88 -58
  32. data/html/javascripts/effects.js +396 -364
  33. data/html/javascripts/prototype.js +2817 -1107
  34. data/html/robots.txt +5 -1
  35. data/lib/commands/console.rb +12 -5
  36. data/lib/commands/performance/request.rb +6 -0
  37. data/lib/commands/plugin.rb +15 -10
  38. data/lib/commands/process/spawner.rb +14 -4
  39. data/lib/commands/servers/base.rb +12 -0
  40. data/lib/commands/servers/mongrel.rb +5 -1
  41. data/lib/commands/servers/webrick.rb +14 -7
  42. data/lib/console_app.rb +5 -2
  43. data/lib/console_with_helpers.rb +5 -2
  44. data/lib/dispatcher.rb +3 -151
  45. data/lib/fcgi_handler.rb +79 -81
  46. data/lib/initializer.rb +125 -169
  47. data/lib/rails/plugin.rb +84 -0
  48. data/lib/rails/plugin/loader.rb +150 -0
  49. data/lib/rails/plugin/locator.rb +78 -0
  50. data/lib/rails/version.rb +3 -3
  51. data/lib/rails_generator/base.rb +11 -9
  52. data/lib/rails_generator/commands.rb +20 -10
  53. data/lib/rails_generator/generators/applications/app/USAGE +0 -7
  54. data/lib/rails_generator/generators/applications/app/app_generator.rb +25 -6
  55. data/lib/rails_generator/generators/components/controller/USAGE +11 -12
  56. data/lib/rails_generator/generators/components/controller/controller_generator.rb +2 -2
  57. data/lib/rails_generator/generators/components/controller/templates/functional_test.rb +1 -11
  58. data/lib/rails_generator/generators/components/controller/templates/{view.rhtml → view.html.erb} +0 -0
  59. data/lib/rails_generator/generators/components/integration_test/USAGE +5 -11
  60. data/lib/rails_generator/generators/components/mailer/USAGE +8 -10
  61. data/lib/rails_generator/generators/components/mailer/mailer_generator.rb +3 -3
  62. data/lib/rails_generator/generators/components/mailer/templates/fixture.erb +3 -0
  63. data/lib/rails_generator/generators/components/mailer/templates/fixture.rhtml +0 -3
  64. data/lib/rails_generator/generators/components/mailer/templates/unit_test.rb +8 -24
  65. data/lib/rails_generator/generators/components/mailer/templates/view.erb +3 -0
  66. data/lib/rails_generator/generators/components/mailer/templates/view.rhtml +0 -3
  67. data/lib/rails_generator/generators/components/migration/USAGE +23 -8
  68. data/lib/rails_generator/generators/components/migration/migration_generator.rb +15 -2
  69. data/lib/rails_generator/generators/components/migration/templates/migration.rb +6 -2
  70. data/lib/rails_generator/generators/components/model/USAGE +15 -14
  71. data/lib/rails_generator/generators/components/model/model_generator.rb +10 -3
  72. data/lib/rails_generator/generators/components/model/templates/fixtures.yml +11 -3
  73. data/lib/rails_generator/generators/components/model/templates/migration.rb +4 -1
  74. data/lib/rails_generator/generators/components/model/templates/unit_test.rb +1 -3
  75. data/lib/rails_generator/generators/components/observer/USAGE +5 -7
  76. data/lib/rails_generator/generators/components/observer/templates/unit_test.rb +0 -2
  77. data/lib/rails_generator/generators/components/plugin/USAGE +8 -18
  78. data/lib/rails_generator/generators/components/plugin/plugin_generator.rb +1 -0
  79. data/lib/rails_generator/generators/components/plugin/templates/MIT-LICENSE +20 -0
  80. data/lib/rails_generator/generators/components/plugin/templates/README +10 -1
  81. data/lib/rails_generator/generators/components/plugin/templates/USAGE +1 -1
  82. data/lib/rails_generator/generators/components/plugin/templates/init.rb +1 -1
  83. data/lib/rails_generator/generators/components/plugin/templates/plugin.rb +1 -1
  84. data/lib/rails_generator/generators/components/plugin/templates/tasks.rake +1 -1
  85. data/lib/rails_generator/generators/components/resource/USAGE +23 -0
  86. data/lib/rails_generator/generators/components/resource/resource_generator.rb +13 -15
  87. data/lib/rails_generator/generators/components/resource/templates/controller.rb +1 -1
  88. data/lib/rails_generator/generators/components/resource/templates/functional_test.rb +2 -14
  89. data/lib/rails_generator/generators/components/scaffold/USAGE +24 -31
  90. data/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb +45 -146
  91. data/lib/rails_generator/generators/components/scaffold/templates/controller.rb +64 -37
  92. data/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb +23 -80
  93. data/lib/rails_generator/generators/components/scaffold/templates/{layout.rhtml → layout.html.erb} +0 -0
  94. data/lib/rails_generator/generators/components/scaffold/templates/style.css +1 -1
  95. data/lib/rails_generator/generators/components/{scaffold_resource/templates/view_edit.rhtml → scaffold/templates/view_edit.html.erb} +4 -4
  96. data/lib/rails_generator/generators/components/{scaffold_resource/templates/view_index.rhtml → scaffold/templates/view_index.html.erb} +4 -4
  97. data/lib/rails_generator/generators/components/{scaffold_resource/templates/view_new.rhtml → scaffold/templates/view_new.html.erb} +3 -3
  98. data/lib/rails_generator/generators/components/{scaffold_resource/templates/view_show.rhtml → scaffold/templates/view_show.html.erb} +1 -1
  99. data/lib/rails_generator/generators/components/session_migration/USAGE +6 -11
  100. data/lib/rails_generator/generators/components/session_migration/templates/migration.rb +3 -3
  101. data/lib/rails_generator/lookup.rb +45 -10
  102. data/lib/rails_generator/scripts.rb +6 -3
  103. data/lib/rails_generator/scripts/destroy.rb +23 -0
  104. data/lib/rails_generator/secret_key_generator.rb +160 -0
  105. data/lib/rails_generator/spec.rb +1 -1
  106. data/lib/source_annotation_extractor.rb +62 -0
  107. data/lib/tasks/annotations.rake +23 -0
  108. data/lib/tasks/databases.rake +249 -83
  109. data/lib/tasks/documentation.rake +11 -13
  110. data/lib/tasks/framework.rake +1 -1
  111. data/lib/tasks/rails.rb +1 -1
  112. data/lib/tasks/testing.rake +5 -7
  113. data/lib/test_help.rb +4 -3
  114. data/lib/webrick_server.rb +3 -4
  115. metadata +31 -49
  116. data/bin/breakpointer +0 -3
  117. data/lib/binding_of_caller.rb +0 -85
  118. data/lib/breakpoint.rb +0 -553
  119. data/lib/breakpoint_client.rb +0 -196
  120. data/lib/commands/breakpointer.rb +0 -1
  121. data/lib/rails_generator/generators/components/resource/templates/USAGE +0 -18
  122. data/lib/rails_generator/generators/components/resource/templates/fixtures.yml +0 -11
  123. data/lib/rails_generator/generators/components/resource/templates/migration.rb +0 -13
  124. data/lib/rails_generator/generators/components/resource/templates/model.rb +0 -2
  125. data/lib/rails_generator/generators/components/resource/templates/unit_test.rb +0 -10
  126. data/lib/rails_generator/generators/components/scaffold/templates/form.rhtml +0 -3
  127. data/lib/rails_generator/generators/components/scaffold/templates/form_scaffolding.rhtml +0 -1
  128. data/lib/rails_generator/generators/components/scaffold/templates/view_edit.rhtml +0 -9
  129. data/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml +0 -27
  130. data/lib/rails_generator/generators/components/scaffold/templates/view_new.rhtml +0 -8
  131. data/lib/rails_generator/generators/components/scaffold/templates/view_show.rhtml +0 -8
  132. data/lib/rails_generator/generators/components/scaffold_resource/USAGE +0 -29
  133. data/lib/rails_generator/generators/components/scaffold_resource/scaffold_resource_generator.rb +0 -93
  134. data/lib/rails_generator/generators/components/scaffold_resource/templates/controller.rb +0 -79
  135. data/lib/rails_generator/generators/components/scaffold_resource/templates/fixtures.yml +0 -11
  136. data/lib/rails_generator/generators/components/scaffold_resource/templates/functional_test.rb +0 -57
  137. data/lib/rails_generator/generators/components/scaffold_resource/templates/helper.rb +0 -2
  138. data/lib/rails_generator/generators/components/scaffold_resource/templates/layout.rhtml +0 -17
  139. data/lib/rails_generator/generators/components/scaffold_resource/templates/migration.rb +0 -13
  140. data/lib/rails_generator/generators/components/scaffold_resource/templates/model.rb +0 -2
  141. data/lib/rails_generator/generators/components/scaffold_resource/templates/style.css +0 -74
  142. data/lib/rails_generator/generators/components/scaffold_resource/templates/unit_test.rb +0 -10
  143. data/lib/rails_generator/generators/components/web_service/USAGE +0 -28
  144. data/lib/rails_generator/generators/components/web_service/templates/api_definition.rb +0 -5
  145. data/lib/rails_generator/generators/components/web_service/templates/controller.rb +0 -8
  146. data/lib/rails_generator/generators/components/web_service/templates/functional_test.rb +0 -19
  147. data/lib/rails_generator/generators/components/web_service/web_service_generator.rb +0 -29
  148. data/lib/tasks/pre_namespace_aliases.rake +0 -53
@@ -43,9 +43,12 @@ module Rails
43
43
 
44
44
  def usage_message
45
45
  usage = "\nInstalled Generators\n"
46
- Rails::Generator::Base.sources.each do |source|
46
+ Rails::Generator::Base.sources.inject({}) do |mem, source|
47
47
  label = source.label.to_s.capitalize
48
- names = source.names
48
+ mem[label] ||= []
49
+ mem[label] |= source.names
50
+ mem
51
+ end.each_pair do |label, names|
49
52
  usage << " #{label}: #{names.join(', ')}\n" unless names.empty?
50
53
  end
51
54
 
@@ -59,7 +62,7 @@ end_blurb
59
62
 
60
63
  if Object.const_defined?(:RAILS_ROOT)
61
64
  usage << <<end_blurb
62
- or to #{File.expand_path(RAILS_ROOT)}/generators/login
65
+ or to #{File.expand_path(RAILS_ROOT)}/lib/generators/login
63
66
  to use with this app only.
64
67
  end_blurb
65
68
  end
@@ -3,5 +3,28 @@ require File.dirname(__FILE__) + '/../scripts'
3
3
  module Rails::Generator::Scripts
4
4
  class Destroy < Base
5
5
  mandatory_options :command => :destroy
6
+
7
+ protected
8
+ def usage_message
9
+ usage = "\nInstalled Generators\n"
10
+ Rails::Generator::Base.sources.each do |source|
11
+ label = source.label.to_s.capitalize
12
+ names = source.names
13
+ usage << " #{label}: #{names.join(', ')}\n" unless names.empty?
14
+ end
15
+
16
+ usage << <<end_blurb
17
+
18
+ This script will destroy all files created by the corresponding
19
+ script/generate command. For instance, script/destroy migration CreatePost
20
+ will delete the appropriate ###_create_post.rb file in db/migrate, while
21
+ script/destroy scaffold Post will delete the posts controller and
22
+ views, post model and migration, all associated tests, and the map.resources
23
+ :posts line in config/routes.rb.
24
+
25
+ For instructions on finding new generators, run script/generate
26
+ end_blurb
27
+ return usage
28
+ end
6
29
  end
7
30
  end
@@ -0,0 +1,160 @@
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
+ module Rails
9
+ class SecretKeyGenerator
10
+ GENERATORS = [ :secure_random, :win32_api, :urandom, :openssl, :prng ].freeze
11
+
12
+ def initialize(identifier)
13
+ @identifier = identifier
14
+ end
15
+
16
+ # Generate a random secret key with the best possible method available on
17
+ # the current platform.
18
+ def generate_secret
19
+ generator = GENERATORS.find do |g|
20
+ self.class.send("supports_#{g}?")
21
+ end
22
+ send("generate_secret_with_#{generator}")
23
+ end
24
+
25
+ # Generate a random secret key by using the Win32 API. Raises LoadError
26
+ # if the current platform cannot make use of the Win32 API. Raises
27
+ # SystemCallError if some other error occured.
28
+ def generate_secret_with_win32_api
29
+ # Following code is based on David Garamond's GUID library for Ruby.
30
+ require 'Win32API'
31
+
32
+ crypt_acquire_context = Win32API.new("advapi32", "CryptAcquireContext",
33
+ 'PPPII', 'L')
34
+ crypt_gen_random = Win32API.new("advapi32", "CryptGenRandom",
35
+ 'LIP', 'L')
36
+ crypt_release_context = Win32API.new("advapi32", "CryptReleaseContext",
37
+ 'LI', 'L')
38
+ prov_rsa_full = 1
39
+ crypt_verifycontext = 0xF0000000
40
+
41
+ hProvStr = " " * 4
42
+ if crypt_acquire_context.call(hProvStr, nil, nil, prov_rsa_full,
43
+ crypt_verifycontext) == 0
44
+ raise SystemCallError, "CryptAcquireContext failed: #{lastWin32ErrorMessage}"
45
+ end
46
+ hProv, = hProvStr.unpack('L')
47
+ bytes = " " * 64
48
+ if crypt_gen_random.call(hProv, bytes.size, bytes) == 0
49
+ raise SystemCallError, "CryptGenRandom failed: #{lastWin32ErrorMessage}"
50
+ end
51
+ if crypt_release_context.call(hProv, 0) == 0
52
+ raise SystemCallError, "CryptReleaseContext failed: #{lastWin32ErrorMessage}"
53
+ end
54
+ bytes.unpack("H*")[0]
55
+ end
56
+
57
+ # Generate a random secret key with Ruby 1.9's SecureRandom module.
58
+ # Raises LoadError if the current Ruby version does not support
59
+ # SecureRandom.
60
+ def generate_secret_with_secure_random
61
+ require 'securerandom'
62
+ return SecureRandom.hex(64)
63
+ end
64
+
65
+ # Generate a random secret key with OpenSSL. If OpenSSL is not
66
+ # already loaded, then this method will attempt to load it.
67
+ # LoadError will be raised if that fails.
68
+ def generate_secret_with_openssl
69
+ require 'openssl'
70
+ if !File.exist?("/dev/urandom")
71
+ # OpenSSL transparently seeds the random number generator with
72
+ # data from /dev/urandom. On platforms where that is not
73
+ # available, such as Windows, we have to provide OpenSSL with
74
+ # our own seed. Unfortunately there's no way to provide a
75
+ # secure seed without OS support, so we'll have to do with
76
+ # rand() and Time.now.usec().
77
+ OpenSSL::Random.seed(rand(0).to_s + Time.now.usec.to_s)
78
+ end
79
+ data = OpenSSL::BN.rand(2048, -1, false).to_s
80
+ return OpenSSL::Digest::SHA512.new(data).hexdigest
81
+ end
82
+
83
+ # Generate a random secret key with /dev/urandom.
84
+ # Raises SystemCallError on failure.
85
+ def generate_secret_with_urandom
86
+ return File.read("/dev/urandom", 64).unpack("H*")[0]
87
+ end
88
+
89
+ # Generate a random secret key with Ruby's pseudo random number generator,
90
+ # as well as some environment information.
91
+ #
92
+ # This is the least cryptographically secure way to generate a secret key,
93
+ # and should be avoided whenever possible.
94
+ def generate_secret_with_prng
95
+ require 'digest/sha2'
96
+ sha = Digest::SHA2.new(512)
97
+ now = Time.now
98
+ sha << now.to_s
99
+ sha << String(now.usec)
100
+ sha << String(rand(0))
101
+ sha << String($$)
102
+ sha << @identifier
103
+ return sha.hexdigest
104
+ end
105
+
106
+ private
107
+ def lastWin32ErrorMessage
108
+ # Following code is based on David Garamond's GUID library for Ruby.
109
+ get_last_error = Win32API.new("kernel32", "GetLastError", '', 'L')
110
+ format_message = Win32API.new("kernel32", "FormatMessageA",
111
+ 'LPLLPLPPPPPPPP', 'L')
112
+ format_message_ignore_inserts = 0x00000200
113
+ format_message_from_system = 0x00001000
114
+
115
+ code = get_last_error.call
116
+ msg = "\0" * 1024
117
+ len = format_message.call(format_message_ignore_inserts +
118
+ format_message_from_system, 0,
119
+ code, 0, msg, 1024, nil, nil,
120
+ nil, nil, nil, nil, nil, nil)
121
+ msg[0, len].tr("\r", '').chomp
122
+ end
123
+
124
+ def self.supports_secure_random?
125
+ begin
126
+ require 'securerandom'
127
+ true
128
+ rescue LoadError
129
+ false
130
+ end
131
+ end
132
+
133
+ def self.supports_win32_api?
134
+ return false unless RUBY_PLATFORM =~ /(:?mswin|mingw)/
135
+ begin
136
+ require 'Win32API'
137
+ true
138
+ rescue LoadError
139
+ false
140
+ end
141
+ end
142
+
143
+ def self.supports_urandom?
144
+ File.exists?('/dev/urandom')
145
+ end
146
+
147
+ def self.supports_openssl?
148
+ begin
149
+ require 'openssl'
150
+ true
151
+ rescue LoadError
152
+ false
153
+ end
154
+ end
155
+
156
+ def self.supports_prng?
157
+ true
158
+ end
159
+ end
160
+ end
@@ -2,7 +2,7 @@ module Rails
2
2
  module Generator
3
3
  # A spec knows where a generator was found and how to instantiate it.
4
4
  # Metadata include the generator's name, its base path, and the source
5
- # which yielded it (PathSource, GemSource, etc.)
5
+ # which yielded it (PathSource, GemPathSource, etc.)
6
6
  class Spec
7
7
  attr_reader :name, :path, :source
8
8
 
@@ -0,0 +1,62 @@
1
+ class SourceAnnotationExtractor
2
+ class Annotation < Struct.new(:line, :tag, :text)
3
+ def to_s(options={})
4
+ s = "[%3d] " % line
5
+ s << "[#{tag}] " if options[:tag]
6
+ s << text
7
+ end
8
+ end
9
+
10
+ def self.enumerate(tag, options={})
11
+ extractor = new(tag)
12
+ extractor.display(extractor.find, options)
13
+ end
14
+
15
+ attr_reader :tag
16
+
17
+ def initialize(tag)
18
+ @tag = tag
19
+ end
20
+
21
+ def find(dirs=%w(app lib test))
22
+ dirs.inject({}) { |h, dir| h.update(find_in(dir)) }
23
+ end
24
+
25
+ def find_in(dir)
26
+ results = {}
27
+
28
+ Dir.glob("#{dir}/*") do |item|
29
+ next if File.basename(item)[0] == ?.
30
+
31
+ if File.directory?(item)
32
+ results.update(find_in(item))
33
+ elsif item =~ /\.(builder|(r(?:b|xml|js)))$/
34
+ results.update(extract_annotations_from(item, /#\s*(#{tag}):?\s*(.*)$/))
35
+ elsif item =~ /\.(rhtml|erb)$/
36
+ results.update(extract_annotations_from(item, /<%\s*#\s*(#{tag}):?\s*(.*?)\s*%>/))
37
+ end
38
+ end
39
+
40
+ results
41
+ end
42
+
43
+ def extract_annotations_from(file, pattern)
44
+ lineno = 0
45
+ result = File.readlines(file).inject([]) do |list, line|
46
+ lineno += 1
47
+ next list unless line =~ pattern
48
+ list << Annotation.new(lineno, $1, $2)
49
+ end
50
+ result.empty? ? {} : { file => result }
51
+ end
52
+
53
+ def display(results, options={})
54
+ results.keys.sort.each do |file|
55
+ puts "#{file}:"
56
+ results[file].each do |note|
57
+ puts " * #{note.to_s(options)}"
58
+ end
59
+ puts
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,23 @@
1
+ require 'source_annotation_extractor'
2
+
3
+ desc "Enumerate all annotations"
4
+ task :notes do
5
+ SourceAnnotationExtractor.enumerate "OPTIMIZE|FIXME|TODO", :tag => true
6
+ end
7
+
8
+ namespace :notes do
9
+ desc "Enumerate all OPTIMIZE annotations"
10
+ task :optimize do
11
+ SourceAnnotationExtractor.enumerate "OPTIMIZE"
12
+ end
13
+
14
+ desc "Enumerate all FIXME annotations"
15
+ task :fixme do
16
+ SourceAnnotationExtractor.enumerate "FIXME"
17
+ end
18
+
19
+ desc "Enumerate all TODO annotations"
20
+ task :todo do
21
+ SourceAnnotationExtractor.enumerate "TODO"
22
+ end
23
+ end
@@ -1,10 +1,143 @@
1
1
  namespace :db do
2
- desc "Migrate the database through scripts in db/migrate. Target specific version with VERSION=x"
2
+ namespace :create do
3
+ desc 'Create all the local databases defined in config/database.yml'
4
+ task :all => :environment do
5
+ ActiveRecord::Base.configurations.each_value do |config|
6
+ # Skip entries that don't have a database key, such as the first entry here:
7
+ #
8
+ # defaults: &defaults
9
+ # adapter: mysql
10
+ # username: root
11
+ # password:
12
+ # host: localhost
13
+ #
14
+ # development:
15
+ # database: blog_development
16
+ # <<: *defaults
17
+ next unless config['database']
18
+ # Only connect to local databases
19
+ if config['host'] == 'localhost' || config['host'].blank?
20
+ create_database(config)
21
+ else
22
+ p "This task only creates local databases. #{config['database']} is on a remote host."
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ desc 'Create the database defined in config/database.yml for the current RAILS_ENV'
29
+ task :create => :environment do
30
+ create_database(ActiveRecord::Base.configurations[RAILS_ENV])
31
+ end
32
+
33
+ def create_database(config)
34
+ begin
35
+ ActiveRecord::Base.establish_connection(config)
36
+ ActiveRecord::Base.connection
37
+ rescue
38
+ case config['adapter']
39
+ when 'mysql'
40
+ @charset = ENV['CHARSET'] || 'utf8'
41
+ @collation = ENV['COLLATION'] || 'utf8_general_ci'
42
+ begin
43
+ ActiveRecord::Base.establish_connection(config.merge({'database' => nil}))
44
+ ActiveRecord::Base.connection.create_database(config['database'], {:charset => @charset, :collation => @collation})
45
+ ActiveRecord::Base.establish_connection(config)
46
+ rescue
47
+ $stderr.puts "Couldn't create database for #{config.inspect}"
48
+ end
49
+ when 'postgresql'
50
+ `createdb "#{config['database']}" -E utf8`
51
+ when 'sqlite'
52
+ `sqlite "#{config['database']}"`
53
+ when 'sqlite3'
54
+ `sqlite3 "#{config['database']}"`
55
+ end
56
+ else
57
+ p "#{config['database']} already exists"
58
+ end
59
+ end
60
+
61
+ namespace :drop do
62
+ desc 'Drops all the local databases defined in config/database.yml'
63
+ task :all => :environment do
64
+ ActiveRecord::Base.configurations.each_value do |config|
65
+ # Skip entries that don't have a database key
66
+ next unless config['database']
67
+ # Only connect to local databases
68
+ if config['host'] == 'localhost' || config['host'].blank?
69
+ drop_database(config)
70
+ else
71
+ p "This task only drops local databases. #{config['database']} is on a remote host."
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ desc 'Drops the database for the current RAILS_ENV'
78
+ task :drop => :environment do
79
+ drop_database(ActiveRecord::Base.configurations[RAILS_ENV || 'development'])
80
+ end
81
+
82
+ desc "Migrate the database through scripts in db/migrate. Target specific version with VERSION=x. Turn off output with VERBOSE=false."
3
83
  task :migrate => :environment do
84
+ ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
4
85
  ActiveRecord::Migrator.migrate("db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
5
86
  Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
6
87
  end
7
88
 
89
+ desc 'Rolls the schema back to the previous version. Specify the number of steps with STEP=n'
90
+ task :rollback => :environment do
91
+ step = ENV['STEP'] ? ENV['STEP'].to_i : 1
92
+ version = ActiveRecord::Migrator.current_version - step
93
+ ActiveRecord::Migrator.migrate('db/migrate/', version)
94
+ end
95
+
96
+ desc 'Drops and recreates the database from db/schema.rb for the current environment.'
97
+ task :reset => ['db:drop', 'db:create', 'db:schema:load']
98
+
99
+ desc "Retrieves the charset for the current environment's database"
100
+ task :charset => :environment do
101
+ config = ActiveRecord::Base.configurations[RAILS_ENV || 'development']
102
+ case config['adapter']
103
+ when 'mysql'
104
+ ActiveRecord::Base.establish_connection(config)
105
+ puts ActiveRecord::Base.connection.charset
106
+ else
107
+ puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
108
+ end
109
+ end
110
+
111
+ desc "Retrieves the collation for the current environment's database"
112
+ task :collation => :environment do
113
+ config = ActiveRecord::Base.configurations[RAILS_ENV || 'development']
114
+ case config['adapter']
115
+ when 'mysql'
116
+ ActiveRecord::Base.establish_connection(config)
117
+ puts ActiveRecord::Base.connection.collation
118
+ else
119
+ puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
120
+ end
121
+ end
122
+
123
+ desc "Retrieves the current schema version number"
124
+ task :version => :environment do
125
+ puts "Current version: #{ActiveRecord::Migrator.current_version}"
126
+ end
127
+
128
+ desc "Raises an error if there are pending migrations"
129
+ task :abort_if_pending_migrations => :environment do
130
+ pending_migrations = ActiveRecord::Migrator.new(:up, 'db/migrate').pending_migrations
131
+
132
+ if pending_migrations.any?
133
+ puts "You have #{pending_migrations.size} pending migrations:"
134
+ pending_migrations.each do |pending_migration|
135
+ puts ' %4d %s' % [pending_migration.version, pending_migration.name]
136
+ end
137
+ abort "Run `rake db:migrate` to update your database then try again."
138
+ end
139
+ end
140
+
8
141
  namespace :fixtures do
9
142
  desc "Load fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y"
10
143
  task :load => :environment do
@@ -14,6 +147,28 @@ namespace :db do
14
147
  Fixtures.create_fixtures('test/fixtures', File.basename(fixture_file, '.*'))
15
148
  end
16
149
  end
150
+
151
+ desc "Search for a fixture given a LABEL or ID."
152
+ task :identify => :environment do
153
+ require "active_record/fixtures"
154
+
155
+ label, id = ENV["LABEL"], ENV["ID"]
156
+ raise "LABEL or ID required" if label.blank? && id.blank?
157
+
158
+ puts %Q(The fixture ID for "#{label}" is #{Fixtures.identify(label)}.) if label
159
+
160
+ Dir["#{RAILS_ROOT}/test/fixtures/**/*.yml"].each do |file|
161
+ if data = YAML::load(ERB.new(IO.read(file)).result)
162
+ data.keys.each do |key|
163
+ key_id = Fixtures.identify(key)
164
+
165
+ if key == label || key_id == id.to_i
166
+ puts "#{file}: #{key} (#{key_id})"
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end
17
172
  end
18
173
 
19
174
  namespace :schema do
@@ -37,29 +192,29 @@ namespace :db do
37
192
  task :dump => :environment do
38
193
  abcs = ActiveRecord::Base.configurations
39
194
  case abcs[RAILS_ENV]["adapter"]
40
- when "mysql", "oci", "oracle"
41
- ActiveRecord::Base.establish_connection(abcs[RAILS_ENV])
42
- File.open("db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump }
43
- when "postgresql"
44
- ENV['PGHOST'] = abcs[RAILS_ENV]["host"] if abcs[RAILS_ENV]["host"]
45
- ENV['PGPORT'] = abcs[RAILS_ENV]["port"].to_s if abcs[RAILS_ENV]["port"]
46
- ENV['PGPASSWORD'] = abcs[RAILS_ENV]["password"].to_s if abcs[RAILS_ENV]["password"]
47
- search_path = abcs[RAILS_ENV]["schema_search_path"]
48
- search_path = "--schema=#{search_path}" if search_path
49
- `pg_dump -i -U "#{abcs[RAILS_ENV]["username"]}" -s -x -O -f db/#{RAILS_ENV}_structure.sql #{search_path} #{abcs[RAILS_ENV]["database"]}`
50
- raise "Error dumping database" if $?.exitstatus == 1
51
- when "sqlite", "sqlite3"
52
- dbfile = abcs[RAILS_ENV]["database"] || abcs[RAILS_ENV]["dbfile"]
53
- `#{abcs[RAILS_ENV]["adapter"]} #{dbfile} .schema > db/#{RAILS_ENV}_structure.sql`
54
- when "sqlserver"
55
- `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /f db\\#{RAILS_ENV}_structure.sql /q /A /r`
56
- `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /F db\ /q /A /r`
57
- when "firebird"
58
- set_firebird_env(abcs[RAILS_ENV])
59
- db_string = firebird_db_string(abcs[RAILS_ENV])
60
- sh "isql -a #{db_string} > db/#{RAILS_ENV}_structure.sql"
61
- else
62
- raise "Task not supported by '#{abcs["test"]["adapter"]}'"
195
+ when "mysql", "oci", "oracle"
196
+ ActiveRecord::Base.establish_connection(abcs[RAILS_ENV])
197
+ File.open("db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump }
198
+ when "postgresql"
199
+ ENV['PGHOST'] = abcs[RAILS_ENV]["host"] if abcs[RAILS_ENV]["host"]
200
+ ENV['PGPORT'] = abcs[RAILS_ENV]["port"].to_s if abcs[RAILS_ENV]["port"]
201
+ ENV['PGPASSWORD'] = abcs[RAILS_ENV]["password"].to_s if abcs[RAILS_ENV]["password"]
202
+ search_path = abcs[RAILS_ENV]["schema_search_path"]
203
+ search_path = "--schema=#{search_path}" if search_path
204
+ `pg_dump -i -U "#{abcs[RAILS_ENV]["username"]}" -s -x -O -f db/#{RAILS_ENV}_structure.sql #{search_path} #{abcs[RAILS_ENV]["database"]}`
205
+ raise "Error dumping database" if $?.exitstatus == 1
206
+ when "sqlite", "sqlite3"
207
+ dbfile = abcs[RAILS_ENV]["database"] || abcs[RAILS_ENV]["dbfile"]
208
+ `#{abcs[RAILS_ENV]["adapter"]} #{dbfile} .schema > db/#{RAILS_ENV}_structure.sql`
209
+ when "sqlserver"
210
+ `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /f db\\#{RAILS_ENV}_structure.sql /q /A /r`
211
+ `scptxfr /s #{abcs[RAILS_ENV]["host"]} /d #{abcs[RAILS_ENV]["database"]} /I /F db\ /q /A /r`
212
+ when "firebird"
213
+ set_firebird_env(abcs[RAILS_ENV])
214
+ db_string = firebird_db_string(abcs[RAILS_ENV])
215
+ sh "isql -a #{db_string} > db/#{RAILS_ENV}_structure.sql"
216
+ else
217
+ raise "Task not supported by '#{abcs["test"]["adapter"]}'"
63
218
  end
64
219
 
65
220
  if ActiveRecord::Base.connection.supports_migrations?
@@ -81,33 +236,33 @@ namespace :db do
81
236
  task :clone_structure => [ "db:structure:dump", "db:test:purge" ] do
82
237
  abcs = ActiveRecord::Base.configurations
83
238
  case abcs["test"]["adapter"]
84
- when "mysql"
85
- ActiveRecord::Base.establish_connection(:test)
86
- ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
87
- IO.readlines("db/#{RAILS_ENV}_structure.sql").join.split("\n\n").each do |table|
88
- ActiveRecord::Base.connection.execute(table)
89
- end
90
- when "postgresql"
91
- ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
92
- ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
93
- ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
94
- `psql -U "#{abcs["test"]["username"]}" -f db/#{RAILS_ENV}_structure.sql #{abcs["test"]["database"]}`
95
- when "sqlite", "sqlite3"
96
- dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"]
97
- `#{abcs["test"]["adapter"]} #{dbfile} < db/#{RAILS_ENV}_structure.sql`
98
- when "sqlserver"
99
- `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql`
100
- when "oci", "oracle"
101
- ActiveRecord::Base.establish_connection(:test)
102
- IO.readlines("db/#{RAILS_ENV}_structure.sql").join.split(";\n\n").each do |ddl|
103
- ActiveRecord::Base.connection.execute(ddl)
104
- end
105
- when "firebird"
106
- set_firebird_env(abcs["test"])
107
- db_string = firebird_db_string(abcs["test"])
108
- sh "isql -i db/#{RAILS_ENV}_structure.sql #{db_string}"
109
- else
110
- raise "Task not supported by '#{abcs["test"]["adapter"]}'"
239
+ when "mysql"
240
+ ActiveRecord::Base.establish_connection(:test)
241
+ ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
242
+ IO.readlines("db/#{RAILS_ENV}_structure.sql").join.split("\n\n").each do |table|
243
+ ActiveRecord::Base.connection.execute(table)
244
+ end
245
+ when "postgresql"
246
+ ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
247
+ ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
248
+ ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
249
+ `psql -U "#{abcs["test"]["username"]}" -f db/#{RAILS_ENV}_structure.sql #{abcs["test"]["database"]}`
250
+ when "sqlite", "sqlite3"
251
+ dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"]
252
+ `#{abcs["test"]["adapter"]} #{dbfile} < db/#{RAILS_ENV}_structure.sql`
253
+ when "sqlserver"
254
+ `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql`
255
+ when "oci", "oracle"
256
+ ActiveRecord::Base.establish_connection(:test)
257
+ IO.readlines("db/#{RAILS_ENV}_structure.sql").join.split(";\n\n").each do |ddl|
258
+ ActiveRecord::Base.connection.execute(ddl)
259
+ end
260
+ when "firebird"
261
+ set_firebird_env(abcs["test"])
262
+ db_string = firebird_db_string(abcs["test"])
263
+ sh "isql -i db/#{RAILS_ENV}_structure.sql #{db_string}"
264
+ else
265
+ raise "Task not supported by '#{abcs["test"]["adapter"]}'"
111
266
  end
112
267
  end
113
268
 
@@ -115,40 +270,40 @@ namespace :db do
115
270
  task :purge => :environment do
116
271
  abcs = ActiveRecord::Base.configurations
117
272
  case abcs["test"]["adapter"]
118
- when "mysql"
119
- ActiveRecord::Base.establish_connection(:test)
120
- ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"])
121
- when "postgresql"
122
- ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
123
- ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
124
- ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
125
- enc_option = "-E #{abcs["test"]["encoding"]}" if abcs["test"]["encoding"]
126
-
127
- ActiveRecord::Base.clear_active_connections!
128
- `dropdb -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
129
- `createdb #{enc_option} -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
130
- when "sqlite","sqlite3"
131
- dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"]
132
- File.delete(dbfile) if File.exist?(dbfile)
133
- when "sqlserver"
134
- dropfkscript = "#{abcs["test"]["host"]}.#{abcs["test"]["database"]}.DP1".gsub(/\\/,'-')
135
- `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{dropfkscript}`
136
- `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql`
137
- when "oci", "oracle"
138
- ActiveRecord::Base.establish_connection(:test)
139
- ActiveRecord::Base.connection.structure_drop.split(";\n\n").each do |ddl|
140
- ActiveRecord::Base.connection.execute(ddl)
141
- end
142
- when "firebird"
143
- ActiveRecord::Base.establish_connection(:test)
144
- ActiveRecord::Base.connection.recreate_database!
145
- else
146
- raise "Task not supported by '#{abcs["test"]["adapter"]}'"
273
+ when "mysql"
274
+ ActiveRecord::Base.establish_connection(:test)
275
+ ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"])
276
+ when "postgresql"
277
+ ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
278
+ ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
279
+ ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
280
+ enc_option = "-E #{abcs["test"]["encoding"]}" if abcs["test"]["encoding"]
281
+
282
+ ActiveRecord::Base.clear_active_connections!
283
+ `dropdb -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
284
+ `createdb #{enc_option} -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
285
+ when "sqlite","sqlite3"
286
+ dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"]
287
+ File.delete(dbfile) if File.exist?(dbfile)
288
+ when "sqlserver"
289
+ dropfkscript = "#{abcs["test"]["host"]}.#{abcs["test"]["database"]}.DP1".gsub(/\\/,'-')
290
+ `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{dropfkscript}`
291
+ `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql`
292
+ when "oci", "oracle"
293
+ ActiveRecord::Base.establish_connection(:test)
294
+ ActiveRecord::Base.connection.structure_drop.split(";\n\n").each do |ddl|
295
+ ActiveRecord::Base.connection.execute(ddl)
296
+ end
297
+ when "firebird"
298
+ ActiveRecord::Base.establish_connection(:test)
299
+ ActiveRecord::Base.connection.recreate_database!
300
+ else
301
+ raise "Task not supported by '#{abcs["test"]["adapter"]}'"
147
302
  end
148
303
  end
149
304
 
150
305
  desc 'Prepare the test database and load the schema'
151
- task :prepare => :environment do
306
+ task :prepare => %w(environment db:abort_if_pending_migrations) do
152
307
  if defined?(ActiveRecord::Base) && !ActiveRecord::Base.configurations.blank?
153
308
  Rake::Task[{ :sql => "db:test:clone_structure", :ruby => "db:test:clone" }[ActiveRecord::Base.schema_format]].invoke
154
309
  end
@@ -156,12 +311,12 @@ namespace :db do
156
311
  end
157
312
 
158
313
  namespace :sessions do
159
- desc "Creates a sessions table for use with CGI::Session::ActiveRecordStore"
314
+ desc "Creates a sessions migration for use with CGI::Session::ActiveRecordStore"
160
315
  task :create => :environment do
161
316
  raise "Task unavailable to this database (no migration support)" unless ActiveRecord::Base.connection.supports_migrations?
162
317
  require 'rails_generator'
163
318
  require 'rails_generator/scripts/generate'
164
- Rails::Generator::Scripts::Generate.new.run(["session_migration", ENV["MIGRATION"] || "AddSessions"])
319
+ Rails::Generator::Scripts::Generate.new.run(["session_migration", ENV["MIGRATION"] || "CreateSessions"])
165
320
  end
166
321
 
167
322
  desc "Clear the sessions table"
@@ -173,6 +328,17 @@ namespace :db do
173
328
  end
174
329
  end
175
330
 
331
+ def drop_database(config)
332
+ case config['adapter']
333
+ when 'mysql'
334
+ ActiveRecord::Base.connection.drop_database config['database']
335
+ when /^sqlite/
336
+ FileUtils.rm_f(File.join(RAILS_ROOT, config['database']))
337
+ when 'postgresql'
338
+ `dropdb "#{config['database']}"`
339
+ end
340
+ end
341
+
176
342
  def session_table_name
177
343
  ActiveRecord::Base.pluralize_table_names ? :sessions : :session
178
344
  end