secondbase 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +8 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +9 -5
- data/VERSION +1 -1
- data/lib/secondbase.rb +2 -1
- data/lib/secondbase/active_record/associations/has_and_belongs_to_many_association.rb +66 -0
- data/lib/secondbase/active_record/base.rb +13 -0
- data/lib/secondbase/{fixtures.rb → active_record/fixtures.rb} +1 -3
- data/lib/secondbase/active_record/patches.rb +13 -0
- data/lib/secondbase/active_record/test_fixtures.rb +32 -0
- data/lib/secondbase/model.rb +1 -2
- data/secondbase.gemspec +14 -13
- metadata +27 -23
data/CHANGELOG.md
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# CHANGELOG
|
2
|
+
|
3
|
+
## 0.6
|
4
|
+
|
5
|
+
* This version of the gem ONLY SUPPORTS Rails 3.x. For 2.x support, check out the branch 'rails_2_3' (or version .5 of the gem)
|
6
|
+
* patched has_and_belongs_to_many associations, for secondbase models, so that ActiveRecord understands that the join table is in the secondbase.
|
7
|
+
* patched ActiveRecord::TestFixtures so that transactional fixture support is respected for the SecondBase.
|
8
|
+
* reorganized monkey patches to make it easier to work in fixes for different versions of rails.
|
data/Gemfile
CHANGED
@@ -7,7 +7,7 @@ source "http://rubygems.org"
|
|
7
7
|
# Include everything needed to run rake, tests, features, etc.
|
8
8
|
group :development do
|
9
9
|
gem "shoulda", ">= 0"
|
10
|
-
gem "bundler", "
|
11
|
-
gem "jeweler", "~> 1.
|
10
|
+
gem "bundler", ">= 1.0.0"
|
11
|
+
gem "jeweler", "~> 1.8.2"
|
12
12
|
gem "activerecord", "~> 3.0.0"
|
13
13
|
end
|
data/Gemfile.lock
CHANGED
@@ -16,11 +16,15 @@ GEM
|
|
16
16
|
builder (2.1.2)
|
17
17
|
git (1.2.5)
|
18
18
|
i18n (0.4.1)
|
19
|
-
jeweler (1.
|
20
|
-
bundler (~> 1.0
|
19
|
+
jeweler (1.8.4)
|
20
|
+
bundler (~> 1.0)
|
21
21
|
git (>= 1.2.5)
|
22
22
|
rake
|
23
|
-
|
23
|
+
rdoc
|
24
|
+
json (1.7.5)
|
25
|
+
rake (0.9.2.2)
|
26
|
+
rdoc (3.12)
|
27
|
+
json (~> 1.4)
|
24
28
|
shoulda (2.11.1)
|
25
29
|
tzinfo (0.3.23)
|
26
30
|
|
@@ -29,6 +33,6 @@ PLATFORMS
|
|
29
33
|
|
30
34
|
DEPENDENCIES
|
31
35
|
activerecord (~> 3.0.0)
|
32
|
-
bundler (
|
33
|
-
jeweler (~> 1.
|
36
|
+
bundler (>= 1.0.0)
|
37
|
+
jeweler (~> 1.8.2)
|
34
38
|
shoulda
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
data/lib/secondbase.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'active_record'
|
2
|
+
require 'secondbase/active_record/patches'
|
2
3
|
|
3
4
|
module SecondBase
|
4
5
|
CONNECTION_PREFIX = 'secondbase'
|
5
6
|
|
6
|
-
require 'secondbase/railtie'
|
7
|
+
require 'secondbase/railtie'
|
7
8
|
require 'secondbase/rake_method_chain'
|
8
9
|
|
9
10
|
def self.do
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
# = Active Record Has And Belongs To Many Association
|
3
|
+
module Associations
|
4
|
+
class HasAndBelongsToManyAssociation < AssociationCollection
|
5
|
+
|
6
|
+
# determines the appropriate engine for the join table's parent klass
|
7
|
+
def arel_engine
|
8
|
+
Arel::Sql::Engine.new(@reflection.klass.engine)
|
9
|
+
end
|
10
|
+
|
11
|
+
# This method is entirely replicated, except for line 25. We simply
|
12
|
+
# need to pass in the appropriate engine to Arel.
|
13
|
+
def insert_record(record, force = true, validate = true)
|
14
|
+
if record.new_record?
|
15
|
+
if force
|
16
|
+
record.save!
|
17
|
+
else
|
18
|
+
return false unless record.save(:validate => validate)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
if @reflection.options[:insert_sql]
|
23
|
+
@owner.connection.insert(interpolate_and_sanitize_sql(@reflection.options[:insert_sql], record))
|
24
|
+
else
|
25
|
+
relation = Arel::Table.new(@reflection.options[:join_table], arel_engine)
|
26
|
+
timestamps = record_timestamp_columns(record)
|
27
|
+
timezone = record.send(:current_time_from_proper_timezone) if timestamps.any?
|
28
|
+
|
29
|
+
attributes = Hash[columns.map do |column|
|
30
|
+
name = column.name
|
31
|
+
value = case name.to_s
|
32
|
+
when @reflection.primary_key_name.to_s
|
33
|
+
@owner.id
|
34
|
+
when @reflection.association_foreign_key.to_s
|
35
|
+
record.id
|
36
|
+
when *timestamps
|
37
|
+
timezone
|
38
|
+
else
|
39
|
+
@owner.send(:quote_value, record[name], column) if record.has_attribute?(name)
|
40
|
+
end
|
41
|
+
[relation[name], value] unless value.nil?
|
42
|
+
end]
|
43
|
+
|
44
|
+
relation.insert(attributes)
|
45
|
+
end
|
46
|
+
|
47
|
+
return true
|
48
|
+
end
|
49
|
+
|
50
|
+
# This method is entirely replicated, except for line 57. We simply
|
51
|
+
# need to pass in the appropriate engine to Arel.
|
52
|
+
def delete_records(records)
|
53
|
+
if sql = @reflection.options[:delete_sql]
|
54
|
+
records.each { |record| @owner.connection.delete(interpolate_and_sanitize_sql(sql, record)) }
|
55
|
+
else
|
56
|
+
|
57
|
+
relation = Arel::Table.new(@reflection.options[:join_table], arel_engine)
|
58
|
+
|
59
|
+
relation.where(relation[@reflection.primary_key_name].eq(@owner.id).
|
60
|
+
and(relation[@reflection.association_foreign_key].in(records.map { |x| x.id }.compact))
|
61
|
+
).delete
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Base
|
3
|
+
|
4
|
+
# Arel is concerned with "engines". Normally the engine defaults to the primary
|
5
|
+
# connection (ActiveRecord::Base). This will let us easily override the engine
|
6
|
+
# when dealing with Seoncdbase models (deep in ActiveRecord code).
|
7
|
+
# Since SecondBase::Base inherits from ActiveRecord::Base, this will pass the
|
8
|
+
# right engine around.
|
9
|
+
def self.engine
|
10
|
+
self
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'secondbase/model'
|
2
|
-
|
3
1
|
###########################
|
4
2
|
# Monkey patch Fixtures
|
5
3
|
# Fixtures needs to load fixtures into the database defined by the parent class!
|
@@ -7,7 +5,7 @@ require 'secondbase/model'
|
|
7
5
|
# I feel like the concepts here could be incorporated directly into Fixtures.
|
8
6
|
# I mean, they shouldn't be so presumptions to think that every model lives in the
|
9
7
|
# same database....
|
10
|
-
class Fixtures
|
8
|
+
class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
|
11
9
|
def self.create_fixtures(fixtures_directory, table_names, class_names = {})
|
12
10
|
table_names = [table_names].flatten.map { |n| n.to_s }
|
13
11
|
table_names.each { |n| class_names[n.tr('/', '_').to_sym] = n.classify if n.include?('/') }
|
@@ -0,0 +1,13 @@
|
|
1
|
+
####################
|
2
|
+
## ActiveRecord patches for all versions of rails
|
3
|
+
require 'secondbase/active_record/base'
|
4
|
+
|
5
|
+
|
6
|
+
####################
|
7
|
+
## ActiveRecord patches for specific versions of rails
|
8
|
+
if Rails.env.test?
|
9
|
+
require 'secondbase/active_record/fixtures'
|
10
|
+
require 'secondbase/active_record/test_fixtures'
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'secondbase/active_record/associations/has_and_belongs_to_many_association'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
## ActiveRecord::TestFixtures
|
2
|
+
## Monkey patch active record's test_fixtures module to manage
|
3
|
+
## transactions for the SecondBase
|
4
|
+
module ActiveRecord
|
5
|
+
module TestFixtures
|
6
|
+
alias_method :original_setup_fixtures, :setup_fixtures
|
7
|
+
alias_method :original_teardown_fixtures, :teardown_fixtures
|
8
|
+
|
9
|
+
def setup_fixtures
|
10
|
+
original_setup_fixtures
|
11
|
+
# start tx for secondbase, if required
|
12
|
+
# Load fixtures once and begin transaction.
|
13
|
+
if run_in_transaction?
|
14
|
+
SecondBase::Base.connection.increment_open_transactions
|
15
|
+
SecondBase::Base.connection.transaction_joinable = false
|
16
|
+
SecondBase::Base.connection.begin_db_transaction
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def teardown_fixtures
|
21
|
+
original_teardown_fixtures
|
22
|
+
|
23
|
+
# Rollback secondbase changes if a transaction is active.
|
24
|
+
if run_in_transaction? && SecondBase::Base.connection.open_transactions != 0
|
25
|
+
SecondBase::Base.connection.rollback_db_transaction
|
26
|
+
SecondBase::Base.connection.decrement_open_transactions
|
27
|
+
end
|
28
|
+
|
29
|
+
SecondBase::Base.clear_active_connections!
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/secondbase/model.rb
CHANGED
@@ -2,10 +2,9 @@
|
|
2
2
|
#
|
3
3
|
# NOTE: By extending this model, you assume that the underlying table will be located in your Second (Data)base
|
4
4
|
module SecondBase
|
5
|
-
require 'active_record'
|
6
5
|
|
7
6
|
class Base < ActiveRecord::Base
|
8
|
-
establish_connection ActiveRecord::Base.configurations[CONNECTION_PREFIX][Rails.env]
|
7
|
+
establish_connection ActiveRecord::Base.configurations[SecondBase::CONNECTION_PREFIX][Rails.env]
|
9
8
|
|
10
9
|
self.abstract_class = true
|
11
10
|
end
|
data/secondbase.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{secondbase}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.6.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["karledurante"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2012-08-31}
|
13
13
|
s.description = %q{Secondbase provides support to Rails to create a homogeneous environment 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.}
|
14
14
|
s.email = %q{kdurante@customink.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
]
|
19
19
|
s.files = [
|
20
20
|
".document",
|
21
|
+
"CHANGELOG.md",
|
21
22
|
"Gemfile",
|
22
23
|
"Gemfile.lock",
|
23
24
|
"LICENSE.txt",
|
@@ -28,7 +29,11 @@ Gem::Specification.new do |s|
|
|
28
29
|
"lib/generators/secondbase/migration_generator.rb",
|
29
30
|
"lib/generators/secondbase/templates/migration.rb",
|
30
31
|
"lib/secondbase.rb",
|
31
|
-
"lib/secondbase/
|
32
|
+
"lib/secondbase/active_record/associations/has_and_belongs_to_many_association.rb",
|
33
|
+
"lib/secondbase/active_record/base.rb",
|
34
|
+
"lib/secondbase/active_record/fixtures.rb",
|
35
|
+
"lib/secondbase/active_record/patches.rb",
|
36
|
+
"lib/secondbase/active_record/test_fixtures.rb",
|
32
37
|
"lib/secondbase/model.rb",
|
33
38
|
"lib/secondbase/railtie.rb",
|
34
39
|
"lib/secondbase/rake_method_chain.rb",
|
@@ -45,31 +50,27 @@ Gem::Specification.new do |s|
|
|
45
50
|
s.require_paths = ["lib"]
|
46
51
|
s.rubygems_version = %q{1.4.2}
|
47
52
|
s.summary = %q{Allow Rails manage second database in your projects}
|
48
|
-
s.test_files = [
|
49
|
-
"test/helper.rb",
|
50
|
-
"test/test_secondbase.rb"
|
51
|
-
]
|
52
53
|
|
53
54
|
if s.respond_to? :specification_version then
|
54
55
|
s.specification_version = 3
|
55
56
|
|
56
57
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
57
58
|
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
58
|
-
s.add_development_dependency(%q<bundler>, ["
|
59
|
-
s.add_development_dependency(%q<jeweler>, ["~> 1.
|
59
|
+
s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
|
60
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.2"])
|
60
61
|
s.add_development_dependency(%q<activerecord>, ["~> 3.0.0"])
|
61
62
|
s.add_development_dependency(%q<activerecord>, ["~> 3.0.0"])
|
62
63
|
else
|
63
64
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
64
|
-
s.add_dependency(%q<bundler>, ["
|
65
|
-
s.add_dependency(%q<jeweler>, ["~> 1.
|
65
|
+
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
66
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.2"])
|
66
67
|
s.add_dependency(%q<activerecord>, ["~> 3.0.0"])
|
67
68
|
s.add_dependency(%q<activerecord>, ["~> 3.0.0"])
|
68
69
|
end
|
69
70
|
else
|
70
71
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
71
|
-
s.add_dependency(%q<bundler>, ["
|
72
|
-
s.add_dependency(%q<jeweler>, ["~> 1.
|
72
|
+
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
73
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.2"])
|
73
74
|
s.add_dependency(%q<activerecord>, ["~> 3.0.0"])
|
74
75
|
s.add_dependency(%q<activerecord>, ["~> 3.0.0"])
|
75
76
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: secondbase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 6
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.6.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- karledurante
|
@@ -15,11 +15,11 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2012-08-31 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
-
|
22
|
+
prerelease: false
|
23
23
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
24
24
|
none: false
|
25
25
|
requirements:
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
- 0
|
31
31
|
version: "0"
|
32
32
|
requirement: *id001
|
33
|
-
|
33
|
+
type: :development
|
34
34
|
name: shoulda
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
|
-
|
36
|
+
prerelease: false
|
37
37
|
version_requirements: &id002 !ruby/object:Gem::Requirement
|
38
38
|
none: false
|
39
39
|
requirements:
|
40
|
-
- -
|
40
|
+
- - ">="
|
41
41
|
- !ruby/object:Gem::Version
|
42
42
|
hash: 23
|
43
43
|
segments:
|
@@ -46,26 +46,26 @@ dependencies:
|
|
46
46
|
- 0
|
47
47
|
version: 1.0.0
|
48
48
|
requirement: *id002
|
49
|
-
|
49
|
+
type: :development
|
50
50
|
name: bundler
|
51
51
|
- !ruby/object:Gem::Dependency
|
52
|
-
|
52
|
+
prerelease: false
|
53
53
|
version_requirements: &id003 !ruby/object:Gem::Requirement
|
54
54
|
none: false
|
55
55
|
requirements:
|
56
56
|
- - ~>
|
57
57
|
- !ruby/object:Gem::Version
|
58
|
-
hash:
|
58
|
+
hash: 51
|
59
59
|
segments:
|
60
60
|
- 1
|
61
|
-
-
|
62
|
-
-
|
63
|
-
version: 1.
|
61
|
+
- 8
|
62
|
+
- 2
|
63
|
+
version: 1.8.2
|
64
64
|
requirement: *id003
|
65
|
-
|
65
|
+
type: :development
|
66
66
|
name: jeweler
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
|
-
|
68
|
+
prerelease: false
|
69
69
|
version_requirements: &id004 !ruby/object:Gem::Requirement
|
70
70
|
none: false
|
71
71
|
requirements:
|
@@ -78,10 +78,10 @@ dependencies:
|
|
78
78
|
- 0
|
79
79
|
version: 3.0.0
|
80
80
|
requirement: *id004
|
81
|
-
|
81
|
+
type: :development
|
82
82
|
name: activerecord
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
|
84
|
+
prerelease: false
|
85
85
|
version_requirements: &id005 !ruby/object:Gem::Requirement
|
86
86
|
none: false
|
87
87
|
requirements:
|
@@ -94,7 +94,7 @@ dependencies:
|
|
94
94
|
- 0
|
95
95
|
version: 3.0.0
|
96
96
|
requirement: *id005
|
97
|
-
|
97
|
+
type: :development
|
98
98
|
name: activerecord
|
99
99
|
description: Secondbase provides support to Rails to create a homogeneous environment 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.
|
100
100
|
email: kdurante@customink.com
|
@@ -107,6 +107,7 @@ extra_rdoc_files:
|
|
107
107
|
- README.rdoc
|
108
108
|
files:
|
109
109
|
- .document
|
110
|
+
- CHANGELOG.md
|
110
111
|
- Gemfile
|
111
112
|
- Gemfile.lock
|
112
113
|
- LICENSE.txt
|
@@ -117,7 +118,11 @@ files:
|
|
117
118
|
- lib/generators/secondbase/migration_generator.rb
|
118
119
|
- lib/generators/secondbase/templates/migration.rb
|
119
120
|
- lib/secondbase.rb
|
120
|
-
- lib/secondbase/
|
121
|
+
- lib/secondbase/active_record/associations/has_and_belongs_to_many_association.rb
|
122
|
+
- lib/secondbase/active_record/base.rb
|
123
|
+
- lib/secondbase/active_record/fixtures.rb
|
124
|
+
- lib/secondbase/active_record/patches.rb
|
125
|
+
- lib/secondbase/active_record/test_fixtures.rb
|
121
126
|
- lib/secondbase/model.rb
|
122
127
|
- lib/secondbase/railtie.rb
|
123
128
|
- lib/secondbase/rake_method_chain.rb
|
@@ -162,6 +167,5 @@ rubygems_version: 1.4.2
|
|
162
167
|
signing_key:
|
163
168
|
specification_version: 3
|
164
169
|
summary: Allow Rails manage second database in your projects
|
165
|
-
test_files:
|
166
|
-
|
167
|
-
- test/test_secondbase.rb
|
170
|
+
test_files: []
|
171
|
+
|