active_shard 0.2.2 → 0.2.3

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.
@@ -0,0 +1,329 @@
1
+ namespace :shards do
2
+
3
+ desc 'Create the database from config/database.yml for the current Rails.env (use db:create:all to create all dbs in the config)'
4
+ task :create => :environment do
5
+
6
+ # Make the test database at the same time as the development one, if it exists
7
+ if Rails.env.development?
8
+ ActiveShard.config.shard_definitions( :test ).each do |definition|
9
+ create_database(definition)
10
+ end
11
+ end
12
+ ActiveShard.config.shard_definitions( Rails.env.to_sym ).each do |definition|
13
+ create_database( definition )
14
+ end
15
+ end
16
+
17
+ def create_database( definition )
18
+ begin
19
+ if definition.connection_adapter =~ /sqlite/
20
+ active_shard_does_not_implement!( definition.connection_adapter )
21
+ else
22
+ pool = ActiveShard::ActiveRecord::ConnectionProxyPool.new( definition )
23
+ pool.connection
24
+ end
25
+ rescue
26
+ case definition.connection_adapter
27
+ when /mysql/
28
+ @charset = ENV['CHARSET'] || 'utf8'
29
+ @collation = ENV['COLLATION'] || 'utf8_unicode_ci'
30
+ creation_options = {:charset => (definition.connection_spec['charset'] || @charset), :collation => (definition.connection_spec['collation'] || @collation)}
31
+ error_class = definition.connection_adapter =~ /mysql2/ ? Mysql2::Error : Mysql::Error
32
+ access_denied_error = 1045
33
+ begin
34
+ sd = ActiveShard::ShardDefinition.new(
35
+ definition.name, { :schema => definition.schema }.merge( definition.connection_spec ).merge( :database => nil )
36
+ )
37
+
38
+ pool = ActiveShard::ActiveRecord::ConnectionProxyPool.new( sd )
39
+
40
+ pool.connection.create_database( definition.connection_database, creation_options )
41
+
42
+ ActiveShard::ActiveRecord::ConnectionProxyPool.new( definition ).connection
43
+ rescue error_class => sqlerr
44
+ $stderr.puts sqlerr.error
45
+ $stderr.puts "Couldn't create database for #{definition.inspect}"
46
+ end
47
+ when 'postgresql'
48
+ active_shard_does_not_implement!( 'postgresql' )
49
+ end
50
+ else
51
+ $stderr.puts "#{definition.connection_database} already exists"
52
+ end
53
+ end
54
+
55
+ desc "Migrate the database (options: VERSION=x, VERBOSE=false)."
56
+ task :migrate, [:shard_name] => :environment do |t, args|
57
+ schemas = {}
58
+
59
+ active_shard_definitions( args ).each do |shard_definition|
60
+ with_shard( shard_definition.name ) do |shard_name, schema|
61
+ schemas[schema] = shard_name
62
+
63
+ ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
64
+ ActiveRecord::Migrator.migrate("db/migrate/#{schema}/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
65
+ end
66
+ end
67
+
68
+ schemas.each_pair { |schema, shard| dump_schema( shard ) }
69
+ end
70
+
71
+ namespace :migrate do
72
+ # desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
73
+ task :redo, [:shard_name] => :environment do |t, args|
74
+ if ENV["VERSION"]
75
+ Rake::Task["shards:migrate:down"].invoke( *args.values )
76
+ Rake::Task["shards:migrate:up"].invoke( *args.values )
77
+ else
78
+ Rake::Task["shards:rollback"].invoke( *args.values )
79
+ Rake::Task["shards:migrate"].invoke( *args.values )
80
+ end
81
+ end
82
+
83
+ # desc 'Runs the "up" for a given migration VERSION.'
84
+ task :up, [:shard_name] => :environment do |t, args|
85
+ version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
86
+ raise "VERSION is required" unless version
87
+
88
+ with_shard( args ) do |shard_name, schema|
89
+ ActiveRecord::Migrator.run(:up, "db/migrate/#{schema}", version)
90
+
91
+ dump_schema( shard_name )
92
+ end
93
+ end
94
+
95
+ # desc 'Runs the "down" for a given migration VERSION.'
96
+ task :down, [:shard_name] => :environment do |t, args|
97
+ version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
98
+ raise "VERSION is required" unless version
99
+
100
+ with_shard( args ) do |shard_name, schema|
101
+ ActiveRecord::Migrator.run(:down, "db/migrate/#{schema}", version)
102
+
103
+ dump_schema( shard_name )
104
+ end
105
+ end
106
+ end
107
+
108
+ desc 'Rolls the schema back to the previous version (specify steps w/ STEP=n).'
109
+ task :rollback, [:shard_name] => :environment do |t, args|
110
+ step = ENV['STEP'] ? ENV['STEP'].to_i : 1
111
+
112
+ with_shard( args ) do |shard_name, schema|
113
+ ActiveRecord::Migrator.rollback("db/migrate/#{schema}", step)
114
+
115
+ dump_schema( shard_name )
116
+ end
117
+ end
118
+
119
+ # desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
120
+ task :forward, [:shard_name] => :environment do |t, args|
121
+ step = ENV['STEP'] ? ENV['STEP'].to_i : 1
122
+
123
+ with_shard( args ) do |shard_name, schema|
124
+ ActiveRecord::Migrator.forward("db/migrate/#{schema}", step)
125
+
126
+ dump_schema( shard_name )
127
+ end
128
+ end
129
+
130
+ desc "Retrieves the current schema version number"
131
+ task :version, [:shard_name] => :environment do |t, args|
132
+ with_shard( args ) do |shard_name, schema|
133
+ puts "Current version: #{ActiveRecord::Migrator.current_version}"
134
+ end
135
+ end
136
+
137
+ namespace :schema do
138
+
139
+ desc "Create a db/<schema>_schema.rb file that can be portably used against any DB supported by AR"
140
+ task :dump, [:shard_name] => :environment do |t, args|
141
+ require 'active_record/schema_dumper'
142
+
143
+ defs = active_shard_definitions( args )
144
+
145
+ defs.schemas.each do |schema|
146
+ shard_definition = defs.by_schema( schema ).first
147
+
148
+ with_shard( shard_definition.name ) do
149
+ File.open( "#{Rails.root}/db/#{schema}_schema.rb", "w" ) do |file|
150
+ ActiveRecord::SchemaDumper.dump( ActiveRecord::Base.connection, file )
151
+ end
152
+ end
153
+ end
154
+
155
+ Rake::Task["shards:schema:dump"].reenable
156
+ end
157
+
158
+ desc "Load a <schema>_schema.rb file into the database"
159
+ task :load, [:shard_name] => :environment do |t, args|
160
+ defs = active_shard_definitions( args )
161
+
162
+ defs.each do |shard_definition|
163
+ with_shard( shard_definition.name ) do
164
+ ActiveRecord::Schema.class_eval <<-EOM
165
+ def self.migrations_path
166
+ "db/migrate/#{shard_definition.schema}"
167
+ end
168
+ EOM
169
+
170
+ file = "#{Rails.root}/db/#{shard_definition.schema}_schema.rb"
171
+ if File.exists?( file )
172
+ load( file )
173
+ else
174
+ abort %{#{file} doesn't exist yet. Run "rake shards:migrate[#{shard_definition.name}]" to create it then try again. If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded}
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end
180
+
181
+ namespace :structure do
182
+ desc "Dump the database structure to an SQL file"
183
+ task :dump, [:shard_name] => :environment do |t, args|
184
+ ActiveShard.with_environment( :development ) do
185
+ defs = active_shard_definitions( args )
186
+
187
+ defs.schemas.each do |schema|
188
+ shard_definition = defs.by_schema( schema ).first
189
+
190
+ with_shard( shard_definition.name ) do
191
+
192
+ structure_file_path = "#{Rails.root}/db/#{schema}_structure.sql"
193
+
194
+ abcs = ActiveShard.shard( shard_definition.name ).connection_adapter
195
+ case abcs
196
+ when /mysql/, "oci", "oracle"
197
+ # We are already connected via with_shard, so just use.
198
+ #
199
+ File.open( structure_file_path, "w+" ) { |f| f << ActiveRecord::Base.connection.structure_dump }
200
+ when "postgresql", "sqlite", "sqlite3", "sqlserver", "firebird"
201
+ active_shard_does_not_implement!(abcs)
202
+ else
203
+ raise "Task not supported by '#{abcs}'"
204
+ end
205
+
206
+ if ActiveRecord::Base.connection.supports_migrations?
207
+ File.open( structure_file_path, "a" ) { |f| f << ActiveRecord::Base.connection.dump_schema_information }
208
+ end
209
+ end
210
+ end
211
+ end
212
+ end
213
+ end
214
+
215
+ namespace :test do
216
+ # desc "Recreate the test database from the current schema.rb"
217
+ task :load => 'shards:test:purge' do
218
+ ActiveShard.with_environment( :test ) do
219
+ ActiveRecord::Schema.verbose = false
220
+
221
+ puts "Building test shards ..."
222
+ ActiveShard.shard_definitions.each do |shard_definition|
223
+ puts " --> #{shard_definition.name} (#{shard_definition.schema})"
224
+ Rake::Task["shards:schema:load"].invoke( shard_definition.name )
225
+ Rake::Task["shards:schema:load"].reenable
226
+ end
227
+ end
228
+ end
229
+
230
+ # desc "Recreate the test database from the current environment's database schema"
231
+ task :clone => %w(shards:schema:dump shards:test:load)
232
+
233
+ # desc "Recreate the test databases from the development structure"
234
+ task :clone_structure, [:shard_name] => [ "shards:structure:dump", "shards:test:purge" ] do |t, args|
235
+ ActiveShard.with_environment( :test ) do
236
+ defs = active_shard_definitions( args )
237
+
238
+ defs.each do |shard_definition|
239
+ adapter = shard_definition.connection_adapter
240
+
241
+ case adapter
242
+ when /mysql/
243
+ with_shard( shard_definition.name ) do
244
+ ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
245
+ IO.readlines("#{Rails.root}/db/#{shard_definition.schema}_structure.sql").join.split("\n\n").each do |table|
246
+ ActiveRecord::Base.connection.execute(table)
247
+ end
248
+ end
249
+ when "postgresql", "sqlite", "sqlite3", "sqlserver", "oci", "oracle", "firebird"
250
+ active_shard_does_not_implement!( adapter )
251
+ else
252
+ raise "Task not supported by '#{adapter}'"
253
+ end
254
+ end
255
+ end
256
+ end
257
+
258
+ # desc "Empty the test database"
259
+ task :purge => :environment do
260
+ ActiveShard.with_environment( :test ) do
261
+ ActiveShard.shard_definitions.each do |shard_definition|
262
+ with_shard( shard_definition.name ) do |shard_name, schema|
263
+ adapter = ActiveShard.shard( shard_name ).connection_adapter
264
+
265
+ case adapter
266
+ when /mysql/
267
+ ActiveRecord::Base.connection.recreate_database(
268
+ shard_definition.connection_database,
269
+ shard_definition.connection_spec
270
+ )
271
+ when "postgresql", "sqlite", "sqlite3", "sqlserver", "oci", "oracle", "firebird"
272
+ active_shard_does_not_implement!( adapter )
273
+ else
274
+ raise "Task not supported by '#{abcs["test"]["adapter"]}'"
275
+ end
276
+ end
277
+ end
278
+ end
279
+ end
280
+
281
+ # desc 'Check for pending migrations and load the test schema'
282
+ task :prepare => :environment do
283
+ clone_schema
284
+ end
285
+ end
286
+ end
287
+
288
+ def dump_schema( *args )
289
+ Rake::Task[{ :sql => "shards:structure:dump", :ruby => "shards:schema:dump" }[ActiveRecord::Base.schema_format]].invoke(*args)
290
+ end
291
+
292
+ def clone_schema( *args )
293
+ Rake::Task[{ :sql => "shards:test:clone_structure", :ruby => "shards:test:load" }[ActiveRecord::Base.schema_format]].invoke(*args)
294
+ end
295
+
296
+ def active_shard_does_not_implement!( adapter )
297
+ raise "Unimplemented by ActiveShard at the moment. If someone using #{adapter} wants to fix this, that would be awesome!"
298
+ end
299
+
300
+ def active_shard_definitions( options={} )
301
+ shard_name = options[ :shard_name ]
302
+
303
+ if shard_name.blank?
304
+ ActiveShard.shard_definitions
305
+ else
306
+ ActiveShard::ShardCollection.new([ ActiveShard.shard( shard_name ) ])
307
+ end
308
+ end
309
+
310
+ def with_shard( args )
311
+ shard_name =
312
+ case args
313
+ when Symbol, String
314
+ args.to_sym
315
+ else
316
+ args[ :shard_name ].nil? ? nil : args[ :shard_name ].to_sym
317
+ end
318
+
319
+ raise "No shard specified. Please run with shard name, rake task[shard_name]" unless shard_name
320
+
321
+ schema = ActiveShard.shard( shard_name ).schema.to_sym
322
+
323
+ ActiveRecord::Base.send( :include, ActiveShard::ActiveRecord::ShardSupport )
324
+ ActiveRecord::Base.schema_name( schema )
325
+
326
+ ActiveShard.with( shard_name ) do
327
+ yield( shard_name, schema )
328
+ end
329
+ end
@@ -1,3 +1,3 @@
1
1
  module ActiveShard
2
- VERSION = '0.2.2'
2
+ VERSION = '0.2.3'
3
3
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: active_shard
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.2
5
+ version: 0.2.3
6
6
  platform: ruby
7
7
  authors:
8
8
  - Brasten Sager
@@ -45,6 +45,7 @@ files:
45
45
  - lib/active_shard/active_record.rb
46
46
  - lib/active_shard/config.rb
47
47
  - lib/active_shard/exceptions.rb
48
+ - lib/active_shard/rails/database.rake
48
49
  - lib/active_shard/railtie.rb
49
50
  - lib/active_shard/scope.rb
50
51
  - lib/active_shard/scope_manager.rb