reactive-activerecord 0.2.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/LICENSE +21 -0
- data/Manifest +26 -0
- data/README +26 -0
- data/Rakefile +5 -0
- data/lib/activerecord_meta_model.rb +111 -0
- data/lib/reactive-activerecord.rb +29 -0
- data/lib/tasks/databases.rake +349 -0
- data/reactive_app_generators/activerecord/USAGE +2 -0
- data/reactive_app_generators/activerecord/activerecord_generator.rb +84 -0
- data/reactive_app_generators/activerecord/templates/frontbase.yml +28 -0
- data/reactive_app_generators/activerecord/templates/ibm_db.yml +62 -0
- data/reactive_app_generators/activerecord/templates/mysql.yml +57 -0
- data/reactive_app_generators/activerecord/templates/oracle.yml +39 -0
- data/reactive_app_generators/activerecord/templates/postgresql.yml +51 -0
- data/reactive_app_generators/activerecord/templates/sqlite2.yml +19 -0
- data/reactive_app_generators/activerecord/templates/sqlite3.yml +22 -0
- data/reactive_generators/model/USAGE +27 -0
- data/reactive_generators/model/model_generator.rb +56 -0
- data/reactive_generators/model/templates/fixtures.yml +19 -0
- data/reactive_generators/model/templates/migration.rb +16 -0
- data/reactive_generators/model/templates/model.rb +2 -0
- data/reactive_generators/model/templates/unit_test.rb +8 -0
- data/reactive_generators/resource/USAGE +27 -0
- data/reactive_generators/resource/resource_generator.rb +39 -0
- data/reactive_generators/resource/templates/controller.rb +51 -0
- data/reactive_generators/resource/templates/helper.rb +2 -0
- metadata +105 -0
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2008-2009 Pascal Hurni
|
2
|
+
Copyright (c) 2004-2007 David Heinemeier Hansson
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
LICENSE
|
2
|
+
Manifest
|
3
|
+
README
|
4
|
+
Rakefile
|
5
|
+
lib/activerecord_meta_model.rb
|
6
|
+
lib/reactive-activerecord.rb
|
7
|
+
lib/tasks/databases.rake
|
8
|
+
reactive_app_generators/activerecord/USAGE
|
9
|
+
reactive_app_generators/activerecord/activerecord_generator.rb
|
10
|
+
reactive_app_generators/activerecord/templates/frontbase.yml
|
11
|
+
reactive_app_generators/activerecord/templates/ibm_db.yml
|
12
|
+
reactive_app_generators/activerecord/templates/mysql.yml
|
13
|
+
reactive_app_generators/activerecord/templates/oracle.yml
|
14
|
+
reactive_app_generators/activerecord/templates/postgresql.yml
|
15
|
+
reactive_app_generators/activerecord/templates/sqlite2.yml
|
16
|
+
reactive_app_generators/activerecord/templates/sqlite3.yml
|
17
|
+
reactive_generators/model/USAGE
|
18
|
+
reactive_generators/model/model_generator.rb
|
19
|
+
reactive_generators/model/templates/fixtures.yml
|
20
|
+
reactive_generators/model/templates/migration.rb
|
21
|
+
reactive_generators/model/templates/model.rb
|
22
|
+
reactive_generators/model/templates/unit_test.rb
|
23
|
+
reactive_generators/resource/USAGE
|
24
|
+
reactive_generators/resource/resource_generator.rb
|
25
|
+
reactive_generators/resource/templates/controller.rb
|
26
|
+
reactive_generators/resource/templates/helper.rb
|
data/README
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
== reactive-activerecord
|
2
|
+
|
3
|
+
Reactive plugin that provides ActiveRecord support for Models.
|
4
|
+
|
5
|
+
Version:: 0.2.0
|
6
|
+
Author:: Pascal Hurni
|
7
|
+
Email:: phi@ruby-reactive.org
|
8
|
+
Homepage:: http://www.ruby-reactive.org
|
9
|
+
|
10
|
+
== Description
|
11
|
+
|
12
|
+
Provides ActiveRecord for the ORM used by the reactive-mvc plugin.
|
13
|
+
|
14
|
+
== Configuration
|
15
|
+
|
16
|
+
gem_requirement:: A string specifying the activerecord gem version requirement.
|
17
|
+
Defaults to none.
|
18
|
+
logger:: The logger instance used by activerecord.
|
19
|
+
Defaults to Reactive configuration#logger.
|
20
|
+
config_file:: YAML configuration file for the database connections.
|
21
|
+
Defaults to 'config/database.yml'
|
22
|
+
|
23
|
+
== Requirements
|
24
|
+
|
25
|
+
* reactive-core >= 0.2.0
|
26
|
+
* activerecord >= 2.0.0
|
data/Rakefile
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
module Reactive
|
2
|
+
module MetaModel
|
3
|
+
module ActiveRecord
|
4
|
+
def self.included(base)
|
5
|
+
def base.meta
|
6
|
+
@meta ||= ActiveRecordModel.new(self)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def supra
|
11
|
+
@supra ||= ActiveRecordInstance.new(self)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class ActiveRecordInstance
|
16
|
+
delegate :new_record?, :changed?, :mark_for_destruction, :marked_for_destruction?,
|
17
|
+
:valid?, :errors,
|
18
|
+
:to => :@instance
|
19
|
+
|
20
|
+
def initialize(instance)
|
21
|
+
@instance = instance
|
22
|
+
end
|
23
|
+
|
24
|
+
# reload without hitting the database
|
25
|
+
# does not trigger observers
|
26
|
+
def revert
|
27
|
+
@instance.instance_variable_set(:@marked_for_destruction, false)
|
28
|
+
@instance.changes.each {|attr, (old,new)| @instance.send("#{attr}=", old) }
|
29
|
+
@instance.send(:changed_attributes).clear
|
30
|
+
@instance.class.meta.has_manys.each {|assoc_meta| @instance.send(assoc_meta.name).each {|record| record.supra.revert} }
|
31
|
+
@instance.class.meta.has_ones.each {|assoc_meta| revert_assoc(@instance.send(assoc_meta.name)) }
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def revert_assoc(assoc)
|
37
|
+
assoc && assoc.supra.revert
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
class ActiveRecordModel < Model
|
43
|
+
|
44
|
+
class Column < Column
|
45
|
+
def initialize(column)
|
46
|
+
@name, @type, @primary = column.name.to_sym, column.type, column.primary
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class Association < Association
|
51
|
+
def initialize(association)
|
52
|
+
@name, @kind, @klass = association.name.to_sym, association.macro, association.klass
|
53
|
+
@polymorphic = association.options[:polymorphic]
|
54
|
+
# TODO: has_* don't have attributes in their table, so avoid these attributes (they may clash with real attributes!)
|
55
|
+
@columns = [
|
56
|
+
association.primary_key_name,
|
57
|
+
association.options[:foreign_type],
|
58
|
+
association.counter_cache_column
|
59
|
+
].compact.map(&:to_sym)
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
attr_reader :name
|
65
|
+
|
66
|
+
delegate :add_observer, :delete_observer, :to => :@model
|
67
|
+
|
68
|
+
def initialize(model)
|
69
|
+
@model = model
|
70
|
+
@name = model.to_s.demodulize.underscore
|
71
|
+
end
|
72
|
+
|
73
|
+
def has_manys
|
74
|
+
@has_manys ||= @model.reflect_on_all_associations(:has_many).map {|association| Association.new(association)}
|
75
|
+
end
|
76
|
+
|
77
|
+
def has_ones
|
78
|
+
@has_ones ||= @model.reflect_on_all_associations(:has_one).map {|association| Association.new(association)}
|
79
|
+
end
|
80
|
+
|
81
|
+
def belong_tos
|
82
|
+
@belong_tos ||= @model.reflect_on_all_associations(:belongs_to).map {|association| Association.new(association)}
|
83
|
+
end
|
84
|
+
|
85
|
+
def associations
|
86
|
+
belong_tos + has_ones + has_manys
|
87
|
+
end
|
88
|
+
|
89
|
+
def columns
|
90
|
+
@columns ||= @model.columns.map {|column| Column.new(column)}
|
91
|
+
end
|
92
|
+
|
93
|
+
def attributes
|
94
|
+
columns + associations
|
95
|
+
end
|
96
|
+
|
97
|
+
def attribute(name)
|
98
|
+
attributes.find {|attribute| attribute.name == name.to_sym}
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
=begin
|
106
|
+
self.nested_resources = []
|
107
|
+
self.has_manys = []
|
108
|
+
self.has_ones = []
|
109
|
+
self.belong_tos = []
|
110
|
+
self.columns = []
|
111
|
+
=end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
Reactive::Initializer.configure :activerecord do
|
2
|
+
Reactive.configuration.reactive_activerecord.config_file ||= Reactive.path_for(:config, 'database.yml')
|
3
|
+
Reactive.configuration.paths[:db] = Reactive.configuration.reactive_activerecord.db_path || Reactive.path_for("db")
|
4
|
+
end
|
5
|
+
|
6
|
+
# Also called from the ModelGenerator
|
7
|
+
def reactive_activerecord_init # :nodoc:
|
8
|
+
gem 'activerecord', Reactive.configuration.reactive_activerecord.gem_requirement || '>=0'
|
9
|
+
require 'activerecord'
|
10
|
+
|
11
|
+
(Reactive.configuration.reactive_activerecord.base || {}).each do |name, value|
|
12
|
+
ActiveRecord::Base.send("#{name}=", value)
|
13
|
+
end
|
14
|
+
|
15
|
+
ActiveRecord::Base.logger ||= Reactive.logger
|
16
|
+
ActiveRecord::Base.configurations = YAML::load(IO.read(Reactive.configuration.reactive_activerecord.config_file))
|
17
|
+
ActiveRecord::Base.establish_connection(Reactive.configuration.environment)
|
18
|
+
end
|
19
|
+
|
20
|
+
Reactive::Initializer.init :activerecord do
|
21
|
+
reactive_activerecord_init
|
22
|
+
|
23
|
+
require(File.join(File.dirname(__FILE__), 'activerecord_meta_model'))
|
24
|
+
ActiveRecord::Base.send(:include, Reactive::MetaModel::ActiveRecord)
|
25
|
+
end
|
26
|
+
|
27
|
+
Reactive::Initializer.after_init :activerecord do
|
28
|
+
ActiveRecord::Base.instantiate_observers
|
29
|
+
end
|
@@ -0,0 +1,349 @@
|
|
1
|
+
namespace :db do
|
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 %w( 127.0.0.1 localhost ).include?(config['host']) || 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 environment'
|
29
|
+
task :create => :environment do
|
30
|
+
create_database(ActiveRecord::Base.configurations[Reactive.configuration.environment])
|
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 environment'
|
78
|
+
task :drop => :environment do
|
79
|
+
drop_database(ActiveRecord::Base.configurations[Reactive.configuration.environment || '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."
|
83
|
+
task :migrate => :environment do
|
84
|
+
ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
|
85
|
+
ActiveRecord::Migrator.migrate(Reactive.relative_path_for(:db, "migrate/"), ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
|
86
|
+
Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
|
87
|
+
end
|
88
|
+
|
89
|
+
namespace :migrate do
|
90
|
+
desc 'Rollbacks the database one migration and re migrate up. If you want to rollback more than one step, define STEP=x'
|
91
|
+
task :redo => [ 'db:rollback', 'db:migrate' ]
|
92
|
+
|
93
|
+
desc 'Resets your database using your migrations for the current environment'
|
94
|
+
task :reset => ["db:drop", "db:create", "db:migrate"]
|
95
|
+
end
|
96
|
+
|
97
|
+
desc 'Rolls the schema back to the previous version. Specify the number of steps with STEP=n'
|
98
|
+
task :rollback => :environment do
|
99
|
+
step = ENV['STEP'] ? ENV['STEP'].to_i : 1
|
100
|
+
version = ActiveRecord::Migrator.current_version - step
|
101
|
+
ActiveRecord::Migrator.migrate('db/migrate/', version)
|
102
|
+
end
|
103
|
+
|
104
|
+
desc 'Drops and recreates the database from db/schema.rb for the current environment.'
|
105
|
+
task :reset => ['db:drop', 'db:create', 'db:schema:load']
|
106
|
+
|
107
|
+
desc "Retrieves the charset for the current environment's database"
|
108
|
+
task :charset => :environment do
|
109
|
+
config = ActiveRecord::Base.configurations[Reactive.configuration.environment || 'development']
|
110
|
+
case config['adapter']
|
111
|
+
when 'mysql'
|
112
|
+
ActiveRecord::Base.establish_connection(config)
|
113
|
+
puts ActiveRecord::Base.connection.charset
|
114
|
+
else
|
115
|
+
puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
desc "Retrieves the collation for the current environment's database"
|
120
|
+
task :collation => :environment do
|
121
|
+
config = ActiveRecord::Base.configurations[Reactive.configuration.environment || 'development']
|
122
|
+
case config['adapter']
|
123
|
+
when 'mysql'
|
124
|
+
ActiveRecord::Base.establish_connection(config)
|
125
|
+
puts ActiveRecord::Base.connection.collation
|
126
|
+
else
|
127
|
+
puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
desc "Retrieves the current schema version number"
|
132
|
+
task :version => :environment do
|
133
|
+
puts "Current version: #{ActiveRecord::Migrator.current_version}"
|
134
|
+
end
|
135
|
+
|
136
|
+
desc "Raises an error if there are pending migrations"
|
137
|
+
task :abort_if_pending_migrations => :environment do
|
138
|
+
if defined? ActiveRecord
|
139
|
+
pending_migrations = ActiveRecord::Migrator.new(:up, 'db/migrate').pending_migrations
|
140
|
+
|
141
|
+
if pending_migrations.any?
|
142
|
+
puts "You have #{pending_migrations.size} pending migrations:"
|
143
|
+
pending_migrations.each do |pending_migration|
|
144
|
+
puts ' %4d %s' % [pending_migration.version, pending_migration.name]
|
145
|
+
end
|
146
|
+
abort "Run `rake db:migrate` to update your database then try again."
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
namespace :fixtures do
|
152
|
+
desc "Load fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y"
|
153
|
+
task :load => :environment do
|
154
|
+
require 'active_record/fixtures'
|
155
|
+
ActiveRecord::Base.establish_connection(Reactive.configuration.environment.to_sym)
|
156
|
+
(ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(Reactive.path_for(:test, 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
|
157
|
+
Fixtures.create_fixtures('test/fixtures', File.basename(fixture_file, '.*'))
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
desc "Search for a fixture given a LABEL or ID."
|
162
|
+
task :identify => :environment do
|
163
|
+
require "active_record/fixtures"
|
164
|
+
|
165
|
+
label, id = ENV["LABEL"], ENV["ID"]
|
166
|
+
raise "LABEL or ID required" if label.blank? && id.blank?
|
167
|
+
|
168
|
+
puts %Q(The fixture ID for "#{label}" is #{Fixtures.identify(label)}.) if label
|
169
|
+
|
170
|
+
Dir[Reactive.path_for(:test, 'fixtures/**/*.yml')].each do |file|
|
171
|
+
if data = YAML::load(ERB.new(IO.read(file)).result)
|
172
|
+
data.keys.each do |key|
|
173
|
+
key_id = Fixtures.identify(key)
|
174
|
+
|
175
|
+
if key == label || key_id == id.to_i
|
176
|
+
puts "#{file}: #{key} (#{key_id})"
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
namespace :schema do
|
185
|
+
desc "Create a db/schema.rb file that can be portably used against any DB supported by AR"
|
186
|
+
task :dump => :environment do
|
187
|
+
require 'active_record/schema_dumper'
|
188
|
+
File.open(ENV['SCHEMA'] || Reactive.path_for(:db, "schema.rb"), "w") do |file|
|
189
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
desc "Load a schema.rb file into the database"
|
194
|
+
task :load => :environment do
|
195
|
+
file = ENV['SCHEMA'] || Reactive.path_for(:db, "schema.rb")
|
196
|
+
load(file)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
namespace :structure do
|
201
|
+
desc "Dump the database structure to a SQL file"
|
202
|
+
task :dump => :environment do
|
203
|
+
env = Reactive.configuration.environment
|
204
|
+
abcs = ActiveRecord::Base.configurations
|
205
|
+
case abcs[env]["adapter"]
|
206
|
+
when "mysql", "oci", "oracle"
|
207
|
+
ActiveRecord::Base.establish_connection(abcs[env])
|
208
|
+
File.open(Reactive.path_for(:db, "#{env}_structure.sql"), "w+") { |f| f << ActiveRecord::Base.connection.structure_dump }
|
209
|
+
when "postgresql"
|
210
|
+
ENV['PGHOST'] = abcs[env]["host"] if abcs[env]["host"]
|
211
|
+
ENV['PGPORT'] = abcs[env]["port"].to_s if abcs[env]["port"]
|
212
|
+
ENV['PGPASSWORD'] = abcs[env]["password"].to_s if abcs[env]["password"]
|
213
|
+
search_path = abcs[env]["schema_search_path"]
|
214
|
+
search_path = "--schema=#{search_path}" if search_path
|
215
|
+
`pg_dump -i -U "#{abcs[env]["username"]}" -s -x -O -f db/#{env}_structure.sql #{search_path} #{abcs[env]["database"]}`
|
216
|
+
raise "Error dumping database" if $?.exitstatus == 1
|
217
|
+
when "sqlite", "sqlite3"
|
218
|
+
dbfile = abcs[env]["database"] || abcs[env]["dbfile"]
|
219
|
+
`#{abcs[env]["adapter"]} #{dbfile} .schema > db/#{env}_structure.sql`
|
220
|
+
when "sqlserver"
|
221
|
+
`scptxfr /s #{abcs[env]["host"]} /d #{abcs[env]["database"]} /I /f db\\#{env}_structure.sql /q /A /r`
|
222
|
+
`scptxfr /s #{abcs[env]["host"]} /d #{abcs[env]["database"]} /I /F db\ /q /A /r`
|
223
|
+
when "firebird"
|
224
|
+
set_firebird_env(abcs[env])
|
225
|
+
db_string = firebird_db_string(abcs[env])
|
226
|
+
sh "isql -a #{db_string} > db/#{env}_structure.sql"
|
227
|
+
else
|
228
|
+
raise "Task not supported by '#{abcs["test"]["adapter"]}'"
|
229
|
+
end
|
230
|
+
|
231
|
+
if ActiveRecord::Base.connection.supports_migrations?
|
232
|
+
File.open(Reactive.path_for(:db, "#{env}_structure.sql"), "a") { |f| f << ActiveRecord::Base.connection.dump_schema_information }
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
namespace :test do
|
238
|
+
desc "Recreate the test database from the current environment's database schema"
|
239
|
+
task :clone => %w(db:schema:dump db:test:purge) do
|
240
|
+
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])
|
241
|
+
ActiveRecord::Schema.verbose = false
|
242
|
+
Rake::Task["db:schema:load"].invoke
|
243
|
+
end
|
244
|
+
|
245
|
+
|
246
|
+
desc "Recreate the test databases from the development structure"
|
247
|
+
task :clone_structure => [ "db:structure:dump", "db:test:purge" ] do
|
248
|
+
env = Reactive.configuration.environment
|
249
|
+
abcs = ActiveRecord::Base.configurations
|
250
|
+
case abcs["test"]["adapter"]
|
251
|
+
when "mysql"
|
252
|
+
ActiveRecord::Base.establish_connection(:test)
|
253
|
+
ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
|
254
|
+
IO.readlines(Reactive.path_for(:db, "#{env}_structure.sql")).join.split("\n\n").each do |table|
|
255
|
+
ActiveRecord::Base.connection.execute(table)
|
256
|
+
end
|
257
|
+
when "postgresql"
|
258
|
+
ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
|
259
|
+
ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
|
260
|
+
ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
|
261
|
+
`psql -U "#{abcs["test"]["username"]}" -f db/#{env}_structure.sql #{abcs["test"]["database"]}`
|
262
|
+
when "sqlite", "sqlite3"
|
263
|
+
dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"]
|
264
|
+
`#{abcs["test"]["adapter"]} #{dbfile} < db/#{env}_structure.sql`
|
265
|
+
when "sqlserver"
|
266
|
+
`osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{env}_structure.sql`
|
267
|
+
when "oci", "oracle"
|
268
|
+
ActiveRecord::Base.establish_connection(:test)
|
269
|
+
IO.readlines(Reactive.path_for(:db, "#{env}_structure.sql")).join.split(";\n\n").each do |ddl|
|
270
|
+
ActiveRecord::Base.connection.execute(ddl)
|
271
|
+
end
|
272
|
+
when "firebird"
|
273
|
+
set_firebird_env(abcs["test"])
|
274
|
+
db_string = firebird_db_string(abcs["test"])
|
275
|
+
sh "isql -i db/#{env}_structure.sql #{db_string}"
|
276
|
+
else
|
277
|
+
raise "Task not supported by '#{abcs["test"]["adapter"]}'"
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
desc "Empty the test database"
|
282
|
+
task :purge => :environment do
|
283
|
+
abcs = ActiveRecord::Base.configurations
|
284
|
+
case abcs["test"]["adapter"]
|
285
|
+
when "mysql"
|
286
|
+
ActiveRecord::Base.establish_connection(:test)
|
287
|
+
ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"])
|
288
|
+
when "postgresql"
|
289
|
+
ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
|
290
|
+
ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
|
291
|
+
ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
|
292
|
+
enc_option = "-E #{abcs["test"]["encoding"]}" if abcs["test"]["encoding"]
|
293
|
+
|
294
|
+
ActiveRecord::Base.clear_active_connections!
|
295
|
+
`dropdb -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
|
296
|
+
`createdb #{enc_option} -U "#{abcs["test"]["username"]}" #{abcs["test"]["database"]}`
|
297
|
+
when "sqlite","sqlite3"
|
298
|
+
dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"]
|
299
|
+
File.delete(dbfile) if File.exist?(dbfile)
|
300
|
+
when "sqlserver"
|
301
|
+
dropfkscript = "#{abcs["test"]["host"]}.#{abcs["test"]["database"]}.DP1".gsub(/\\/,'-')
|
302
|
+
`osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{dropfkscript}`
|
303
|
+
`osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{Reactive.configuration.environment}_structure.sql`
|
304
|
+
when "oci", "oracle"
|
305
|
+
ActiveRecord::Base.establish_connection(:test)
|
306
|
+
ActiveRecord::Base.connection.structure_drop.split(";\n\n").each do |ddl|
|
307
|
+
ActiveRecord::Base.connection.execute(ddl)
|
308
|
+
end
|
309
|
+
when "firebird"
|
310
|
+
ActiveRecord::Base.establish_connection(:test)
|
311
|
+
ActiveRecord::Base.connection.recreate_database!
|
312
|
+
else
|
313
|
+
raise "Task not supported by '#{abcs["test"]["adapter"]}'"
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
desc 'Prepare the test database and load the schema'
|
318
|
+
task :prepare => %w(environment db:abort_if_pending_migrations) do
|
319
|
+
if defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
|
320
|
+
Rake::Task[{ :sql => "db:test:clone_structure", :ruby => "db:test:clone" }[ActiveRecord::Base.schema_format]].invoke
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
end
|
326
|
+
|
327
|
+
def drop_database(config)
|
328
|
+
case config['adapter']
|
329
|
+
when 'mysql'
|
330
|
+
ActiveRecord::Base.connection.drop_database config['database']
|
331
|
+
when /^sqlite/
|
332
|
+
FileUtils.rm_f(Reactive.path_for(config['database']))
|
333
|
+
when 'postgresql'
|
334
|
+
`dropdb "#{config['database']}"`
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
def session_table_name
|
339
|
+
ActiveRecord::Base.pluralize_table_names ? :sessions : :session
|
340
|
+
end
|
341
|
+
|
342
|
+
def set_firebird_env(config)
|
343
|
+
ENV["ISC_USER"] = config["username"].to_s if config["username"]
|
344
|
+
ENV["ISC_PASSWORD"] = config["password"].to_s if config["password"]
|
345
|
+
end
|
346
|
+
|
347
|
+
def firebird_db_string(config)
|
348
|
+
FireRuby::Database.db_string_for(config.symbolize_keys)
|
349
|
+
end
|