homeq 1.1.4

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 (63) hide show
  1. data/CHANGELOG +103 -0
  2. data/COPYING +348 -0
  3. data/README.rdoc +64 -0
  4. data/Rakefile +131 -0
  5. data/bin/hq +6 -0
  6. data/config/boot.rb +224 -0
  7. data/config/databases/frontbase.yml +28 -0
  8. data/config/databases/mysql.yml +54 -0
  9. data/config/databases/oracle.yml +39 -0
  10. data/config/databases/postgresql.yml +48 -0
  11. data/config/databases/sqlite2.yml +16 -0
  12. data/config/databases/sqlite3.yml +19 -0
  13. data/config/environment.rb +20 -0
  14. data/config/environments/development.cfg +35 -0
  15. data/config/environments/production.cfg +35 -0
  16. data/config/environments/test.cfg +35 -0
  17. data/config/generators/job/templates/job.rb.erb +20 -0
  18. data/config/generators/message/templates/messages/MESSAGE.proto.erb +12 -0
  19. data/config/generators/model/templates/models/MODEL.rb.erb +3 -0
  20. data/config/generators/service/templates/services/SERVICE.rb.erb +43 -0
  21. data/config/homeq.cfg +35 -0
  22. data/extras/consumer.rb +85 -0
  23. data/extras/homeq.cfg +49 -0
  24. data/extras/hqd.rb +33 -0
  25. data/extras/producer.rb +79 -0
  26. data/extras/simple_consumer.rb +53 -0
  27. data/lib/homeq/base/base.rb +44 -0
  28. data/lib/homeq/base/commando.rb +81 -0
  29. data/lib/homeq/base/config.rb +99 -0
  30. data/lib/homeq/base/exception.rb +48 -0
  31. data/lib/homeq/base/histogram.rb +141 -0
  32. data/lib/homeq/base/logger.rb +185 -0
  33. data/lib/homeq/base/ohash.rb +297 -0
  34. data/lib/homeq/base/options.rb +171 -0
  35. data/lib/homeq/base/poolable.rb +100 -0
  36. data/lib/homeq/base/system.rb +446 -0
  37. data/lib/homeq/cli.rb +35 -0
  38. data/lib/homeq/cp/commands.rb +71 -0
  39. data/lib/homeq/cp/connection.rb +97 -0
  40. data/lib/homeq/cp/cp.rb +30 -0
  41. data/lib/homeq/cp/server.rb +105 -0
  42. data/lib/homeq/sobs/client.rb +119 -0
  43. data/lib/homeq/sobs/connection.rb +635 -0
  44. data/lib/homeq/sobs/foreman.rb +237 -0
  45. data/lib/homeq/sobs/job.rb +66 -0
  46. data/lib/homeq/sobs/message.rb +49 -0
  47. data/lib/homeq/sobs/queue.rb +224 -0
  48. data/lib/homeq/sobs/sender.rb +150 -0
  49. data/lib/homeq/sobs/server.rb +654 -0
  50. data/lib/homeq/sobs/sobs.rb +45 -0
  51. data/lib/homeq/sobs/topology.rb +111 -0
  52. data/lib/homeq.rb +106 -0
  53. data/lib/tasks/Rakefile +49 -0
  54. data/lib/tasks/database.rake +387 -0
  55. data/lib/tasks/gem.rake +9 -0
  56. data/lib/tasks/generate.rake +192 -0
  57. data/lib/tasks/hq.rake +171 -0
  58. data/lib/tasks/testing.rake +95 -0
  59. data/lib/tasks/utility.rb +17 -0
  60. data/script/console.rb +45 -0
  61. data/script/generate +7 -0
  62. data/test/unittest.rb +51 -0
  63. metadata +222 -0
