ccls-use_db 0.9.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.
data/README.rdoc ADDED
@@ -0,0 +1,101 @@
1
+ = UseDb
2
+ by David Stevenson
3
+ ds@elctech.com
4
+
5
+ == USAGE
6
+
7
+ This plugin allows you to use multiple databases in your rails application.
8
+ You can switch the database for a model in the following manner:
9
+
10
+ class MyModel < ActiveRecord::Base
11
+ use_db :prefix => "secdb_", :suffix => "_cool"
12
+ end
13
+
14
+ "use_db" takes a prefix and a suffix (only 1 of which is required) which are prepended and appended onto the current RAILS_ENV.
15
+ In the above example, I would have to make the following database entries to my database.yml:
16
+
17
+ secdb_development_cool:
18
+ adapter: mysql
19
+ database: secdb_dev_db
20
+ ...
21
+
22
+ secdb_test_cool:
23
+ adapater: mysql
24
+ database: secdb_test_db
25
+ ...
26
+
27
+ It's often useful to create a single abstract model which all models using a different database extend from:
28
+
29
+ class SecdbBase < ActiveRecord::Base
30
+ use_db :prefix => "secdb_"
31
+ self.abstract_class = true
32
+ end
33
+
34
+ class MyModel < SecdbBase
35
+ # this model will use a different database automatically now
36
+ end
37
+
38
+ == MIGRATIONS
39
+
40
+ To write a migration which executes on a different database, add the following method to your
41
+ migration:
42
+
43
+ class MyMigration < ActiveRecord::Migration
44
+ def self.database_model
45
+ return "SecdbBase"
46
+ end
47
+
48
+ def self.up
49
+ ...
50
+ end
51
+
52
+ ...
53
+ end
54
+
55
+ The "self.database_model" call must return a string which is the name of the model whose connection
56
+ you want to borrow when performing the migration. If this method is undefined, the default ActiveRecord::Base
57
+ connection is used.
58
+
59
+ == TESTING
60
+
61
+ In order to test multiple databases, you must invoke a task which clones the development database
62
+ structure and copies it into the test database, clearing out the existing test data. There is a single
63
+ helper method which executes this task and you invoke it as follows:
64
+
65
+ UseDbTest.prepare_test_db(:prefix => "secdb_")
66
+
67
+ Even though it might not be the best place for it, I often place a call to this in my test helper.
68
+ You don't want it to execute for every test, so put the following guards around it:
69
+
70
+ unless defined?(CLONED_SEC_DB_FOR_TEST)
71
+ UseDbTest.prepare_test_db(:prefix => "secdb_")
72
+ CLONED_SEC_DB_FOR_TEST = true
73
+ end
74
+
75
+ == FIXTURES
76
+
77
+ Fixtures will automatically be loaded into the correct database as long as the fixture name corresponds
78
+ to the name of a model. For example, if I have a model called SecdbUser who uses a different database and
79
+ I create a fixture file called secdb_users.yml, the fixture loader will use whatever database connection
80
+ belongs to the SecdbUser model.
81
+
82
+ There is currently no other way to force a fixture to use a specific database (sorry, no join tables yet),
83
+ like there is for migrations.
84
+
85
+
86
+
87
+
88
+ == Gemified with Jeweler
89
+
90
+ vi Rakefile
91
+ rake version:write
92
+
93
+ rake version:bump:patch
94
+ rake version:bump:minor
95
+ rake version:bump:major
96
+
97
+ rake gemspec
98
+
99
+ rake install
100
+ rake release
101
+
@@ -0,0 +1 @@
1
+ require 'use_db'
@@ -0,0 +1,39 @@
1
+ #namespace :db do
2
+ # namespace :structure do
3
+ # task :dump_use_db do
4
+ # UseDbTest.other_databases.each do |options|
5
+ # puts "DUMPING TEST DB: #{options.inspect}" if UseDbPlugin.debug_print
6
+ # UseDbTest.dump_db_structure(options)
7
+ # end
8
+ # end
9
+ # end
10
+ #
11
+ # namespace :test do
12
+ # task :clone_structure => "db:test:clone_structure_use_db"
13
+ #
14
+ # task :clone_structure_use_db => ["db:structure:dump_use_db","db:test:purge_use_db"] do
15
+ # UseDbTest.other_databases.each do |options|
16
+ # puts "CLONING TEST DB: #{options.inspect}" if UseDbPlugin.debug_print
17
+ # UseDbTest.clone_db_structure(options)
18
+ # end
19
+ # end
20
+ #
21
+ # task :purge_use_db => "db:test:purge" do
22
+ # UseDbTest.other_databases.each do |options|
23
+ # puts "PURGING TEST DB: #{options.inspect}" if UseDbPlugin.debug_print
24
+ # UseDbTest.purge_db(options)
25
+ # end
26
+ # end
27
+ # end
28
+ #end
29
+
30
+ require 'use_db'
31
+ # without this, the extra databases don't load
32
+ # I'd like to find another way though
33
+ Rake::Task[:rails_env].prerequisites.unshift(:environment )
34
+
35
+ #namespace :test do
36
+ # task :units => "db:test:clone_structure_use_db"
37
+ # task :functionals => "db:test:clone_structure_use_db"
38
+ # task :integrations => "db:test:clone_structure_use_db"
39
+ #end
data/lib/use_db.rb ADDED
@@ -0,0 +1,13 @@
1
+ module UseDb
2
+ # predefine namespace
3
+ end
4
+ require 'active_record'
5
+ require 'active_record/fixtures'
6
+ require 'active_record/migration'
7
+ require 'use_db/configurations'
8
+ require 'use_db/use_db_plugin'
9
+ require 'use_db/use_db_test'
10
+ require 'use_db/test_model'
11
+ require 'use_db/override_fixtures'
12
+ require 'use_db/override_test_case'
13
+ require 'use_db/migration'
@@ -0,0 +1,35 @@
1
+ #
2
+ # include the other (potential) database.yml files
3
+ #
4
+ module UseDb::Configurations
5
+
6
+ def self.included(base)
7
+ unless base.respond_to?(:configurations_with_other_dbs)
8
+ base.extend(ClassMethods)
9
+ base.class_eval do
10
+ class << self
11
+ alias_method_chain :configurations, :other_dbs
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ module ClassMethods
18
+
19
+ def configurations_with_other_dbs
20
+ # puts "In configurations with other dbs"
21
+ if configurations_without_other_dbs.empty?
22
+ # for rake tasks
23
+ configurations_without_other_dbs.update(YAML::load(ERB.new(IO.read(
24
+ File.join( Rails.root,'config','database.yml'))).result))
25
+ end
26
+ OTHER_DB_FILES.each do |f|
27
+ configurations_without_other_dbs.update(YAML::load(ERB.new(IO.read(f)).result))
28
+ end if defined?(OTHER_DB_FILES)
29
+ configurations_without_other_dbs
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ ActiveRecord::Base.send(:include,UseDb::Configurations)
@@ -0,0 +1,89 @@
1
+ module UseDb::Migration
2
+
3
+ def self.included(base)
4
+ unless base.respond_to?(:method_missing_without_connection_swap)
5
+ base.extend(ClassMethods)
6
+ base.class_eval do
7
+ class << self
8
+ alias_method_chain :method_missing, :connection_swap
9
+ end
10
+ end
11
+ end
12
+ end
13
+
14
+ module ClassMethods
15
+
16
+ def method_missing_with_connection_swap(method, *arguments, &block)
17
+ say_with_time "#{method}(#{arguments.map { |a| a.inspect }.join(", ")})" do
18
+ arguments[0] = ActiveRecord::Migrator.proper_table_name(arguments.first
19
+ ) unless arguments.empty? || method == :execute
20
+ if (self.respond_to?(:database_model))
21
+ write "Using custom database model's connection (#{self.database_model}) for this migration"
22
+ eval("#{self.database_model}.connection.send(method, *arguments, &block)")
23
+ else
24
+ ActiveRecord::Base.connection.send(method, *arguments, &block)
25
+ # method_missing_without_connection_swap(method, *arguments, &block)
26
+ end
27
+ end
28
+ end
29
+
30
+ def uses_db?
31
+ true
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+ ActiveRecord::Migration.send(:include,UseDb::Migration)
38
+
39
+ module UseDb::Migrator
40
+
41
+ def self.included(base)
42
+ unless base.respond_to?(:get_all_versions_without_connection_swap)
43
+ base.extend(ClassMethods)
44
+ base.alias_method_chain( :record_version_state_after_migrating, :connection_swap
45
+ ) unless base.methods.include?(:record_version_state_after_migrating_without_connection_swap)
46
+ base.class_eval do
47
+ class << self
48
+ alias_method_chain :get_all_versions, :connection_swap
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ module ClassMethods
55
+
56
+ def get_all_versions_with_connection_swap
57
+ # puts "in use_db get_all_versions"
58
+ # Base.connection.select_values("SELECT version FROM #{schema_migrations_table_name}").map(&:to_i).sort
59
+ UseDbPlugin.all_use_dbs.collect(&:connection).collect{|c|
60
+ c.initialize_schema_migrations_table # in case it doesn't exist
61
+ c.select_values("SELECT version FROM #{schema_migrations_table_name}").map(&:to_i)
62
+ }.flatten.uniq.sort
63
+ end
64
+
65
+ end
66
+
67
+ def record_version_state_after_migrating_with_connection_swap(version)
68
+ just_migrated = migrations.detect { |m| m.version == version }
69
+ load(just_migrated.filename)
70
+ migration_model = just_migrated.name.constantize
71
+ if migration_model.respond_to?(:database_model)
72
+ ar_model = migration_model.database_model.constantize
73
+ ar_model.connection.initialize_schema_migrations_table
74
+ sm_table = self.class.schema_migrations_table_name
75
+ @migrated_versions ||= []
76
+ if down?
77
+ @migrated_versions.delete(version.to_i)
78
+ ar_model.connection.update("DELETE FROM #{sm_table} WHERE version = '#{version}'")
79
+ else
80
+ @migrated_versions.push(version.to_i).sort!
81
+ ar_model.connection.insert("INSERT INTO #{sm_table} (version) VALUES ('#{version}')")
82
+ end
83
+ else
84
+ record_version_state_after_migrating_without_connection_swap(version)
85
+ end
86
+ end
87
+
88
+ end
89
+ ActiveRecord::Migrator.send(:include,UseDb::Migrator)
@@ -0,0 +1,18 @@
1
+ #
2
+ # Put the fixtures in the correct database
3
+ #
4
+ module UseDb::Fixtures
5
+
6
+ def self.included(base)
7
+ unless base.respond_to?(:read_fixture_files_without_connection_set)
8
+ base.alias_method_chain :read_fixture_files, :connection_set
9
+ end
10
+ end
11
+
12
+ def read_fixture_files_with_connection_set
13
+ @connection = (model_class||ActiveRecord::Base).connection
14
+ read_fixture_files_without_connection_set
15
+ end
16
+
17
+ end
18
+ Fixtures.send(:include,UseDb::Fixtures)
@@ -0,0 +1,63 @@
1
+ #
2
+ # setup and teardown fixtures in all databases
3
+ #
4
+ module UseDb::TestFixtures
5
+
6
+ def self.included(base)
7
+ base.alias_method_chain :setup_fixtures, :use_db
8
+ base.alias_method_chain :teardown_fixtures, :use_db
9
+ end
10
+
11
+ def setup_fixtures_with_use_db
12
+ UseDbPlugin.all_use_dbs.collect do |klass|
13
+ return unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
14
+
15
+ if pre_loaded_fixtures && !use_transactional_fixtures
16
+ raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures'
17
+ end
18
+
19
+ @fixture_cache = {}
20
+ @@already_loaded_fixtures ||= {}
21
+
22
+ # Load fixtures once and begin transaction.
23
+ if run_in_transaction?
24
+ if @@already_loaded_fixtures[self.class]
25
+ @loaded_fixtures = @@already_loaded_fixtures[self.class]
26
+ else
27
+ load_fixtures
28
+ @@already_loaded_fixtures[self.class] = @loaded_fixtures
29
+ end
30
+ klass.connection.increment_open_transactions
31
+ klass.connection.transaction_joinable = false
32
+ klass.connection.begin_db_transaction
33
+ # Load fixtures for every test.
34
+ else
35
+ Fixtures.reset_cache
36
+ @@already_loaded_fixtures[self.class] = nil
37
+ load_fixtures
38
+ end
39
+
40
+ # Instantiate fixtures for every test if requested.
41
+ instantiate_fixtures if use_instantiated_fixtures
42
+ end
43
+ end
44
+
45
+ def teardown_fixtures_with_use_db
46
+ UseDbPlugin.all_use_dbs.collect do |klass|
47
+ return unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
48
+
49
+ unless run_in_transaction?
50
+ Fixtures.reset_cache
51
+ end
52
+
53
+ # Rollback changes if a transaction is active.
54
+ if run_in_transaction? && klass.connection.open_transactions != 0
55
+ klass.connection.rollback_db_transaction
56
+ klass.connection.decrement_open_transactions
57
+ end
58
+ klass.clear_active_connections!
59
+ end
60
+ end
61
+
62
+ end
63
+ ActiveRecord::TestFixtures.send(:include,UseDb::TestFixtures)
@@ -0,0 +1,2 @@
1
+ require 'use_db'
2
+ Dir["#{File.dirname(__FILE__)}/../tasks/**/*.rake"].sort.each { |ext| load ext }
@@ -0,0 +1,11 @@
1
+ def create_test_model(model_name, prefix="", suffix="", rails_env=RAILS_ENV)
2
+ # puts "Creating test model '#{model_name}', :prefix => '#{prefix}', :suffix => '#{suffix}'"
3
+ str = <<-EOF
4
+ require "use_db"
5
+
6
+ class #{model_name} < ActiveRecord::Base
7
+ use_db :prefix => "#{prefix}", :suffix => "#{suffix}", :rails_env => "#{rails_env}"
8
+ end
9
+ EOF
10
+ eval(str)
11
+ end
@@ -0,0 +1,63 @@
1
+ module UseDbPlugin
2
+ # options can have one or the other of the following options:
3
+ # :prefix - Specify the prefix to append to the RAILS_ENV when finding the adapter secification in database.yml
4
+ # :suffix - Just like :prefix, only contactentated
5
+ # OR
6
+ # :adapter
7
+ # :host
8
+ # :username
9
+ # :password
10
+ # ... etc ... same as the options in establish_connection
11
+ #
12
+ # Set the following to true in your test environment
13
+ # to enable extended debugging printing during testing ...
14
+ # UseDbPlugin.debug_print = true
15
+ #
16
+
17
+ @@use_dbs = [ActiveRecord::Base]
18
+ @@debug_print = false
19
+
20
+ def use_db(options)
21
+ options_dup = options.dup
22
+ conn_spec = get_use_db_conn_spec(options)
23
+ puts "Establishing connecting on behalf of #{self.to_s} to #{conn_spec.inspect}" if UseDbPlugin.debug_print
24
+ establish_connection(conn_spec)
25
+ extend ClassMixin
26
+ @@use_dbs << self unless @@use_dbs.include?(self) || self.to_s.starts_with?("TestModel")
27
+ end
28
+
29
+ def self.all_use_dbs
30
+ return @@use_dbs
31
+ end
32
+
33
+ def self.debug_print
34
+ return @@debug_print
35
+ end
36
+
37
+ def self.debug_print=(newval)
38
+ @@debug_print = newval
39
+ end
40
+
41
+ module ClassMixin
42
+ def uses_db?
43
+ true
44
+ end
45
+ end
46
+
47
+ def get_use_db_conn_spec(options)
48
+ options.symbolize_keys! # without the bang, this was pointless
49
+ suffix = options.delete(:suffix)
50
+ prefix = options.delete(:prefix)
51
+ rails_env = options.delete(:rails_env) || RAILS_ENV
52
+ if (options[:adapter])
53
+ return options
54
+ else
55
+ str = "#{prefix}#{rails_env}#{suffix}"
56
+ connections = ActiveRecord::Base.configurations
57
+ raise "Cannot find database specification. Configuration '#{str}' expected in config/database.yml" if (connections[str].nil?)
58
+ return connections[str]
59
+ end
60
+ end
61
+
62
+ end
63
+ ActiveRecord::Base.extend(UseDbPlugin)
@@ -0,0 +1,61 @@
1
+ class UseDbTest
2
+
3
+ extend UseDbPlugin
4
+
5
+ def self.other_databases
6
+ use_db_config = (defined?(USE_DB_CONFIG)) ? USE_DB_CONFIG : "#{RAILS_ROOT}/config/use_db.yml"
7
+ YAML.load(File.read(use_db_config)).values.collect(&:symbolize_keys!)
8
+ end
9
+
10
+ def self.prepare_test_db(options={})
11
+ schema_dump(options)
12
+ schema_load(options)
13
+ end
14
+
15
+ def self.schema_dump(options)
16
+ # puts "In schema_dump"
17
+ options_dup = options.dup
18
+ options_dup[:rails_env] = "development"
19
+ conn_spec = get_use_db_conn_spec(options_dup)
20
+ test_class = setup_test_model(options[:prefix], options[:suffix], "ForSchemaDump")
21
+ test_class.establish_connection(conn_spec)
22
+ require 'active_record/schema_dumper'
23
+ File.open(schema_file(options), "w") do |file|
24
+ ActiveRecord::SchemaDumper.dump(test_class.connection, file)
25
+ end
26
+ end
27
+
28
+ def self.schema_load(options)
29
+ # puts "In schema_load"
30
+ options_dup = options.dup
31
+ conn_spec = get_use_db_conn_spec(options_dup)
32
+ ActiveRecord::Base.establish_connection(conn_spec)
33
+ file = schema_file(options)
34
+ # database.rake suggests that I should purge first, but why?
35
+ # the schema is :force => true and will wipe everything out anyway.
36
+ # using schema seems a better option than to the DSL that it came from.
37
+ if File.exists?(file)
38
+ # puts "loading #{file}"
39
+ ActiveRecord::Schema.verbose = UseDbPlugin.debug_print
40
+ load(file)
41
+ ActiveRecord::Base.connection.disconnect!
42
+ ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations["test"])
43
+ else
44
+ 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/environment.rb to prevent active_record from loading: config.frameworks -= [ :active_record ]}
45
+ end
46
+ end
47
+
48
+ def self.setup_test_model(prefix="", suffix="", model_suffix="", rails_env=RAILS_ENV)
49
+ prefix ||= ""
50
+ suffix ||= ""
51
+ model_name = "TestModel#{prefix.camelize}#{suffix.camelize}#{model_suffix}".gsub("_","").gsub("-","")
52
+ return eval(model_name) if eval("defined?(#{model_name})")
53
+ create_test_model(model_name, prefix, suffix, rails_env)
54
+ return eval(model_name)
55
+ end
56
+
57
+ def self.schema_file(options)
58
+ "#{RAILS_ROOT}/db/#{RAILS_ENV}_#{options[:prefix]}_#{options[:suffix]}_schema.rb"
59
+ end
60
+
61
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require "ccls-use_db"
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ccls-use_db
3
+ version: !ruby/object:Gem::Version
4
+ hash: 61
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 9
9
+ - 3
10
+ version: 0.9.3
11
+ platform: ruby
12
+ authors:
13
+ - David Stevenson
14
+ - George 'Jake' Wendt
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-10-12 00:00:00 -07:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: rails
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ hash: 7
31
+ segments:
32
+ - 2
33
+ version: "2"
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ description: Gem version of use_db rails plugin
37
+ email: github@jakewendt.com
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files:
43
+ - README.rdoc
44
+ files:
45
+ - lib/ccls-use_db.rb
46
+ - lib/tasks/use_db_tasks.rake
47
+ - lib/use_db.rb
48
+ - lib/use_db/configurations.rb
49
+ - lib/use_db/migration.rb
50
+ - lib/use_db/override_fixtures.rb
51
+ - lib/use_db/override_test_case.rb
52
+ - lib/use_db/tasks.rb
53
+ - lib/use_db/test_model.rb
54
+ - lib/use_db/use_db_plugin.rb
55
+ - lib/use_db/use_db_test.rb
56
+ - rails/init.rb
57
+ - README.rdoc
58
+ has_rdoc: true
59
+ homepage: http://github.com/ccls/use_db
60
+ licenses: []
61
+
62
+ post_install_message:
63
+ rdoc_options: []
64
+
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 3
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ hash: 3
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ requirements: []
86
+
87
+ rubyforge_project:
88
+ rubygems_version: 1.6.2
89
+ signing_key:
90
+ specification_version: 3
91
+ summary: Gem version of use_db rails plugin
92
+ test_files: []
93
+