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.
Files changed (42) hide show
  1. data/README.rdoc +68 -31
  2. data/lib/blank_slate.rb +3 -0
  3. data/lib/plant.rb +37 -46
  4. data/lib/query.rb +44 -0
  5. data/lib/reflection.rb +40 -0
  6. data/lib/selector.rb +181 -0
  7. data/lib/setup.rb +13 -22
  8. data/lib/stubber.rb +164 -21
  9. data/test/Rakefile.rb +11 -0
  10. data/test/app/models/address.rb +9 -0
  11. data/test/app/models/customer.rb +3 -0
  12. data/test/app/models/profile.rb +2 -0
  13. data/test/app/models/user.rb +7 -0
  14. data/test/databases.rake.rb +513 -0
  15. data/test/db/migrate/20101230223546_create_users.rb.rb +14 -0
  16. data/test/db/migrate/20101230223547_create_profiles.rb +15 -0
  17. data/test/db/migrate/20101230223548_create_customers.rb +11 -0
  18. data/test/db/migrate/20101230223549_create_addresses.rb +13 -0
  19. data/test/db/schema.rb +41 -0
  20. data/test/help_test.rb +15 -5
  21. data/test/plants.rb +5 -5
  22. data/test/test_basic_queries.rb +36 -0
  23. data/test/test_plant_definition.rb +129 -0
  24. data/test/test_plants_ids.rb +16 -0
  25. data/test/test_queries_on_has_many_association.rb +51 -0
  26. data/test/test_queries_on_has_one_association.rb +45 -0
  27. data/test/test_queries_on_model_attributes.rb +59 -0
  28. data/test/test_queries_with_like.rb +22 -0
  29. data/test/test_queries_with_limit.rb +28 -0
  30. data/test/test_queries_with_named_scope.rb +18 -0
  31. data/test/test_queries_with_order.rb +17 -0
  32. data/test/test_queries_with_ranges.rb +21 -0
  33. data/test/test_selector_condition.rb +26 -0
  34. data/test/test_stubbing.rb +43 -0
  35. metadata +60 -22
  36. data/test/models/adress.rb +0 -12
  37. data/test/models/customer.rb +0 -7
  38. data/test/models/profile.rb +0 -8
  39. data/test/models/user.rb +0 -8
  40. data/test/plant_tests.rb +0 -115
  41. data/test/test_plant.rb +0 -7
  42. data/test/test_plant_with_active_support.rb +0 -8
data/lib/setup.rb CHANGED
@@ -1,32 +1,23 @@
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
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
- module Run
8
- def run(result,&block)
9
- Plant.destroy
10
- original_run(result,&block)
11
- Plant.unstub_find_for_each_class
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
- alias_method :original_run, :run
20
- include Plant::Run
19
+ alias_method :original_run, :run
20
+ include Plant::Run
21
21
  end
22
22
  end
23
- else
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
- def self.stubs_find klass
5
- class << klass
6
- alias_method :original_find, :find
7
-
8
- def find *args
9
- case args.first
10
- when :first then Plant::Stubber.find_all(self.name.constantize).first
11
- when :last then Plant::Stubber.find_all(self.name.constantize).last
12
- when :all then Plant::Stubber.find_all(self.name.constantize)
13
- else Plant::Stubber.find(self.name.constantize)
14
- end
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.unstubs_find_for klass
20
- class << klass
21
- undef_method :find
22
- alias_method :find, :original_find
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.find_all klass
27
- Plant.all[klass] || []
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.find klass
31
- return nil unless Plant.all[klass]
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,9 @@
1
+ class Address < ActiveRecord::Base
2
+
3
+ belongs_to :user
4
+
5
+ def self.find
6
+ "original_find"
7
+ end
8
+
9
+ end
@@ -0,0 +1,3 @@
1
+ class Customer < ActiveRecord::Base
2
+
3
+ end
@@ -0,0 +1,2 @@
1
+ class Profile < ActiveRecord::Base
2
+ end
@@ -0,0 +1,7 @@
1
+ class User < ActiveRecord::Base
2
+ scope :albert, :conditions => { :name => 'Albert' }
3
+
4
+ has_one :profile
5
+ has_many :addresses
6
+
7
+ end
@@ -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