@@ -0,0 +1,111 @@
1
+ #############################################################################
2
+ #
3
+ # $Id: topology.rb 48 2008-11-19 05:11:59Z colin $
4
+ #
5
+ # Author:: Colin Steele (colin@colinsteele.org)
6
+ # Homepage::
7
+ #
8
+ # TODO: info
9
+ #
10
+ #----------------------------------------------------------------------------
11
+ #
12
+ # Copyright (C) 2008 by Colin Steele. All Rights Reserved.
13
+ # colin@colinsteele.org
14
+ #
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of either: 1) the GNU General Public License
17
+ # as published by the Free Software Foundation; either version 2 of the
18
+ # License, or (at your option) any later version; or 2) Ruby's License.
19
+ #
20
+ # See the file COPYING for complete licensing information.
21
+ #
22
+ #---------------------------------------------------------------------------
23
+ #
24
+ #
25
+ #############################################################################
26
+
27
+ require 'yaml'
28
+
29
+ module HomeQ
30
+
31
+ module SOBS
32
+
33
+ module Topology
34
+
35
+ # Make our configuration available.
36
+ module HomeQ::Base::Commando::InstanceMethods
37
+ def topology
38
+ if block_given?
39
+ yield
40
+ else
41
+ sys.topology
42
+ end
43
+ end
44
+ def queue(queuename, &block)
45
+ sys.topology.queue(queuename) { |q|
46
+ q.instance_eval(&block)
47
+ }
48
+ end
49
+ document_command "topology", "Get/set queue topology"
50
+ document_command "queue(name) {}", "Configure queue topology"
51
+ end
52
+
53
+ class Topology
54
+ attr :queues, false
55
+ attr :connections, false
56
+ def initialize
57
+ @queues = {}
58
+ @connections = {}
59
+ end
60
+ def queue(name)
61
+ @current_queue = name
62
+ yield self
63
+ @current_queue = nil
64
+ end
65
+ def located_at(host, port, hostname='localhost')
66
+ @queues[@current_queue] = [@current_queue, host, port, hostname]
67
+ end
68
+ def connect(other_queue, mode=SOBS::Queue::READ_WRITE, threshold=nil)
69
+ @connections[@current_queue] ||= []
70
+ @connections[@current_queue] << [other_queue, mode, threshold]
71
+ end
72
+ def reads_from(other_queue, refuse_threshold = nil)
73
+ connect(other_queue, SOBS::Queue::READ_ONLY, refuse_threshold)
74
+ end
75
+ def writes_to(other_queue, refuse_threshold = nil)
76
+ connect(other_queue, SOBS::Queue::WRITE_ONLY, refuse_threshold)
77
+ end
78
+ def read_write(other_queue, refuse_threshold = nil)
79
+ connect(other_queue, SOBS::Queue::READ_WRITE, refuse_threshold)
80
+ end
81
+ def [](name)
82
+ @queues[name]
83
+ end
84
+ def connections(name)
85
+ @connections[name] || []
86
+ end
87
+ def to_s
88
+ str = ""
89
+ @queues.each { |name, tuple|
90
+ queue_name, host, port, hostname = tuple
91
+ str << "#{name} #{host} #{port} #{hostname}\n"
92
+ next unless @connections[name]
93
+ @connections[name].each { |other_queue, mode, threshold|
94
+ str << " #{mode.upcase} #{other_queue} #{threshold}\n"
95
+ }
96
+ }
97
+ str
98
+ end
99
+ def to_yaml
100
+ YAML.dump({
101
+ 'queues' => @queues,
102
+ 'connections' => @connections
103
+ })
104
+ end
105
+ end
106
+
107
+ end # Topology
108
+
109
+ end # SOBS
110
+
111
+ end # HomeQ
data/lib/homeq.rb ADDED
@@ -0,0 +1,106 @@
1
+ #############################################################################
2
+ #
3
+ # $Id: homeq.rb 45 2008-10-24 20:36:21Z colin $
4
+ #
5
+ # Author:: Colin Steele (colin@colinsteele.org)
6
+ # Homepage::
7
+ #
8
+ # TODO: info
9
+ #
10
+ #----------------------------------------------------------------------------
11
+ #
12
+ # Copyright (C) 2008 by Colin Steele. All Rights Reserved.
13
+ # colin@colinsteele.org
14
+ #
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of either: 1) the GNU General Public License
17
+ # as published by the Free Software Foundation; either version 2 of the
18
+ # License, or (at your option) any later version; or 2) Ruby's License.
19
+ #
20
+ # See the file COPYING for complete licensing information.
21
+ #
22
+ #---------------------------------------------------------------------------
23
+ #
24
+ #
25
+ #############################################################################
26
+
27
+ require 'strscan'
28
+ require 'singleton'
29
+ require 'yaml'
30
+
31
+ HOMEQ_VERSION = "1.1.4" unless defined?(HOMEQ_VERSION)
32
+ unless defined?(HOMEQ_ROOT)
33
+ HOMEQ_ROOT = File.expand_path("#{File.dirname(__FILE__)}/..")
34
+ end
35
+ HOMEQ_ENV = (ENV['HOMEQ_ENV'] || 'production') unless defined?(HOMEQ_ENV)
36
+
37
+ module HomeQ
38
+ VERSION = HOMEQ_VERSION
39
+ def self.included(base)
40
+ base.class_eval {
41
+ include(HomeQ::HQ)
42
+ include(HomeQ::Base::Configuration)
43
+ include(HomeQ::Base::Logging)
44
+ }
45
+ end
46
+
47
+ def self.calculated_homeq_env
48
+ if defined?(HOMEQ_APP_ROOT)
49
+ require "#{HOMEQ_APP_ROOT}/config/environment"
50
+ else
51
+ require 'config/environment'
52
+ end
53
+
54
+ options = HomeQ::Base::Options::Options.instance.options
55
+ sys = HomeQ::Base::System.instance
56
+
57
+ options.log_level = 'fatal'
58
+ options.foreground = true
59
+ options.queue_name = '__'
60
+
61
+ env = nil
62
+ sys.start {
63
+ env = HOMEQ_ENV
64
+ EM.next_tick {
65
+ sys.stop
66
+ }
67
+ }
68
+ env
69
+ end
70
+
71
+ def self.calculated_homeq_topology
72
+ if defined?(HOMEQ_APP_ROOT)
73
+ require "#{HOMEQ_APP_ROOT}/config/environment"
74
+ else
75
+ require 'config/environment'
76
+ end
77
+
78
+ options = HomeQ::Base::Options::Options.instance.options
79
+ sys = HomeQ::Base::System.instance
80
+
81
+ if sys.topology.queues.any?
82
+ return sys.topology
83
+ end
84
+
85
+ options.log_level = 'fatal'
86
+ options.foreground = true
87
+ options.queue_name = '__'
88
+ topology = nil
89
+ sys.start {
90
+ topology = sys.topology
91
+ sys.stop
92
+ }
93
+ topology
94
+ end
95
+
96
+ def self.queue_list_for_host_from_topology(some_hostname = `hostname`.chomp)
97
+ queues_for_this_host = []
98
+ self.
99
+ calculated_homeq_topology.queues.
100
+ values.each { |queue_name, host, port, hostname|
101
+ queues_for_this_host << queue_name if hostname == some_hostname
102
+ }
103
+ queues_for_this_host
104
+ end
105
+
106
+ end
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/ruby
2
+ #############################################################################
3
+ #
4
+ # Author:: Colin Steele (colin@colinsteele.org)
5
+ #
6
+ #############################################################################
7
+
8
+ require 'rubygems'
9
+ require 'rake'
10
+
11
+ require File.join(File.dirname(__FILE__), '/config/environment')
12
+
13
+ require 'rake/testtask'
14
+ require 'rake/rdoctask'
15
+
16
+ # load custom tasks
17
+ Dir["#{HOMEQ_APP_ROOT}/lib/tasks/**/*.rake"].sort.each { |ext| load ext }
18
+
19
+ task :default => [:test]
20
+
21
+ desc "Load HOMEQ environment"
22
+ task (:environment) do
23
+ require File.join(File.dirname(__FILE__), '/config/environment')
24
+ end
25
+
26
+ desc "Recreate the CHANGELOG"
27
+ task(:changelog) do
28
+ rm 'CHANGELOG', :force => true
29
+ touch 'CHANGELOG'
30
+ puts %x[svn2cl.sh]
31
+ end
32
+
33
+ Rake::RDocTask.new do |rd|
34
+ rd.main = "README"
35
+ rd.rdoc_files.include("README", "lib/**/*.rb", "app/**/*.rb")
36
+ rd.rdoc_dir = 'doc'
37
+ rd.title = ''
38
+ rd.options << '--line-numbers'
39
+ rd.options << '--inline-source'
40
+ rd.options << '--main' << 'README'
41
+ end
42
+
43
+ desc "Recreate message classes from proto definitions"
44
+ task(:messages => Dir['app/messages/*.proto']) do |t|
45
+ cd 'app/messages'
46
+ t.prerequisites.each { |f|
47
+ sh "rprotoc -o wire #{File.basename(f)}"
48
+ }
49
+ end
@@ -0,0 +1,387 @@
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
+ local_database?(config) { create_database(config) }
20
+ end
21
+ end
22
+ end
23
+
24
+ desc 'Create the database defined in config/database.yml for the current HOMEQ_ENV'
25
+ task :create => :environment do
26
+ create_database(ActiveRecord::Base.configurations[HOMEQ_ENV])
27
+ end
28
+
29
+ def create_database(config)
30
+ begin
31
+ ActiveRecord::Base.establish_connection(config)
32
+ ActiveRecord::Base.connection
33
+ rescue
34
+ case config['adapter']
35
+ when 'mysql'
36
+ @charset = ENV['CHARSET'] || 'utf8'
37
+ @collation = ENV['COLLATION'] || 'utf8_general_ci'
38
+ begin
39
+ ActiveRecord::Base.establish_connection(config.merge('database' => nil))
40
+ ActiveRecord::Base.connection.create_database(config['database'], :charset => (config['charset'] || @charset), :collation => (config['collation'] || @collation))
41
+ ActiveRecord::Base.establish_connection(config)
42
+ rescue
43
+ $stderr.puts "Couldn't create database for #{config.inspect}, charset: #{config['charset'] || @charset}, collation: #{config['collation'] || @collation} (if you set the charset manually, make sure you have a matching collation)"
44
+ end
45
+ when 'postgresql'
46
+ @encoding = config[:encoding] || ENV['CHARSET'] || 'utf8'
47
+ begin
48
+ ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
49
+ ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => @encoding))
50
+ ActiveRecord::Base.establish_connection(config)
51
+ rescue
52
+ $stderr.puts $!, *($!.backtrace)
53
+ $stderr.puts "Couldn't create database for #{config.inspect}"
54
+ end
55
+ when 'sqlite'
56
+ `sqlite "#{config['database']}"`
57
+ when 'sqlite3'
58
+ `sqlite3 "#{config['database']}"`
59
+ end
60
+ else
61
+ $stderr.puts "#{config['database']} already exists"
62
+ end
63
+ end
64
+
65
+ namespace :drop do
66
+ desc 'Drops all the local databases defined in config/database.yml'
67
+ task :all => :environment do
68
+ ActiveRecord::Base.configurations.each_value do |config|
69
+ # Skip entries that don't have a database key
70
+ next unless config['database']
71
+ # Only connect to local databases
72
+ local_database?(config) { drop_database(config) }
73
+ end
74
+ end
75
+ end
76
+
77
+ desc 'Drops the database for the current HOMEQ_ENV'
78
+ task :drop => :environment do
79
+ config = ActiveRecord::Base.configurations[HOMEQ_ENV || 'development']
80
+ begin
81
+ drop_database(config)
82
+ rescue Exception => e
83
+ puts "Couldn't drop #{config['database']} : #{e.inspect}"
84
+ end
85
+ end
86
+
87
+ def local_database?(config, &block)
88
+ if %w( 127.0.0.1 localhost ).include?(config['host']) || config['host'].blank?
89
+ yield
90
+ else
91
+ puts "This task only modifies local databases. #{config['database']} is on a remote host."
92
+ end
93
+ end
94
+
95
+
96
+ desc "Migrate the database through scripts in db/migrate. Target specific version with VERSION=x. Turn off output with VERBOSE=false."
97
+ task :migrate => :environment do
98
+ ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
99
+ ActiveRecord::Migrator.migrate("db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
100
+ Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
101
+ end
102
+
103
+ namespace :migrate do
104
+ desc 'Rollbacks the database one migration and re migrate up. If you want to rollback more than one step, define STEP=x'
105
+ task :redo => [ 'db:rollback', 'db:migrate' ]
106
+
107
+ desc 'Resets your database using your migrations for the current environment'
108
+ task :reset => ["db:drop", "db:create", "db:migrate"]
109
+
110
+ desc 'Runs the "up" for a given migration VERSION.'
111
+ task :up => :environment do
112
+ version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
113
+ raise "VERSION is required" unless version
114
+ ActiveRecord::Migrator.run(:up, "db/migrate/", version)
115
+ Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
116
+ end
117
+
118
+ desc 'Runs the "down" for a given migration VERSION.'
119
+ task :down => :environment do
120
+ version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
121
+ raise "VERSION is required" unless version
122
+ ActiveRecord::Migrator.run(:down, "db/migrate/", version)
123
+ Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
124
+ end
125
+ end
126
+
127
+ desc 'Rolls the schema back to the previous version. Specify the number of steps with STEP=n'
128
+ task :rollback => :environment do
129
+ step = ENV['STEP'] ? ENV['STEP'].to_i : 1
130
+ ActiveRecord::Migrator.rollback('db/migrate/', step)
131
+ Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
132
+ end
133
+
134
+ desc 'Drops and recreates the database from db/schema.rb for the current environment.'
135
+ task :reset => ['db:drop', 'db:create', 'db:schema:load']
136
+
137
+ desc "Retrieves the charset for the current environment's database"
138
+ task :charset => :environment do
139
+ config = ActiveRecord::Base.configurations[HOMEQ_ENV || 'development']
140
+ case config['adapter']
141
+ when 'mysql'
142
+ ActiveRecord::Base.establish_connection(config)
143
+ puts ActiveRecord::Base.connection.charset
144
+ else
145
+ puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
146
+ end
147
+ end
148
+
149
+ desc "Retrieves the collation for the current environment's database"
150
+ task :collation => :environment do
151
+ config = ActiveRecord::Base.configurations[HOMEQ_ENV || 'development']
152
+ case config['adapter']
153
+ when 'mysql'
154
+ ActiveRecord::Base.establish_connection(config)
155
+ puts ActiveRecord::Base.connection.collation
156
+ else
157
+ puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
158
+ end
159
+ end
160
+
161
+ desc "Retrieves the current schema version number"
162
+ task :version => :environment do
163
+ puts "Current version: #{ActiveRecord::Migrator.current_version}"
164
+ end
165
+
166
+ desc "Raises an error if there are pending migrations"
167
+ task :abort_if_pending_migrations => :environment do
168
+ if defined? ActiveRecord
169
+ pending_migrations = ActiveRecord::Migrator.new(:up, 'db/migrate').pending_migrations
170
+
171
+ if pending_migrations.any?
172
+ puts "You have #{pending_migrations.size} pending migrations:"
173
+ pending_migrations.each do |pending_migration|
174
+ puts ' %4d %s' % [pending_migration.version, pending_migration.name]
175
+ end
176
+ abort %{Run "rake db:migrate" to update your database then try again.}
177
+ end
178
+ end
179
+ end
180
+
181
+ namespace :fixtures do
182
+ desc "Load fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y"
183
+ task :load => :environment do
184
+ require 'active_record/fixtures'
185
+ ActiveRecord::Base.establish_connection(HOMEQ_ENV.to_sym)
186
+ (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(HOMEQ_APP_ROOT, 'test', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
187
+ Fixtures.create_fixtures('test/fixtures', File.basename(fixture_file, '.*'))
188
+ end
189
+ end
190
+
191
+ desc "Search for a fixture given a LABEL or ID."
192
+ task :identify => :environment do
193
+ require "active_record/fixtures"
194
+
195
+ label, id = ENV["LABEL"], ENV["ID"]
196
+ raise "LABEL or ID required" if label.blank? && id.blank?
197
+
198
+ puts %Q(The fixture ID for "#{label}" is #{Fixtures.identify(label)}.) if label
199
+
200
+ Dir["#{HOMEQ_APP_ROOT}/test/fixtures/**/*.yml"].each do |file|
201
+ if data = YAML::load(ERB.new(IO.read(file)).result)
202
+ data.keys.each do |key|
203
+ key_id = Fixtures.identify(key)
204
+
205
+ if key == label || key_id == id.to_i
206
+ puts "#{file}: #{key} (#{key_id})"
207
+ end
208
+ end
209
+ end
210
+ end
211
+ end
212
+ end
213
+
214
+ namespace :schema do
215
+ desc "Create a db/schema.rb file that can be portably used against any DB supported by AR"
216
+ task :dump => :environment do
217
+ require 'active_record/schema_dumper'
218
+ File.open(ENV['SCHEMA'] || "db/schema.rb", "w") do |file|
219
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
220
+ end
221
+ end
222
+
223
+ desc "Load a schema.rb file into the database"
224
+ task :load => :environment do
225
+ file = ENV['SCHEMA'] || "db/schema.rb"
226
+ load(file)
227
+ end
228
+ end
229
+
230
+ namespace :structure do
231
+ desc "Dump the database structure to a SQL file"
232
+ task :dump => :environment do
233
+ abcs = ActiveRecord::Base.configurations
234
+ case abcs[HOMEQ_ENV]["adapter"]
235
+ when "mysql", "oci", "oracle"
236
+ ActiveRecord::Base.establish_connection(abcs[HOMEQ_ENV])
237
+ File.open("db/#{HOMEQ_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump }
238
+ when "postgresql"
239
+ ENV['PGHOST'] = abcs[HOMEQ_ENV]["host"] if abcs[HOMEQ_ENV]["host"]
240
+ ENV['PGPORT'] = abcs[HOMEQ_ENV]["port"].to_s if abcs[HOMEQ_ENV]["port"]
241
+ ENV['PGPASSWORD'] = abcs[HOMEQ_ENV]["password"].to_s if abcs[HOMEQ_ENV]["password"]
242
+ search_path = abcs[HOMEQ_ENV]["schema_search_path"]
243
+ search_path = "--schema=#{search_path}" if search_path
244
+ `pg_dump -i -U "#{abcs[HOMEQ_ENV]["username"]}" -s -x -O -f db/#{HOMEQ_ENV}_structure.sql #{search_path} #{abcs[HOMEQ_ENV]["database"]}`
245
+ raise "Error dumping database" if $?.exitstatus == 1
246
+ when "sqlite", "sqlite3"
247
+ dbfile = abcs[HOMEQ_ENV]["database"] || abcs[HOMEQ_ENV]["dbfile"]
248
+ `#{abcs[HOMEQ_ENV]["adapter"]} #{dbfile} .schema > db/#{HOMEQ_ENV}_structure.sql`
249
+ when "sqlserver"
250
+ `scptxfr /s #{abcs[HOMEQ_ENV]["host"]} /d #{abcs[HOMEQ_ENV]["database"]} /I /f db\\#{HOMEQ_ENV}_structure.sql /q /A /r`
251
+ `scptxfr /s #{abcs[HOMEQ_ENV]["host"]} /d #{abcs[HOMEQ_ENV]["database"]} /I /F db\ /q /A /r`
252
+ when "firebird"
253
+ set_firebird_env(abcs[HOMEQ_ENV])
254
+ db_string = firebird_db_string(abcs[HOMEQ_ENV])
255
+ sh "isql -a #{db_string} > db/#{HOMEQ_ENV}_structure.sql"
256
+ else
257
+ raise "Task not supported by '#{abcs["test"]["adapter"]}'"
258
+ end
259
+
260
+ if ActiveRecord::Base.connection.supports_migrations?
261
+ File.open("db/#{HOMEQ_ENV}_structure.sql", "a") { |f| f << ActiveRecord::Base.connection.dump_schema_information }
262
+ end
263
+ end
264
+ end
265
+
266
+ namespace :test do
267
+ desc "Recreate the test database from the current environment's database schema"
268
+ task :clone => %w(db:schema:dump db:test:purge) do
269
+ ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])
270
+ ActiveRecord::Schema.verbose = false
271
+ Rake::Task["db:schema:load"].invoke
272
+ end
273
+
274
+
275
+ desc "Recreate the test databases from the development structure"
276
+ task :clone_structure => [ "db:structure:dump", "db:test:purge" ] do
277
+ abcs = ActiveRecord::Base.configurations
278
+ case abcs["test"]["adapter"]
279
+ when "mysql"
280
+ ActiveRecord::Base.establish_connection(:test)
281
+ ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
282
+ IO.readlines("db/#{HOMEQ_ENV}_structure.sql").join.split("\n\n").each do |table|
283
+ ActiveRecord::Base.connection.execute(table)
284
+ end
285
+ when "postgresql"
286
+ ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
287
+ ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
288
+ ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
289
+ `psql -U "#{abcs["test"]["username"]}" -f db/#{HOMEQ_ENV}_structure.sql #{abcs["test"]["database"]}`
290
+ when "sqlite", "sqlite3"
291
+ dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"]
292
+ `#{abcs["test"]["adapter"]} #{dbfile} < db/#{HOMEQ_ENV}_structure.sql`
293
+ when "sqlserver"
294
+ `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{HOMEQ_ENV}_structure.sql`
295
+ when "oci", "oracle"
296
+ ActiveRecord::Base.establish_connection(:test)
297
+ IO.readlines("db/#{HOMEQ_ENV}_structure.sql").join.split(";\n\n").each do |ddl|
298
+ ActiveRecord::Base.connection.execute(ddl)
299
+ end
300
+ when "firebird"
301
+ set_firebird_env(abcs["test"])
302
+ db_string = firebird_db_string(abcs["test"])
303
+ sh "isql -i db/#{HOMEQ_ENV}_structure.sql #{db_string}"
304
+ else
305
+ raise "Task not supported by '#{abcs["test"]["adapter"]}'"
306
+ end
307
+ end
308
+
309
+ desc "Empty the test database"
310
+ task :purge => :environment do
311
+ abcs = ActiveRecord::Base.configurations
312
+ case abcs["test"]["adapter"]
313
+ when "mysql"
314
+ ActiveRecord::Base.establish_connection(:test)
315
+ ActiveRecord::Base.connection.recreate_database(abcs["test"]["database"])
316
+ when "postgresql"
317
+ ActiveRecord::Base.clear_active_connections!
318
+ drop_database(abcs['test'])
319
+ create_database(abcs['test'])
320
+ when "sqlite","sqlite3"
321
+ dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"]
322
+ File.delete(dbfile) if File.exist?(dbfile)
323
+ when "sqlserver"
324
+ dropfkscript = "#{abcs["test"]["host"]}.#{abcs["test"]["database"]}.DP1".gsub(/\\/,'-')
325
+ `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{dropfkscript}`
326
+ `osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{HOMEQ_ENV}_structure.sql`
327
+ when "oci", "oracle"
328
+ ActiveRecord::Base.establish_connection(:test)
329
+ ActiveRecord::Base.connection.structure_drop.split(";\n\n").each do |ddl|
330
+ ActiveRecord::Base.connection.execute(ddl)
331
+ end
332
+ when "firebird"
333
+ ActiveRecord::Base.establish_connection(:test)
334
+ ActiveRecord::Base.connection.recreate_database!
335
+ else
336
+ raise "Task not supported by '#{abcs["test"]["adapter"]}'"
337
+ end
338
+ end
339
+
340
+ desc 'Prepare the test database and load the schema'
341
+ task :prepare => %w(environment db:abort_if_pending_migrations) do
342
+ if defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
343
+ Rake::Task[{ :sql => "db:test:clone_structure", :ruby => "db:test:clone" }[ActiveRecord::Base.schema_format]].invoke
344
+ end
345
+ end
346
+ end
347
+
348
+ namespace :sessions do
349
+ desc "Creates a sessions migration for use with CGI::Session::ActiveRecordStore"
350
+ task :create => :environment do
351
+ raise "Task unavailable to this database (no migration support)" unless ActiveRecord::Base.connection.supports_migrations?
352
+ require 'rails_generator'
353
+ require 'rails_generator/scripts/generate'
354
+ Rails::Generator::Scripts::Generate.new.run(["session_migration", ENV["MIGRATION"] || "CreateSessions"])
355
+ end
356
+
357
+ desc "Clear the sessions table"
358
+ task :clear => :environment do
359
+ ActiveRecord::Base.connection.execute "DELETE FROM #{session_table_name}"
360
+ end
361
+ end
362
+ end
363
+
364
+ def drop_database(config)
365
+ case config['adapter']
366
+ when 'mysql'
367
+ ActiveRecord::Base.connection.drop_database config['database']
368
+ when /^sqlite/
369
+ FileUtils.rm(File.join(HOMEQ_APP_ROOT, config['database']))
370
+ when 'postgresql'
371
+ ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
372
+ ActiveRecord::Base.connection.drop_database config['database']
373
+ end
374
+ end
375
+
376
+ def session_table_name
377
+ ActiveRecord::Base.pluralize_table_names ? :sessions : :session
378
+ end
379
+
380
+ def set_firebird_env(config)
381
+ ENV["ISC_USER"] = config["username"].to_s if config["username"]
382
+ ENV["ISC_PASSWORD"] = config["password"].to_s if config["password"]
383
+ end
384
+
385
+ def firebird_db_string(config)
386
+ FireRuby::Database.db_string_for(config.symbolize_keys)
387
+ end
@@ -0,0 +1,9 @@
1
+ namespace :gem do
2
+ desc "install a gem into vendor/gems"
3
+ task :install do
4
+ if ENV["name"].nil?
5
+ STDERR.puts "Usage: rake gem:install name=the_gem_name"; exit 1
6
+ end
7
+ sh "gem install #{ENV['name']} --install-dir=vendor/gems --no-rdoc --no-ri"
8
+ end
9
+ end