secondbase 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "shoulda", ">= 0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.5.1"
12
+ gem "activerecord", "~> 3.0.0"
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,34 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activemodel (3.0.0)
5
+ activesupport (= 3.0.0)
6
+ builder (~> 2.1.2)
7
+ i18n (~> 0.4.1)
8
+ activerecord (3.0.0)
9
+ activemodel (= 3.0.0)
10
+ activesupport (= 3.0.0)
11
+ arel (~> 1.0.0)
12
+ tzinfo (~> 0.3.23)
13
+ activesupport (3.0.0)
14
+ arel (1.0.1)
15
+ activesupport (~> 3.0.0)
16
+ builder (2.1.2)
17
+ git (1.2.5)
18
+ i18n (0.4.1)
19
+ jeweler (1.5.1)
20
+ bundler (~> 1.0.0)
21
+ git (>= 1.2.5)
22
+ rake
23
+ rake (0.8.7)
24
+ shoulda (2.11.1)
25
+ tzinfo (0.3.23)
26
+
27
+ PLATFORMS
28
+ ruby
29
+
30
+ DEPENDENCIES
31
+ activerecord (~> 3.0.0)
32
+ bundler (~> 1.0.0)
33
+ jeweler (~> 1.5.1)
34
+ shoulda
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 karledurante
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,108 @@
1
+ = secondbase
2
+
3
+ SecondBase adds a second database to your application. While Rails enables you to establish connections to as many external databases as you like, Rails can only manage a single database with it's migration and testing tasks.
4
+
5
+ Secondbase enables Rails to work with, and manage, a second database (almost) transparently. As a developer, you should not even realize a second database is in play. Core rake tasks such as db:create, db:migrate, and test will continue to work seamlessly with both databases without you, the developer, having to run any extra rake tasks.
6
+
7
+ == Contributing to secondbase
8
+
9
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
10
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
11
+ * Fork the project
12
+ * Start a feature/bugfix branch
13
+ * Commit and push until you are happy with your contribution
14
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
15
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
16
+
17
+ == System Requirements
18
+ Secondbase requires Rails 3.x. This is mainly because it was easier to include the rake tasks into your Rails application root. With that being said, it would not be hard to port this to Rails 2.x, you simply need to manually modify your Rakefile to require 'secondbase/tasks'.
19
+
20
+ If you have the time to update this gem to be backward compatible, by all means...
21
+
22
+
23
+ == Installation
24
+ Modify your Gemfile to include Secondbase:
25
+
26
+ gem 'secondbase', '0.1.0'
27
+
28
+ Run `bundle install`. You thought it would be harder?
29
+
30
+ == Usage
31
+ === Database
32
+ - setting up database.yml
33
+
34
+
35
+ === Migrations
36
+ SecondBase comes with a generator to assist in managing your migrations
37
+
38
+ rails generator secondbase:migration CreateWidgetsTable
39
+
40
+ The generator will organize your second (data)base migrations alongside of your primary database. The above command will generate the file:
41
+
42
+ db/migrate/secondbase/20101203211338_create_widgets_table.rb
43
+
44
+ To run your migrations, simply run:
45
+
46
+ rake db:migrate
47
+
48
+ This will migrate your first and second (data)bases. If, for some reason, you only want to migrate your second (data)base, run:
49
+
50
+ rake db:migrate:secondbase
51
+
52
+ Please note that migrating up and migrating down must be done specifically on your first or second (data)base. As usual, to migrate your first (data)base up or down to version 20101203211338, you could run:
53
+
54
+ rake db:migrate:up VERSION=20101005311335
55
+ rake db:migrate:down VERSION=20101005311335
56
+
57
+ To migrate your second (data)base up or down to version 20101203211338, you would run:
58
+
59
+ rake db:migrate:up:secondbase VERSION=20101203211338
60
+ rake db:migrate:down:secondbase VERSION=20101203211338
61
+
62
+
63
+ === Models
64
+ Every model in your project that extends ActiveRecord::Base will point to the database defined by Rails.env. This is the default Rails behavior and should be of no surprise to you. So how do we point our models to the second (data)base?
65
+
66
+ SecondBase offers a base model that you can simply extend:
67
+
68
+ require 'secondbase/model'
69
+
70
+ class Widget < SecondBase::Base
71
+ # you're Widget model is now pointing to your second (data)base table 'widgets'
72
+ end
73
+
74
+ === Rake Tasks & Custom Classes
75
+ If you need to write rake tasks, or some other code that does not extend ActiveRecord, you can simply establish a connection to your second (data)base:
76
+
77
+ SecondBase::has_runner(Rails.env)
78
+
79
+ Please note that this is equivalent to using ActiveRecord::Base.establish_connection(config) and will reset the base connection of your ENTIRE application. No worries, to move the runner back to first you can use:
80
+
81
+ FirstBase::has_runner(Rails.env)
82
+
83
+ === Testing
84
+ Tests can still be run using `rake test` or `rake test:units`, etc. However, if you are using fixtures, you will need to update your TestHelper class to include:
85
+
86
+ require 'secondbase/fixtures'
87
+
88
+ This is patch to fixtures that will identify the fixtures which belong to models that extend SecondBase::Base. The patch will then ensure that the table descendants of SecondBase::Base get loaded into your second test (data)base.
89
+
90
+ At this time, there is not support for anything other than fixtures (i.e. factories). If you have the time to update this gem to be test object compatible, by all means...
91
+
92
+ == TODO
93
+ - We should support Rails 2.x as well as 3.x
94
+
95
+ - Migration generator needs support for attribute generation (similar to rails generate migration). For example:
96
+ `rails generate secondbase_migration AddTitleBodyToPost title:string body:text published:boolean`
97
+
98
+ - rake db:fixtures:load is currently broken. Like many other things I have fixed, it assumes you only one a single database and attempts to load all fixtures into it. I don't believe we can get away with alias chaining this one, I think (like the Fixtures class), we'll have to freedom patch it.
99
+
100
+ - secondbase should provide support for testing objects other then fixtures
101
+
102
+ - TESTS!! Not 100% sure how to test the rake tasks, but I can definitely write tests for the classes and generators. I did this in my spare time, sorry...
103
+
104
+ == Copyright
105
+
106
+ Copyright (c) 2010 karledurante. See LICENSE.txt for
107
+ further details.
108
+
data/Rakefile ADDED
@@ -0,0 +1,46 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "secondbase"
16
+ gem.homepage = "http://github.com/karledurante/secondbase"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{Allow Rails manage second database in your projects}
19
+ gem.description = %Q{Secondbase provides support to Rails to create a homogeneous for a dual database project. Using the rake tasks already familiar to you, this gem enables Rails to work with two primary databases, instead of just one.}
20
+ gem.email = "kdurante@customink.com"
21
+ gem.authors = ["karledurante"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rake/testtask'
30
+ Rake::TestTask.new(:test) do |test|
31
+ test.libs << 'lib' << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+
36
+ task :default => :test
37
+
38
+ require 'rake/rdoctask'
39
+ Rake::RDocTask.new do |rdoc|
40
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
41
+
42
+ rdoc.rdoc_dir = 'rdoc'
43
+ rdoc.title = "secondbase #{version}"
44
+ rdoc.rdoc_files.include('README*')
45
+ rdoc.rdoc_files.include('lib/**/*.rb')
46
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,34 @@
1
+ Description:
2
+ Stubs out a new (second)database migration. Pass the migration name, either
3
+ CamelCased or under_scored, and an optional list of attribute pairs as arguments.
4
+
5
+ For your organizational convenience, a migration class is generated in
6
+ db/migrate/secondbase prefixed by a timestamp of the current date and time.
7
+
8
+ You can name your migration in either of these formats to generate add/remove
9
+ column lines from supplied attributes: AddColumnsToTable or RemoveColumnsFromTable
10
+
11
+ Example:
12
+ `rails generate secondbase_migration AddSslFlag`
13
+
14
+ If the current date is May 14, 2008 and the current time 09:09:12, this creates the AddSslFlag migration
15
+ db/migrate/secondbase/20080514090912_add_ssl_flag.rb
16
+
17
+ `rails generate secondbase_migration AddTitleBodyToPost title:string body:text published:boolean`
18
+
19
+ This will create the AddTitleBodyToPost in db/migrate/secondbase/20080514090912_add_title_body_to_post.rb with
20
+ this in the Up migration:
21
+
22
+ add_column :posts, :title, :string
23
+ add_column :posts, :body, :text
24
+ add_column :posts, :published, :boolean
25
+
26
+ And this in the Down migration:
27
+
28
+ remove_column :posts, :published
29
+ remove_column :posts, :body
30
+ remove_column :posts, :title
31
+
32
+ You can continue to use `rake db:migrate` to migrate your first and second databases, or you can
33
+ target secondbase by using `rake db:migrate:secondbase`. Remember, your migrations are timestamped,
34
+ so regardless of the database they target, they will be unique and you will not have collision issues.
@@ -0,0 +1,38 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+ require 'active_record'
4
+
5
+ module Secondbase
6
+ class MigrationGenerator < Rails::Generators::NamedBase
7
+ include Rails::Generators::Migration
8
+
9
+ def self.source_root
10
+ File.join(File.dirname(__FILE__), 'templates')
11
+ end
12
+
13
+ # Implement the required interface for Rails::Generators::Migration.
14
+ # taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
15
+ def self.next_migration_number(dirname) #:nodoc:
16
+ if ActiveRecord::Base.timestamped_migrations
17
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
18
+ else
19
+ "%.3d" % (current_migration_number(dirname) + 1)
20
+ end
21
+ end
22
+
23
+ def create_migration_file
24
+ migration_template 'migration.rb',
25
+ "db/migrate/#{SecondBase::CONNECTION_PREFIX}/#{class_name.underscore}.rb",
26
+ :assigns => get_local_assigns
27
+ end
28
+
29
+ private
30
+ # TODO: We need to add support for name/value pairs like title:string dob:date etc..
31
+ def get_local_assigns
32
+ returning(assigns = {}) do
33
+ assigns[:class_name] = class_name
34
+ end
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,13 @@
1
+ class <%= class_name.underscore.camelize %> < ActiveRecord::Migration
2
+ ############################################################
3
+ # Database migration targeting the SecondBase!
4
+ # Generated using: rails generator secondbase:migration [MigrationName]
5
+
6
+ def self.up
7
+
8
+ end
9
+
10
+ def self.down
11
+
12
+ end
13
+ end
data/lib/secondbase.rb ADDED
@@ -0,0 +1,32 @@
1
+ require 'active_record'
2
+
3
+ module SecondBase
4
+ CONNECTION_PREFIX = 'secondbase'
5
+
6
+ require 'secondbase/railtie' if defined?(Rails)
7
+ require 'secondbase/rake_method_chain'
8
+
9
+ def self.do
10
+ "You have just gotten to SecondBase, my friend."
11
+ end
12
+
13
+
14
+ def self.has_runner(env)
15
+ ActiveRecord::Base.establish_connection(SecondBase::config(env))
16
+ end
17
+
18
+ def self.config(env)
19
+ ActiveRecord::Base.configurations[SecondBase::CONNECTION_PREFIX][env]
20
+ end
21
+
22
+ end
23
+
24
+ module FirstBase
25
+ def self.config(env)
26
+ ActiveRecord::Base.configurations[env]
27
+ end
28
+
29
+ def self.has_runner(env)
30
+ ActiveRecord::Base.establish_connection(FirstBase::config(env))
31
+ end
32
+ end
@@ -0,0 +1,68 @@
1
+ require 'secondbase/model'
2
+
3
+ ###########################
4
+ # Monkey patch Fixtures
5
+ # Fixtures needs to load fixtures into the database defined by the parent class!
6
+ #
7
+ # I feel like the concepts here could be incorporated directly into Fixtures.
8
+ # I mean, they shouldn't be so presumptions to think that every model lives in the
9
+ # same database....
10
+ class Fixtures
11
+ def self.create_fixtures(fixtures_directory, table_names, class_names = {})
12
+ table_names = [table_names].flatten.map { |n| n.to_s }
13
+ table_names.each { |n| class_names[n.tr('/', '_').to_sym] = n.classify if n.include?('/') }
14
+ connection = block_given? ? yield : ActiveRecord::Base.connection
15
+
16
+ # make sure we only load secondbase tables that have fixtures defined...
17
+ sb_table_names = SecondBase::Base.send(:descendants).map(&:table_name)
18
+ sb_table_names = sb_table_names & table_names
19
+ sb_connection = SecondBase::Base.connection
20
+
21
+ # filter out the secondbase tables from firstbase, otherwise we'll get SQL errors...
22
+ table_names_to_fetch = table_names.reject { |table_name| fixture_is_cached?(connection, table_name) || sb_table_names.include?(table_name) }
23
+ fixtures = process_fixture_table_names(table_names_to_fetch, class_names, connection, fixtures_directory)
24
+ fixtures = [fixtures] if !fixtures.instance_of?(Array)
25
+
26
+ sb_table_names_to_fetch = sb_table_names.reject { |table_name| fixture_is_cached?(sb_connection, table_name)}
27
+ sb_fixtures = process_fixture_table_names(sb_table_names_to_fetch, class_names, sb_connection, fixtures_directory)
28
+ sb_fixtures = [sb_fixtures] if !sb_fixtures.instance_of?(Array)
29
+
30
+ (fixtures + sb_fixtures).compact
31
+ end
32
+
33
+ def self.process_fixture_table_names(table_names_to_fetch, class_names, connection, fixtures_directory)
34
+ fixtures_map = {}
35
+ unless table_names_to_fetch.empty?
36
+ ActiveRecord::Base.silence do
37
+ connection.disable_referential_integrity do
38
+ # fixtures_map = {}
39
+
40
+ fixtures = table_names_to_fetch.map do |table_name|
41
+ obj = Fixtures.new(connection, table_name.tr('/', '_'), class_names[table_name.tr('/', '_').to_sym], File.join(fixtures_directory, table_name))
42
+ fixtures_map[table_name] = obj
43
+ end
44
+
45
+ all_loaded_fixtures.update(fixtures_map)
46
+
47
+ connection.transaction(:requires_new => true) do
48
+ fixtures.reverse.each { |fixture| fixture.delete_existing_fixtures }
49
+ fixtures.each { |fixture| fixture.insert_fixtures }
50
+
51
+ # Cap primary key sequences to max(pk).
52
+ if connection.respond_to?(:reset_pk_sequence!)
53
+ table_names_to_fetch.each do |table_name|
54
+ connection.reset_pk_sequence!(table_name.tr('/', '_'))
55
+ end
56
+ end
57
+ end
58
+
59
+ cache_fixtures(connection, fixtures_map)
60
+ end
61
+ end
62
+ end
63
+
64
+ table_names_to_fetch = nil if table_names_to_fetch.blank?
65
+ cached_fixtures(connection, table_names_to_fetch)
66
+ end
67
+
68
+ end
@@ -0,0 +1,12 @@
1
+ # Secondbase model definition
2
+ #
3
+ # NOTE: By extending this model, you assume that the underlying table will be located in your Second (Data)base
4
+ module SecondBase
5
+ require 'active_record'
6
+
7
+ class Base < ActiveRecord::Base
8
+ establish_connection ActiveRecord::Base.configurations[CONNECTION_PREFIX][Rails.env]
9
+
10
+ self.abstract_class = true
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ require 'secondbase'
2
+ require 'rails'
3
+ module SecondBase
4
+ class Railtie < Rails::Railtie
5
+
6
+ rake_tasks do
7
+ load "tasks/secondbase.rake"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,22 @@
1
+ require 'rake'
2
+
3
+ # We want to provide a way to alias tasks so we can hook our custom logic
4
+ # into the existing rails framework. For more information and usage, see:
5
+ # http://www.metaskills.net/2010/5/26/the-alias_method_chain-of-rake-override-rake-task
6
+ Rake::TaskManager.class_eval do
7
+ def alias_task(fq_name)
8
+ new_name = "#{fq_name}:original"
9
+ @tasks[new_name] = @tasks.delete(fq_name)
10
+ end
11
+ end
12
+
13
+ def alias_task(fq_name)
14
+ Rake.application.alias_task(fq_name)
15
+ end
16
+
17
+ def override_task(*args, &block)
18
+ name, params, deps = Rake.application.resolve_args(args.dup)
19
+ fq_name = Rake.application.instance_variable_get(:@scope).dup.push(name).join(':')
20
+ alias_task(fq_name)
21
+ Rake::Task.define_task(*args, &block)
22
+ end
@@ -0,0 +1,194 @@
1
+ require 'secondbase'
2
+ ####################################
3
+ #
4
+ # SecondBase database managment tasks
5
+ #
6
+ # We are overriding a handful of rake tasks here:
7
+ # db:create
8
+ # db:migrate
9
+ # db:test:prepare
10
+ #
11
+ # We ARE NOT redefining the implementation of these tasks, we are simply
12
+ # appending custom functionality to them. We just want to be sure that in
13
+ # addition to creating, migrating, and preparing your default (Rails.env)
14
+ # database, that we can also work with with the second (data)base.
15
+
16
+ namespace :db do
17
+ override_task :create do
18
+ # First, we execute the original/default create task
19
+ Rake::Task["db:create:original"].invoke
20
+
21
+ # now, we create our secondary databases
22
+ Rake::Task['environment'].invoke
23
+ ActiveRecord::Base.configurations[SecondBase::CONNECTION_PREFIX].each_value do |config|
24
+ next unless config['database']
25
+
26
+ # Only connect to local databases
27
+ local_database?(config) { create_database(config) }
28
+ end
29
+ end
30
+
31
+ override_task :migrate do
32
+ Rake::Task['environment'].invoke
33
+
34
+ # Migrate secondbase...
35
+ Rake::Task["db:migrate:secondbase"].invoke
36
+
37
+ # Execute the original/default prepare task
38
+ Rake::Task["db:migrate:original"].invoke
39
+ end
40
+
41
+ namespace :test do
42
+ override_task :prepare do
43
+ Rake::Task['environment'].invoke
44
+
45
+ # Clone the secondary database structure
46
+ Rake::Task["db:test:prepare:secondbase"].invoke
47
+
48
+ # Execute the original/default prepare task
49
+ Rake::Task["db:test:prepare:original"].invoke
50
+ end
51
+ end
52
+
53
+ ##################################
54
+ # SecondBase specific database tasks
55
+ namespace :migrate do
56
+ desc "migrates the second database"
57
+ task :secondbase => :load_config do
58
+ Rake::Task['environment'].invoke
59
+ # NOTE: We are not generating a db schema on purpose. Since we're running
60
+ # in a dual db mode, it could be confusing to have two schemas.
61
+
62
+ # reset connection to secondbase...
63
+ use_secondbase(Rails.env)
64
+
65
+ # run secondbase migrations...
66
+ ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
67
+ ActiveRecord::Migrator.migrate("db/migrate/#{SecondBase::CONNECTION_PREFIX}/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
68
+
69
+ # reset connection back to firstbase...
70
+ use_firstbase(Rails.env)
71
+ end
72
+
73
+ namespace :up do
74
+ desc 'Runs the "up" for a given SecondBase migration VERSION.'
75
+ task :secondbase => :environment do
76
+ version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
77
+ raise "VERSION is required" unless version
78
+
79
+ # reset connection to secondbase...
80
+ use_secondbase(Rails.env)
81
+
82
+ ActiveRecord::Migrator.run(:up, "db/migrate/#{SecondBase::CONNECTION_PREFIX}/", version)
83
+
84
+ # reset connection back to firstbase...
85
+ use_firstbase(Rails.env)
86
+ end
87
+ end
88
+
89
+ namespace :down do
90
+ desc 'Runs the "down" for a given SecondBase migration VERSION.'
91
+ task :secondbase => :environment do
92
+ version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
93
+ raise "VERSION is required" unless version
94
+
95
+ # reset connection to secondbase...
96
+ use_secondbase(Rails.env)
97
+
98
+ ActiveRecord::Migrator.run(:down, "db/migrate/#{SecondBase::CONNECTION_PREFIX}/", version)
99
+
100
+ # reset connection back to firstbase...
101
+ use_firstbase(Rails.env)
102
+ end
103
+ end
104
+ end
105
+
106
+ namespace :create do
107
+ desc 'Create the database defined in config/database.yml for the current RAILS_ENV'
108
+ task :secondbase => :load_config do
109
+
110
+ # We can still use the #create_database method defined in activerecord's databases.rake
111
+ # we call it passing the secondbase config instead of the default (Rails.env) config...
112
+ create_database(secondbase_config(Rails.env))
113
+ end
114
+ end
115
+
116
+ namespace :structure do
117
+ namespace :dump do
118
+ desc "dumps structure for both (first and second) databases."
119
+ task :secondbase do
120
+ Rake::Task['environment'].invoke
121
+
122
+ # we want to dump the development (second)database....
123
+ use_secondbase('development')
124
+
125
+ File.open("#{RAILS_ROOT}/db/#{SecondBase::CONNECTION_PREFIX}_#{RAILS_ENV}_structure.sql", "w+") do |f|
126
+ f << ActiveRecord::Base.connection.structure_dump
127
+ end
128
+
129
+ use_firstbase(Rails.env)
130
+ end
131
+ end
132
+ end
133
+
134
+ namespace :test do
135
+ namespace :prepare do
136
+ desc 'Prepares the test instance of secondbase'
137
+ task :secondbase do
138
+ Rake::Task["db:test:clone_structure:secondbase"].invoke
139
+ end
140
+ end
141
+
142
+ namespace :purge do
143
+ task :secondbase do
144
+ Rake::Task['environment'].invoke
145
+
146
+ use_secondbase('test')
147
+
148
+ ActiveRecord::Base.connection.recreate_database(secondbase_config('test')["database"], secondbase_config('test'))
149
+
150
+ use_firstbase(Rails.env)
151
+ end
152
+ end
153
+
154
+ namespace :clone_structure do
155
+ task :secondbase do
156
+ Rake::Task['environment'].invoke
157
+
158
+ # dump secondbase structure and purge the test secondbase
159
+ `rake db:structure:dump:secondbase`
160
+ `rake db:test:purge:secondbase`
161
+
162
+ # now lets clone the structure for secondbase
163
+ use_secondbase('test')
164
+ ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
165
+ IO.readlines("#{RAILS_ROOT}/db/#{SecondBase::CONNECTION_PREFIX}_#{RAILS_ENV}_structure.sql").join.split("\n\n").each do |table|
166
+ ActiveRecord::Base.connection.execute(table)
167
+ end
168
+
169
+ use_firstbase(Rails.env)
170
+ end
171
+ end
172
+ end
173
+
174
+ end
175
+
176
+
177
+ ####################################
178
+ #
179
+ # Some helper methods to run back and forth between first and second base.
180
+ def use_firstbase(env)
181
+ ActiveRecord::Base.establish_connection(firstbase_config(env))
182
+ end
183
+
184
+ def use_secondbase(env)
185
+ ActiveRecord::Base.establish_connection(secondbase_config(env))
186
+ end
187
+
188
+ def secondbase_config(env)
189
+ ActiveRecord::Base.configurations[SecondBase::CONNECTION_PREFIX][env]
190
+ end
191
+
192
+ def firstbase_config(env)
193
+ ActiveRecord::Base.configurations[env]
194
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'secondbase'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestSecondbase < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: secondbase
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - karledurante
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-12-06 00:00:00 -05:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ prerelease: false
23
+ type: :development
24
+ name: shoulda
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ requirement: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ prerelease: false
37
+ type: :development
38
+ name: bundler
39
+ version_requirements: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 23
45
+ segments:
46
+ - 1
47
+ - 0
48
+ - 0
49
+ version: 1.0.0
50
+ requirement: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ prerelease: false
53
+ type: :development
54
+ name: jeweler
55
+ version_requirements: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ hash: 1
61
+ segments:
62
+ - 1
63
+ - 5
64
+ - 1
65
+ version: 1.5.1
66
+ requirement: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ prerelease: false
69
+ type: :development
70
+ name: activerecord
71
+ version_requirements: &id004 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ hash: 7
77
+ segments:
78
+ - 3
79
+ - 0
80
+ - 0
81
+ version: 3.0.0
82
+ requirement: *id004
83
+ description: Secondbase provides support to Rails to create a homogeneous for a dual database project. Using the rake tasks already familiar to you, this gem enables Rails to work with two primary databases, instead of just one.
84
+ email: kdurante@customink.com
85
+ executables: []
86
+
87
+ extensions: []
88
+
89
+ extra_rdoc_files:
90
+ - LICENSE.txt
91
+ - README.rdoc
92
+ files:
93
+ - .document
94
+ - Gemfile
95
+ - Gemfile.lock
96
+ - LICENSE.txt
97
+ - README.rdoc
98
+ - Rakefile
99
+ - VERSION
100
+ - lib/generators/secondbase/USAGE
101
+ - lib/generators/secondbase/migration_generator.rb
102
+ - lib/generators/secondbase/templates/migration.rb
103
+ - lib/secondbase.rb
104
+ - lib/secondbase/fixtures.rb
105
+ - lib/secondbase/model.rb
106
+ - lib/secondbase/railtie.rb
107
+ - lib/secondbase/rake_method_chain.rb
108
+ - lib/tasks/secondbase.rake
109
+ - test/helper.rb
110
+ - test/test_secondbase.rb
111
+ has_rdoc: true
112
+ homepage: http://github.com/karledurante/secondbase
113
+ licenses:
114
+ - MIT
115
+ post_install_message:
116
+ rdoc_options: []
117
+
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ hash: 3
126
+ segments:
127
+ - 0
128
+ version: "0"
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ hash: 3
135
+ segments:
136
+ - 0
137
+ version: "0"
138
+ requirements: []
139
+
140
+ rubyforge_project:
141
+ rubygems_version: 1.3.7
142
+ signing_key:
143
+ specification_version: 3
144
+ summary: Allow Rails manage second database in your projects
145
+ test_files:
146
+ - test/helper.rb
147
+ - test/test_secondbase.rb