factory_boy 1.0.5 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +68 -31
- data/lib/blank_slate.rb +3 -0
- data/lib/plant.rb +37 -46
- data/lib/query.rb +44 -0
- data/lib/reflection.rb +40 -0
- data/lib/selector.rb +181 -0
- data/lib/setup.rb +13 -22
- data/lib/stubber.rb +164 -21
- data/test/Rakefile.rb +11 -0
- data/test/app/models/address.rb +9 -0
- data/test/app/models/customer.rb +3 -0
- data/test/app/models/profile.rb +2 -0
- data/test/app/models/user.rb +7 -0
- data/test/databases.rake.rb +513 -0
- data/test/db/migrate/20101230223546_create_users.rb.rb +14 -0
- data/test/db/migrate/20101230223547_create_profiles.rb +15 -0
- data/test/db/migrate/20101230223548_create_customers.rb +11 -0
- data/test/db/migrate/20101230223549_create_addresses.rb +13 -0
- data/test/db/schema.rb +41 -0
- data/test/help_test.rb +15 -5
- data/test/plants.rb +5 -5
- data/test/test_basic_queries.rb +36 -0
- data/test/test_plant_definition.rb +129 -0
- data/test/test_plants_ids.rb +16 -0
- data/test/test_queries_on_has_many_association.rb +51 -0
- data/test/test_queries_on_has_one_association.rb +45 -0
- data/test/test_queries_on_model_attributes.rb +59 -0
- data/test/test_queries_with_like.rb +22 -0
- data/test/test_queries_with_limit.rb +28 -0
- data/test/test_queries_with_named_scope.rb +18 -0
- data/test/test_queries_with_order.rb +17 -0
- data/test/test_queries_with_ranges.rb +21 -0
- data/test/test_selector_condition.rb +26 -0
- data/test/test_stubbing.rb +43 -0
- metadata +60 -22
- data/test/models/adress.rb +0 -12
- data/test/models/customer.rb +0 -7
- data/test/models/profile.rb +0 -8
- data/test/models/user.rb +0 -8
- data/test/plant_tests.rb +0 -115
- data/test/test_plant.rb +0 -7
- data/test/test_plant_with_active_support.rb +0 -8
data/lib/setup.rb
CHANGED
@@ -1,32 +1,23 @@
|
|
1
|
-
begin
|
2
|
-
|
3
|
-
rescue LoadError
|
4
|
-
end
|
1
|
+
# begin
|
2
|
+
# require 'mocha' #must put there even if mocha is not used ... else mocha override these aliasings when it's required in test file.
|
3
|
+
# rescue LoadError
|
4
|
+
# end
|
5
5
|
|
6
6
|
module Plant
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
module Run
|
8
|
+
def run(result,&block)
|
9
|
+
Plant.destroy
|
10
|
+
original_run(result,&block)
|
11
|
+
Plant::Stubber.unstubs
|
12
|
+
end
|
12
13
|
end
|
13
|
-
end
|
14
14
|
end
|
15
15
|
|
16
16
|
if defined?(ActiveSupport::TestCase)
|
17
17
|
module ActiveSupport
|
18
18
|
class TestCase < ::Test::Unit::TestCase
|
19
|
-
|
20
|
-
|
19
|
+
alias_method :original_run, :run
|
20
|
+
include Plant::Run
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
24
|
-
module Test
|
25
|
-
module Unit
|
26
|
-
class TestCase
|
27
|
-
alias_method :original_run, :run
|
28
|
-
include Plant::Run
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
23
|
+
end
|
data/lib/stubber.rb
CHANGED
@@ -1,36 +1,179 @@
|
|
1
1
|
module Plant
|
2
2
|
module Stubber
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
4
|
+
@@stubbed = false
|
5
|
+
|
6
|
+
def self.stubs
|
7
|
+
return if @@stubbed
|
8
|
+
stubs_finds
|
9
|
+
stubs_array
|
10
|
+
stubs_where
|
11
|
+
stubs_order
|
12
|
+
stubs_includes
|
13
|
+
stubs_limit
|
14
|
+
stubs_offset
|
15
|
+
@@stubbed = true
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.unstubs
|
19
|
+
return unless @@stubbed
|
20
|
+
unstubs_where
|
21
|
+
unstubs_order
|
22
|
+
unstubs_limit
|
23
|
+
unstubs_offset
|
24
|
+
unstubs_includes
|
25
|
+
unstubs_array
|
26
|
+
unstubs_finds
|
27
|
+
@@stubbed = false
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.stubs_finds
|
31
|
+
active_record_base_eigenclass = class << ActiveRecord::Base; self end
|
32
|
+
|
33
|
+
redefine(active_record_base_eigenclass, :find) do |*args|
|
34
|
+
klass = self.name.constantize
|
35
|
+
case args.first
|
36
|
+
when :first then Plant::Query.find_all(klass).first
|
37
|
+
when :last then Plant::Query.find_all(klass).last
|
38
|
+
when :all then Plant::Query.find_all(klass)
|
39
|
+
else Plant::Query.find_by_ids(klass, args)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
redefine(active_record_base_eigenclass, :find_by_sql) do |*args|
|
44
|
+
Plant::Query.select(self)
|
45
|
+
end
|
46
|
+
|
47
|
+
redefine(active_record_base_eigenclass, :first) do |*args|
|
48
|
+
Plant::Query.find_all(self.name.constantize).first
|
49
|
+
end
|
50
|
+
|
51
|
+
redefine(active_record_base_eigenclass, :all) do |*args|
|
52
|
+
Plant::Query.find_all(self.name.constantize)
|
53
|
+
end
|
54
|
+
|
55
|
+
redefine(active_record_base_eigenclass, :last) do |*args|
|
56
|
+
Plant::Query.find_all(self.name.constantize).last
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.stubs_array
|
62
|
+
redefine(Array, :method_missing) do |method, *args, &block|
|
63
|
+
case method
|
64
|
+
when :order : Plant::Query.order(self, *args)
|
65
|
+
when :limit : Plant::Query.limit(self, *args)
|
66
|
+
when :offset : Plant::Query.offset(self, *args)
|
15
67
|
end
|
16
68
|
end
|
17
69
|
end
|
18
70
|
|
19
|
-
def self.
|
20
|
-
|
21
|
-
|
22
|
-
|
71
|
+
def self.stubs_where
|
72
|
+
redefine(ActiveRecord::QueryMethods, :where) do |opts, *rest|
|
73
|
+
result = original_where(opts, rest)
|
74
|
+
Plant::Query.wheres = result.where_clauses
|
75
|
+
result
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.stubs_order
|
80
|
+
redefine(ActiveRecord::QueryMethods, :order) do |*args|
|
81
|
+
self.all.order(*args)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.stubs_limit
|
86
|
+
redefine(ActiveRecord::QueryMethods, :limit) do |*args|
|
87
|
+
unless self.is_a?Array
|
88
|
+
Plant::Query.find_all(self.name.constantize).limit(*args)
|
89
|
+
else
|
90
|
+
self.all.limit(*args)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.stubs_offset
|
96
|
+
redefine(ActiveRecord::QueryMethods, :offset) do |*args|
|
97
|
+
self.offset(*args)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.stubs_includes
|
102
|
+
redefine(ActiveRecord::QueryMethods, :includes) do |*args|
|
103
|
+
self
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.stubs_associations_collections
|
108
|
+
ActiveRecord::Associations::AssociationCollection.send(:alias_method, :original_method_missing, :method_missing)
|
109
|
+
ActiveRecord::Associations::AssociationCollection.send(:define_method, :method_missing) do |method, *args, &block|
|
110
|
+
eval("@target.#{method}")
|
23
111
|
end
|
24
112
|
end
|
113
|
+
|
114
|
+
def self.stubs_attribute_methods
|
115
|
+
redefine(ActiveRecord::AttributeMethods, :method_missing)
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.unstubs_associations_collections
|
119
|
+
undefine(ActiveRecord::Associations::AssociationCollection, :method_missing)
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.unstubs_attribute_methods
|
123
|
+
undefine(ActiveRecord::AttributeMethods, :method_missing)
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.unstubs_where
|
127
|
+
undefine(ActiveRecord::QueryMethods, :where)
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.unstubs_order
|
131
|
+
undefine(ActiveRecord::QueryMethods, :order)
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.unstubs_limit
|
135
|
+
undefine(ActiveRecord::QueryMethods, :limit)
|
136
|
+
end
|
25
137
|
|
26
|
-
def self.
|
27
|
-
|
138
|
+
def self.unstubs_offset
|
139
|
+
undefine(ActiveRecord::QueryMethods, :offset)
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.unstubs_includes
|
143
|
+
undefine(ActiveRecord::QueryMethods, :includes)
|
28
144
|
end
|
29
145
|
|
30
|
-
def self.
|
31
|
-
|
32
|
-
Plant.all[klass].size == 1 ? Plant.all[klass].first : Plant.all[klass]
|
146
|
+
def self.unstubs_array
|
147
|
+
undefine(Array, :method_missing)
|
33
148
|
end
|
34
149
|
|
150
|
+
def self.unstubs_finds
|
151
|
+
active_record_base_eigenclass = class << ActiveRecord::Base; self end
|
152
|
+
|
153
|
+
undefine(active_record_base_eigenclass, :find)
|
154
|
+
undefine(active_record_base_eigenclass, :find_by_sql)
|
155
|
+
undefine(active_record_base_eigenclass, :first)
|
156
|
+
undefine(active_record_base_eigenclass, :last)
|
157
|
+
undefine(active_record_base_eigenclass, :all)
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
def self.redefine klass, method, &block
|
163
|
+
klass.send(:alias_method, original_method(method), method)
|
164
|
+
klass.send(:define_method, method) do |*params|
|
165
|
+
instance_exec(*params, &block)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def self.undefine klass, method
|
170
|
+
klass.send(:undef_method, method)
|
171
|
+
klass.send(:alias_method, method, original_method(method))
|
172
|
+
end
|
173
|
+
|
174
|
+
def self.original_method method
|
175
|
+
('original_' + method.to_s).to_sym
|
176
|
+
end
|
177
|
+
|
35
178
|
end
|
36
|
-
end
|
179
|
+
end
|
data/test/Rakefile.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rails/all'
|
3
|
+
require 'active_record'
|
4
|
+
require 'rake'
|
5
|
+
require File.join(File.dirname(__FILE__), 'databases.rake.rb')
|
6
|
+
ActiveRecord::Base.establish_connection(
|
7
|
+
:adapter => "sqlite3",
|
8
|
+
:database => "db/test.sqlite3"
|
9
|
+
)
|
10
|
+
ENV['SCHEMA']= File.join(File.dirname(__FILE__), 'db/schema.rb')
|
11
|
+
|
@@ -0,0 +1,513 @@
|
|
1
|
+
namespace :db do
|
2
|
+
task :load_config => :rails_env do
|
3
|
+
require 'active_record'
|
4
|
+
ActiveRecord::Base.configurations = Rails.application.config.database_configuration
|
5
|
+
end
|
6
|
+
|
7
|
+
namespace :create do
|
8
|
+
# desc 'Create all the local databases defined in config/database.yml'
|
9
|
+
task :all => :load_config do
|
10
|
+
ActiveRecord::Base.configurations.each_value do |config|
|
11
|
+
# Skip entries that don't have a database key, such as the first entry here:
|
12
|
+
#
|
13
|
+
# defaults: &defaults
|
14
|
+
# adapter: mysql
|
15
|
+
# username: root
|
16
|
+
# password:
|
17
|
+
# host: localhost
|
18
|
+
#
|
19
|
+
# development:
|
20
|
+
# database: blog_development
|
21
|
+
# <<: *defaults
|
22
|
+
next unless config['database']
|
23
|
+
# Only connect to local databases
|
24
|
+
local_database?(config) { create_database(config) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
desc 'Create the database from config/database.yml for the current Rails.env (use db:create:all to create all dbs in the config)'
|
30
|
+
task :create => :load_config do
|
31
|
+
# Make the test database at the same time as the development one, if it exists
|
32
|
+
if Rails.env.development? && ActiveRecord::Base.configurations['test']
|
33
|
+
create_database(ActiveRecord::Base.configurations['test'])
|
34
|
+
end
|
35
|
+
create_database(ActiveRecord::Base.configurations[Rails.env])
|
36
|
+
end
|
37
|
+
|
38
|
+
def create_database(config)
|
39
|
+
begin
|
40
|
+
if config['adapter'] =~ /sqlite/
|
41
|
+
if File.exist?(config['database'])
|
42
|
+
$stderr.puts "#{config['database']} already exists"
|
43
|
+
else
|
44
|
+
begin
|
45
|
+
# Create the SQLite database
|
46
|
+
ActiveRecord::Base.establish_connection(config)
|
47
|
+
ActiveRecord::Base.connection
|
48
|
+
rescue
|
49
|
+
$stderr.puts $!, *($!.backtrace)
|
50
|
+
$stderr.puts "Couldn't create database for #{config.inspect}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
return # Skip the else clause of begin/rescue
|
54
|
+
else
|
55
|
+
ActiveRecord::Base.establish_connection(config)
|
56
|
+
ActiveRecord::Base.connection
|
57
|
+
end
|
58
|
+
rescue
|
59
|
+
case config['adapter']
|
60
|
+
when /mysql/
|
61
|
+
@charset = ENV['CHARSET'] || 'utf8'
|
62
|
+
@collation = ENV['COLLATION'] || 'utf8_unicode_ci'
|
63
|
+
creation_options = {:charset => (config['charset'] || @charset), :collation => (config['collation'] || @collation)}
|
64
|
+
error_class = config['adapter'] =~ /mysql2/ ? Mysql2::Error : Mysql::Error
|
65
|
+
access_denied_error = 1045
|
66
|
+
begin
|
67
|
+
ActiveRecord::Base.establish_connection(config.merge('database' => nil))
|
68
|
+
ActiveRecord::Base.connection.create_database(config['database'], creation_options)
|
69
|
+
ActiveRecord::Base.establish_connection(config)
|
70
|
+
rescue error_class => sqlerr
|
71
|
+
if sqlerr.errno == access_denied_error
|
72
|
+
print "#{sqlerr.error}. \nPlease provide the root password for your mysql installation\n>"
|
73
|
+
root_password = $stdin.gets.strip
|
74
|
+
grant_statement = "GRANT ALL PRIVILEGES ON #{config['database']}.* " \
|
75
|
+
"TO '#{config['username']}'@'localhost' " \
|
76
|
+
"IDENTIFIED BY '#{config['password']}' WITH GRANT OPTION;"
|
77
|
+
ActiveRecord::Base.establish_connection(config.merge(
|
78
|
+
'database' => nil, 'username' => 'root', 'password' => root_password))
|
79
|
+
ActiveRecord::Base.connection.create_database(config['database'], creation_options)
|
80
|
+
ActiveRecord::Base.connection.execute grant_statement
|
81
|
+
ActiveRecord::Base.establish_connection(config)
|
82
|
+
else
|
83
|
+
$stderr.puts sqlerr.error
|
84
|
+
$stderr.puts "Couldn't create database for #{config.inspect}, charset: #{config['charset'] || @charset}, collation: #{config['collation'] || @collation}"
|
85
|
+
$stderr.puts "(if you set the charset manually, make sure you have a matching collation)" if config['charset']
|
86
|
+
end
|
87
|
+
end
|
88
|
+
when 'postgresql'
|
89
|
+
@encoding = config[:encoding] || ENV['CHARSET'] || 'utf8'
|
90
|
+
begin
|
91
|
+
ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
|
92
|
+
ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => @encoding))
|
93
|
+
ActiveRecord::Base.establish_connection(config)
|
94
|
+
rescue
|
95
|
+
$stderr.puts $!, *($!.backtrace)
|
96
|
+
$stderr.puts "Couldn't create database for #{config.inspect}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
else
|
100
|
+
$stderr.puts "#{config['database']} already exists"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
namespace :drop do
|
105
|
+
# desc 'Drops all the local databases defined in config/database.yml'
|
106
|
+
task :all => :load_config do
|
107
|
+
ActiveRecord::Base.configurations.each_value do |config|
|
108
|
+
# Skip entries that don't have a database key
|
109
|
+
next unless config['database']
|
110
|
+
begin
|
111
|
+
# Only connect to local databases
|
112
|
+
local_database?(config) { drop_database(config) }
|
113
|
+
rescue Exception => e
|
114
|
+
$stderr.puts "Couldn't drop #{config['database']} : #{e.inspect}"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
desc 'Drops the database for the current Rails.env (use db:drop:all to drop all databases)'
|
121
|
+
task :drop do
|
122
|
+
config = ActiveRecord::Base.configurations[Rails.env || 'development']
|
123
|
+
begin
|
124
|
+
drop_database(config)
|
125
|
+
rescue Exception => e
|
126
|
+
$stderr.puts "Couldn't drop #{config['database']} : #{e.inspect}"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def local_database?(config, &block)
|
131
|
+
if %w( 127.0.0.1 localhost ).include?(config['host']) || config['host'].blank?
|
132
|
+
yield
|
133
|
+
else
|
134
|
+
$stderr.puts "This task only modifies local databases. #{config['database']} is on a remote host."
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
desc "Migrate the database (options: VERSION=x, VERBOSE=false)."
|
140
|
+
task :migrate do
|
141
|
+
ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
|
142
|
+
ActiveRecord::Migrator.migrate("db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
|
143
|
+
Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
|
144
|
+
end
|
145
|
+
|
146
|
+
namespace :migrate do
|
147
|
+
# desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
|
148
|
+
task :redo do
|
149
|
+
if ENV["VERSION"]
|
150
|
+
Rake::Task["db:migrate:down"].invoke
|
151
|
+
Rake::Task["db:migrate:up"].invoke
|
152
|
+
else
|
153
|
+
Rake::Task["db:rollback"].invoke
|
154
|
+
Rake::Task["db:migrate"].invoke
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# desc 'Resets your database using your migrations for the current environment'
|
159
|
+
task :reset => ["db:drop", "db:create", "db:migrate"]
|
160
|
+
|
161
|
+
# desc 'Runs the "up" for a given migration VERSION.'
|
162
|
+
task :up do
|
163
|
+
version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
|
164
|
+
raise "VERSION is required" unless version
|
165
|
+
ActiveRecord::Migrator.run(:up, "db/migrate/", version)
|
166
|
+
Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
|
167
|
+
end
|
168
|
+
|
169
|
+
# desc 'Runs the "down" for a given migration VERSION.'
|
170
|
+
task :down do
|
171
|
+
version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
|
172
|
+
raise "VERSION is required" unless version
|
173
|
+
ActiveRecord::Migrator.run(:down, "db/migrate/", version)
|
174
|
+
Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
|
175
|
+
end
|
176
|
+
|
177
|
+
desc "Display status of migrations"
|
178
|
+
task :status do
|
179
|
+
config = ActiveRecord::Base.configurations[Rails.env || 'development']
|
180
|
+
ActiveRecord::Base.establish_connection(config)
|
181
|
+
unless ActiveRecord::Base.connection.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
|
182
|
+
puts 'Schema migrations table does not exist yet.'
|
183
|
+
next # means "return" for rake task
|
184
|
+
end
|
185
|
+
db_list = ActiveRecord::Base.connection.select_values("SELECT version FROM #{ActiveRecord::Migrator.schema_migrations_table_name}")
|
186
|
+
file_list = []
|
187
|
+
Dir.foreach(File.join(Rails.root, 'db', 'migrate')) do |file|
|
188
|
+
# only files matching "20091231235959_some_name.rb" pattern
|
189
|
+
if match_data = /(\d{14})_(.+)\.rb/.match(file)
|
190
|
+
status = db_list.delete(match_data[1]) ? 'up' : 'down'
|
191
|
+
file_list << [status, match_data[1], match_data[2]]
|
192
|
+
end
|
193
|
+
end
|
194
|
+
# output
|
195
|
+
puts "\ndatabase: #{config['database']}\n\n"
|
196
|
+
puts "#{"Status".center(8)} #{"Migration ID".ljust(14)} Migration Name"
|
197
|
+
puts "-" * 50
|
198
|
+
file_list.each do |file|
|
199
|
+
puts "#{file[0].center(8)} #{file[1].ljust(14)} #{file[2].humanize}"
|
200
|
+
end
|
201
|
+
db_list.each do |version|
|
202
|
+
puts "#{'up'.center(8)} #{version.ljust(14)} *** NO FILE ***"
|
203
|
+
end
|
204
|
+
puts
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
desc 'Rolls the schema back to the previous version (specify steps w/ STEP=n).'
|
209
|
+
task :rollback do
|
210
|
+
step = ENV['STEP'] ? ENV['STEP'].to_i : 1
|
211
|
+
ActiveRecord::Migrator.rollback('db/migrate/', step)
|
212
|
+
Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
|
213
|
+
end
|
214
|
+
|
215
|
+
# desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
|
216
|
+
task :forward do
|
217
|
+
step = ENV['STEP'] ? ENV['STEP'].to_i : 1
|
218
|
+
ActiveRecord::Migrator.forward('db/migrate/', step)
|
219
|
+
Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
|
220
|
+
end
|
221
|
+
|
222
|
+
# desc 'Drops and recreates the database from db/schema.rb for the current environment and loads the seeds.'
|
223
|
+
task :reset => [ 'db:drop', 'db:setup' ]
|
224
|
+
|
225
|
+
# desc "Retrieves the charset for the current environment's database"
|
226
|
+
task :charset do
|
227
|
+
config = ActiveRecord::Base.configurations[Rails.env || 'development']
|
228
|
+
case config['adapter']
|
229
|
+
when /mysql/
|
230
|
+
ActiveRecord::Base.establish_connection(config)
|
231
|
+
puts ActiveRecord::Base.connection.charset
|
232
|
+
when 'postgresql'
|
233
|
+
ActiveRecord::Base.establish_connection(config)
|
234
|
+
puts ActiveRecord::Base.connection.encoding
|
235
|
+
when 'sqlite3'
|
236
|
+
ActiveRecord::Base.establish_connection(config)
|
237
|
+
puts ActiveRecord::Base.connection.encoding
|
238
|
+
else
|
239
|
+
$stderr.puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
# desc "Retrieves the collation for the current environment's database"
|
244
|
+
task :collation do
|
245
|
+
config = ActiveRecord::Base.configurations[Rails.env || 'development']
|
246
|
+
case config['adapter']
|
247
|
+
when /mysql/
|
248
|
+
ActiveRecord::Base.establish_connection(config)
|
249
|
+
puts ActiveRecord::Base.connection.collation
|
250
|
+
else
|
251
|
+
$stderr.puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
desc "Retrieves the current schema version number"
|
256
|
+
task :version do
|
257
|
+
puts "Current version: #{ActiveRecord::Migrator.current_version}"
|
258
|
+
end
|
259
|
+
|
260
|
+
# desc "Raises an error if there are pending migrations"
|
261
|
+
task :abort_if_pending_migrations do
|
262
|
+
if defined? ActiveRecord
|
263
|
+
pending_migrations = ActiveRecord::Migrator.new(:up, 'db/migrate').pending_migrations
|
264
|
+
|
265
|
+
if pending_migrations.any?
|
266
|
+
puts "You have #{pending_migrations.size} pending migrations:"
|
267
|
+
pending_migrations.each do |pending_migration|
|
268
|
+
puts ' %4d %s' % [pending_migration.version, pending_migration.name]
|
269
|
+
end
|
270
|
+
abort %{Run "rake db:migrate" to update your database then try again.}
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
desc 'Create the database, load the schema, and initialize with the seed data (use db:reset to also drop the db first)'
|
276
|
+
task :setup => [ 'db:create', 'db:schema:load', 'db:seed' ]
|
277
|
+
|
278
|
+
desc 'Load the seed data from db/seeds.rb'
|
279
|
+
task :seed => 'db:abort_if_pending_migrations' do
|
280
|
+
seed_file = File.join(Rails.root, 'db', 'seeds.rb')
|
281
|
+
load(seed_file) if File.exist?(seed_file)
|
282
|
+
end
|
283
|
+
|
284
|
+
namespace :fixtures do
|
285
|
+
desc "Load fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
|
286
|
+
task :load do
|
287
|
+
require 'active_record/fixtures'
|
288
|
+
|
289
|
+
ActiveRecord::Base.establish_connection(Rails.env)
|
290
|
+
base_dir = ENV['FIXTURES_PATH'] ? File.join(Rails.root, ENV['FIXTURES_PATH']) : File.join(Rails.root, 'test', 'fixtures')
|
291
|
+
fixtures_dir = ENV['FIXTURES_DIR'] ? File.join(base_dir, ENV['FIXTURES_DIR']) : base_dir
|
292
|
+
|
293
|
+
(ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/).map {|f| File.join(fixtures_dir, f) } : Dir["#{fixtures_dir}/**/*.{yml,csv}"]).each do |fixture_file|
|
294
|
+
Fixtures.create_fixtures(fixtures_dir, fixture_file[(fixtures_dir.size + 1)..-5])
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
# desc "Search for a fixture given a LABEL or ID. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
|
299
|
+
task :identify do
|
300
|
+
require 'active_record/fixtures'
|
301
|
+
|
302
|
+
label, id = ENV["LABEL"], ENV["ID"]
|
303
|
+
raise "LABEL or ID required" if label.blank? && id.blank?
|
304
|
+
|
305
|
+
puts %Q(The fixture ID for "#{label}" is #{Fixtures.identify(label)}.) if label
|
306
|
+
|
307
|
+
base_dir = ENV['FIXTURES_PATH'] ? File.join(Rails.root, ENV['FIXTURES_PATH']) : File.join(Rails.root, 'test', 'fixtures')
|
308
|
+
Dir["#{base_dir}/**/*.yml"].each do |file|
|
309
|
+
if data = YAML::load(ERB.new(IO.read(file)).result)
|
310
|
+
data.keys.each do |key|
|
311
|
+
key_id = Fixtures.identify(key)
|
312
|
+
|
313
|
+
if key == label || key_id == id.to_i
|
314
|
+
puts "#{file}: #{key} (#{key_id})"
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
namespace :schema do
|
323
|
+
desc "Create a db/schema.rb file that can be portably used against any DB supported by AR"
|
324
|
+
task :dump do
|
325
|
+
require 'active_record/schema_dumper'
|
326
|
+
File.open(ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb", "w") do |file|
|
327
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
|
328
|
+
end
|
329
|
+
Rake::Task["db:schema:dump"].reenable
|
330
|
+
end
|
331
|
+
|
332
|
+
desc "Load a schema.rb file into the database"
|
333
|
+
task :load do
|
334
|
+
file = ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb"
|
335
|
+
if File.exists?(file)
|
336
|
+
load(file)
|
337
|
+
else
|
338
|
+
abort %{#{file} doesn't exist yet. Run "rake db:migrate" to create it then try again. If you do not intend to use a database, you should instead alter #{Rails.root}/config/boot.rb to limit the frameworks that will be loaded}
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
namespace :structure do
|
344
|
+
desc "Dump the database structure to an SQL file"
|
345
|
+
task :dump do
|
346
|
+
abcs = ActiveRecord::Base.configurations
|
347
|
+
case abcs[Rails.env]["adapter"]
|
348
|
+
when /mysql/, "oci", "oracle"
|
349
|
+
ActiveRecord::Base.establish_connection(abcs[Rails.env])
|
350
|
+
File.open("#{Rails.root}/db/#{Rails.env}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump }
|
351
|
+
when "postgresql"
|
352
|
+
ENV['PGHOST'] = abcs[Rails.env]["host"] if abcs[Rails.env]["host"]
|
353
|
+
ENV['PGPORT'] = abcs[Rails.env]["port"].to_s if abcs[Rails.env]["port"]
|
354
|
+
ENV['PGPASSWORD'] = abcs[Rails.env]["password"].to_s if abcs[Rails.env]["password"]
|
355
|
+
search_path = abcs[Rails.env]["schema_search_path"]
|
356
|
+
unless search_path.blank?
|
357
|
+
search_path = search_path.split(",").map{|search_path| "--schema=#{search_path.strip}" }.join(" ")
|
358
|
+
end
|
359
|
+
`pg_dump -i -U "#{abcs[Rails.env]["username"]}" -s -x -O -f db/#{Rails.env}_structure.sql #{search_path} #{abcs[Rails.env]["database"]}`
|
360
|
+
raise "Error dumping database" if $?.exitstatus == 1
|
361
|
+
when "sqlite", "sqlite3"
|
362
|
+
dbfile = abcs[Rails.env]["database"] || abcs[Rails.env]["dbfile"]
|
363
|
+
`#{abcs[Rails.env]["adapter"]} #{dbfile} .schema > db/#{Rails.env}_structure.sql`
|
364
|
+
when "sqlserver"
|
365
|
+
`scptxfr /s #{abcs[Rails.env]["host"]} /d #{abcs[Rails.env]["database"]} /I /f db\\#{Rails.env}_structure.sql /q /A /r`
|
366
|
+
`scptxfr /s #{abcs[Rails.env]["host"]} /d #{abcs[Rails.env]["database"]} /I /F db\ /q /A /r`
|
367
|
+
when "firebird"
|
368
|
+
set_firebird_env(abcs[Rails.env])
|
369
|
+
db_string = firebird_db_string(abcs[Rails.env])
|
370
|
+
sh "isql -a #{db_string} > #{Rails.root}/db/#{Rails.env}_structure.sql"
|
371
|
+
else
|
372
|
+
raise "Task not supported by '#{abcs["test"]["adapter"]}'"
|
373
|
+
end
|
374
|
+
|
375
|
+
if ActiveRecord::Base.connection.supports_migrations?
|
376
|
+
File.open("#{Rails.root}/db/#{Rails.env}_structure.sql", "a") { |f| f << ActiveRecord::Base.connection.dump_schema_information }
|
377
|
+
end
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
namespace :test do
|
382
|
+
# desc "Recreate the test database from the current schema.rb"
|
383
|
+
task :load do
|
384
|
+
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])
|
385
|
+
ActiveRecord::Schema.verbose = false
|
386
|
+
Rake::Task["db:schema:load"].invoke
|
387
|
+
end
|
388
|
+
|
389
|
+
# desc "Recreate the test database from the current environment's database schema"
|
390
|
+
task :clone => %w(db:schema:dump db:test:load)
|
391
|
+
|
392
|
+
# desc "Recreate the test databases from the development structure"
|
393
|
+
task :clone_structure => [ "db:structure:dump", "db:test:purge" ] do
|
394
|
+
abcs = ActiveRecord::Base.configurations
|
395
|
+
case abcs["test"]["adapter"]
|
396
|
+
when /mysql/
|
397
|
+
ActiveRecord::Base.establish_connection(:test)
|
398
|
+
ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
|
399
|
+
IO.readlines("#{Rails.root}/db/#{Rails.env}_structure.sql").join.split("\n\n").each do |table|
|
400
|
+
ActiveRecord::Base.connection.execute(table)
|
401
|
+
end
|
402
|
+
when "postgresql"
|
403
|
+
ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
|
404
|
+
ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
|
405
|
+
ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
|
406
|
+
`psql -U "#{abcs["test"]["username"]}" -f #{Rails.root}/db/#{Rails.env}_structure.sql #{abcs["test"]["database"]}`
|
407
|
+
when "sqlite", "sqlite3"
|
408
|
+
dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"]
|
409
|
+
`#{abcs["test"]["adapter"]} #{dbfile} < #{Rails.root}/db/#{Rails.env}_structure.sql`
|
410
|
+
when "sqlserver"
|
411
|
+
`osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{Rails.env}_structure.sql`
|
412
|
+
when "oci", "oracle"
|
413
|
+
ActiveRecord::Base.establish_connection(:test)
|
414
|
+
IO.readlines("#{Rails.root}/db/#{Rails.env}_structure.sql").join.split(";\n\n").each do |ddl|
|
415
|
+
ActiveRecord::Base.connection.execute(ddl)
|
416
|
+
end
|
417
|
+
when "firebird"
|
418
|
+
set_firebird_env(abcs["test"])
|
419
|
+
db_string = firebird_db_string(abcs["test"])
|
420
|
+
sh "isql -i #{Rails.root}/db/#{Rails.env}_structure.sql #{db_string}"
|
421
|
+
else
|
422
|
+
raise "Task not supported by '#{abcs["test"]["adapter"]}'"
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
# desc "Empty the test database"
|
427
|
+
task :purge do
|
428
|
+
abcs = ActiveRecord::Base.configurations
|
429
|
+
case abcs["test"]["adapter"]
|
430
|
+
when /mysql/
|
431
|
+
ActiveRecord::Base.establish_connection(:test)
|
432
|
+
ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"], abcs["test"])
|
433
|
+
when "postgresql"
|
434
|
+
ActiveRecord::Base.clear_active_connections!
|
435
|
+
drop_database(abcs['test'])
|
436
|
+
create_database(abcs['test'])
|
437
|
+
when "sqlite","sqlite3"
|
438
|
+
dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"]
|
439
|
+
File.delete(dbfile) if File.exist?(dbfile)
|
440
|
+
when "sqlserver"
|
441
|
+
dropfkscript = "#{abcs["test"]["host"]}.#{abcs["test"]["database"]}.DP1".gsub(/\\/,'-')
|
442
|
+
`osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{dropfkscript}`
|
443
|
+
`osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{Rails.env}_structure.sql`
|
444
|
+
when "oci", "oracle"
|
445
|
+
ActiveRecord::Base.establish_connection(:test)
|
446
|
+
ActiveRecord::Base.connection.structure_drop.split(";\n\n").each do |ddl|
|
447
|
+
ActiveRecord::Base.connection.execute(ddl)
|
448
|
+
end
|
449
|
+
when "firebird"
|
450
|
+
ActiveRecord::Base.establish_connection(:test)
|
451
|
+
ActiveRecord::Base.connection.recreate_database!
|
452
|
+
else
|
453
|
+
raise "Task not supported by '#{abcs["test"]["adapter"]}'"
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
# desc 'Check for pending migrations and load the test schema'
|
458
|
+
task :prepare => 'db:abort_if_pending_migrations' do
|
459
|
+
if defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
|
460
|
+
Rake::Task[{ :sql => "db:test:clone_structure", :ruby => "db:test:load" }[ActiveRecord::Base.schema_format]].invoke
|
461
|
+
end
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
namespace :sessions do
|
466
|
+
# desc "Creates a sessions migration for use with ActiveRecord::SessionStore"
|
467
|
+
task :create do
|
468
|
+
raise "Task unavailable to this database (no migration support)" unless ActiveRecord::Base.connection.supports_migrations?
|
469
|
+
require 'rails/generators'
|
470
|
+
Rails::Generators.configure!
|
471
|
+
require 'rails/generators/rails/session_migration/session_migration_generator'
|
472
|
+
Rails::Generators::SessionMigrationGenerator.start [ ENV["MIGRATION"] || "add_sessions_table" ]
|
473
|
+
end
|
474
|
+
|
475
|
+
# desc "Clear the sessions table"
|
476
|
+
task :clear do
|
477
|
+
ActiveRecord::Base.connection.execute "DELETE FROM #{session_table_name}"
|
478
|
+
end
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
482
|
+
task 'test:prepare' => 'db:test:prepare'
|
483
|
+
|
484
|
+
|
485
|
+
def drop_database(config)
|
486
|
+
case config['adapter']
|
487
|
+
when /mysql/
|
488
|
+
ActiveRecord::Base.establish_connection(config)
|
489
|
+
ActiveRecord::Base.connection.drop_database config['database']
|
490
|
+
when /^sqlite/
|
491
|
+
require 'pathname'
|
492
|
+
path = Pathname.new(config['database'])
|
493
|
+
file = path.absolute? ? path.to_s : File.join(Rails.root, path)
|
494
|
+
|
495
|
+
FileUtils.rm(file)
|
496
|
+
when 'postgresql'
|
497
|
+
ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
|
498
|
+
ActiveRecord::Base.connection.drop_database config['database']
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
def session_table_name
|
503
|
+
ActiveRecord::SessionStore::Session.table_name
|
504
|
+
end
|
505
|
+
|
506
|
+
def set_firebird_env(config)
|
507
|
+
ENV["ISC_USER"] = config["username"].to_s if config["username"]
|
508
|
+
ENV["ISC_PASSWORD"] = config["password"].to_s if config["password"]
|
509
|
+
end
|
510
|
+
|
511
|
+
def firebird_db_string(config)
|
512
|
+
FireRuby::Database.db_string_for(config.symbolize_keys)
|
513
|
+
end
|