dynashard 0.1.0
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/.document +5 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +100 -0
- data/LICENSE.txt +20 -0
- data/README.md +72 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/lib/dynashard/arel_sql_engine.rb +22 -0
- data/lib/dynashard/associations.rb +19 -0
- data/lib/dynashard/connection_handler.rb +45 -0
- data/lib/dynashard/model.rb +92 -0
- data/lib/dynashard/validations.rb +23 -0
- data/lib/dynashard.rb +167 -0
- data/spec/arel_sql_engine_spec.rb +51 -0
- data/spec/associations_spec.rb +182 -0
- data/spec/connection_handler_spec.rb +61 -0
- data/spec/db/schema.rb +67 -0
- data/spec/dynashard_spec.rb +126 -0
- data/spec/model_spec.rb +104 -0
- data/spec/spec_helper.rb +46 -0
- data/spec/support/factories.rb +32 -0
- data/spec/support/models.rb +99 -0
- data/spec/validation_spec.rb +101 -0
- metadata +188 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
class Shard < ActiveRecord::Base
|
2
|
+
def dsn
|
3
|
+
HashWithIndifferentAccess.new(self.attributes.reject{|k,v| v.nil? || ['name','id'].include?(k)})
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
# Owner class that doesn't shard its associations
|
8
|
+
class NonShardingOwner < ActiveRecord::Base
|
9
|
+
# Non-sharded associations
|
10
|
+
has_one :non_sharded_has_one
|
11
|
+
has_many :non_sharded_has_manys
|
12
|
+
has_many :non_sharded_joins
|
13
|
+
has_many :non_sharded_has_many_throughs, :through => :non_sharded_joins
|
14
|
+
|
15
|
+
# Sharded associations
|
16
|
+
has_one :sharded_has_one
|
17
|
+
has_many :sharded_has_manys
|
18
|
+
has_many :sharded_joins
|
19
|
+
has_many :sharded_has_many_throughs, :through => :sharded_joins
|
20
|
+
end
|
21
|
+
|
22
|
+
# Owner class for sharded associations
|
23
|
+
class ShardingOwner < ActiveRecord::Base
|
24
|
+
shard :associated, :using => :shard_dsn
|
25
|
+
|
26
|
+
belongs_to :shard
|
27
|
+
def shard_dsn
|
28
|
+
@dsn ||= shard.dsn
|
29
|
+
end
|
30
|
+
|
31
|
+
# Non-sharded associations
|
32
|
+
has_one :non_sharded_has_one
|
33
|
+
has_many :non_sharded_has_manys
|
34
|
+
has_many :non_sharded_joins
|
35
|
+
has_many :non_sharded_has_many_throughs, :through => :non_sharded_joins
|
36
|
+
|
37
|
+
# Sharded associations
|
38
|
+
has_one :sharded_has_one
|
39
|
+
has_many :sharded_has_manys
|
40
|
+
has_many :sharded_joins
|
41
|
+
has_many :sharded_has_many_throughs, :through => :sharded_joins
|
42
|
+
end
|
43
|
+
|
44
|
+
# Non-sharded has_one association class
|
45
|
+
class NonShardedHasOne < ActiveRecord::Base
|
46
|
+
belongs_to :sharding_owner
|
47
|
+
|
48
|
+
validates :name, :uniqueness => true
|
49
|
+
end
|
50
|
+
|
51
|
+
# Non-sharded has_many association class
|
52
|
+
class NonShardedHasMany < ActiveRecord::Base
|
53
|
+
belongs_to :sharding_owner
|
54
|
+
belongs_to :non_sharding_owner
|
55
|
+
end
|
56
|
+
|
57
|
+
# Join table for has_many :through
|
58
|
+
class NonShardedJoin < ActiveRecord::Base
|
59
|
+
belongs_to :sharding_owner
|
60
|
+
belongs_to :non_sharded_has_many_through
|
61
|
+
end
|
62
|
+
|
63
|
+
# Non-sharded has_many association class
|
64
|
+
class NonShardedHasManyThrough < ActiveRecord::Base
|
65
|
+
has_many :non_sharded_joins
|
66
|
+
end
|
67
|
+
|
68
|
+
# Sharded has_one association class
|
69
|
+
class ShardedHasOne < ActiveRecord::Base
|
70
|
+
shard :by => :owner
|
71
|
+
|
72
|
+
validates :name, :uniqueness => true
|
73
|
+
|
74
|
+
belongs_to :sharding_owner
|
75
|
+
belongs_to :non_sharding_owner
|
76
|
+
end
|
77
|
+
|
78
|
+
# Sharded has_many association class
|
79
|
+
class ShardedHasMany < ActiveRecord::Base
|
80
|
+
shard :by => :owner
|
81
|
+
|
82
|
+
belongs_to :sharding_owner
|
83
|
+
belongs_to :non_sharding_owner
|
84
|
+
end
|
85
|
+
|
86
|
+
# Join table for has_many :through
|
87
|
+
class ShardedJoin < ActiveRecord::Base
|
88
|
+
shard :by => :owner
|
89
|
+
|
90
|
+
belongs_to :sharding_owner
|
91
|
+
belongs_to :sharded_has_many_through
|
92
|
+
end
|
93
|
+
|
94
|
+
# Sharded has_many :through association class
|
95
|
+
class ShardedHasManyThrough < ActiveRecord::Base
|
96
|
+
shard :by => :owner
|
97
|
+
|
98
|
+
has_many :sharded_joins
|
99
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Dynashard::ValidationExtensions' do
|
4
|
+
before(:each) do
|
5
|
+
@owner = Factory(:sharding_owner)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '#find_finder_class_for' do
|
9
|
+
before(:each) do
|
10
|
+
@shard_klass = Dynashard.class_for(@owner.shard_dsn)
|
11
|
+
@sharded_model_subclass = Dynashard.sharded_model_class(@shard_klass, ShardedHasOne)
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when sharding' do
|
15
|
+
before(:each) do
|
16
|
+
@validator = ShardedHasOne.validators.detect{|v| v.is_a?(ActiveRecord::Validations::UniquenessValidator)}
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'with a generated association owner class' do
|
20
|
+
it 'returns the generated class' do
|
21
|
+
new_record = @owner.build_sharded_has_one
|
22
|
+
@validator.send(:find_finder_class_for, new_record).should == @sharded_model_subclass
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'with a model class' do
|
27
|
+
it 'returns the generated shard subclass' do
|
28
|
+
Dynashard.with_context(:owner => @owner.shard_dsn) do
|
29
|
+
new_record = ShardedHasOne.new
|
30
|
+
@validator.send(:find_finder_class_for, new_record).should == @sharded_model_subclass
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when not sharding' do
|
37
|
+
before(:each) do
|
38
|
+
@validator = NonShardedHasOne.validators.detect{|v| v.is_a?(ActiveRecord::Validations::UniquenessValidator)}
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'with a non-sharding association owner class' do
|
42
|
+
it 'returns the model class' do
|
43
|
+
non_sharding_owner = Factory(:non_sharding_owner)
|
44
|
+
new_record = non_sharding_owner.build_non_sharded_has_one
|
45
|
+
@validator.send(:find_finder_class_for, new_record).should == NonShardedHasOne
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'with a non-sharding model class' do
|
50
|
+
it 'returns the model class' do
|
51
|
+
new_record = NonShardedHasOne.new
|
52
|
+
@validator.send(:find_finder_class_for, new_record).should == NonShardedHasOne
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'when validating uniqueness' do
|
59
|
+
context 'with an association proxy target' do
|
60
|
+
context 'with a conflicting record on the shard' do
|
61
|
+
it 'returns invalid' do
|
62
|
+
conflicting_record = Dynashard.with_context(:owner => @owner.shard_dsn){Factory(:sharded_has_one)}
|
63
|
+
new_record = @owner.build_sharded_has_one(:name => conflicting_record.name)
|
64
|
+
new_record.should_not be_valid
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'with a conflicting record on a different shard' do
|
69
|
+
it 'returns valid' do
|
70
|
+
other_shard = Shard.find(:all).detect{|shard| shard != @owner.shard}
|
71
|
+
non_conflicting_record = Dynashard.with_context(:owner => other_shard.dsn){Factory(:sharded_has_one)}
|
72
|
+
new_record = @owner.build_sharded_has_one(:name => non_conflicting_record.name)
|
73
|
+
new_record.should be_valid
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'with a model class' do
|
79
|
+
context 'with a conflicting record on the shard' do
|
80
|
+
it 'returns invalid' do
|
81
|
+
conflicting_record = Dynashard.with_context(:owner => @owner.shard_dsn){Factory(:sharded_has_one)}
|
82
|
+
new_record = ShardedHasOne.new(:name => conflicting_record.name)
|
83
|
+
Dynashard.with_context(:owner => @owner.shard_dsn) do
|
84
|
+
new_record.should_not be_valid
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'with a conflicting record on a different shard' do
|
90
|
+
it 'returns valid' do
|
91
|
+
other_shard = Shard.find(:all).detect{|shard| shard != @owner.shard}
|
92
|
+
non_conflicting_record = Dynashard.with_context(:owner => other_shard.dsn){Factory(:sharded_has_one)}
|
93
|
+
new_record = ShardedHasOne.new(:name => non_conflicting_record.name)
|
94
|
+
Dynashard.with_context(:owner => @owner.shard_dsn) do
|
95
|
+
new_record.should be_valid
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
metadata
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dynashard
|
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
|
+
- Nick Hengeveld
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-01-31 00:00:00 -08:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
name: activerecord
|
25
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 7
|
31
|
+
segments:
|
32
|
+
- 3
|
33
|
+
- 0
|
34
|
+
version: "3.0"
|
35
|
+
requirement: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
type: :development
|
38
|
+
prerelease: false
|
39
|
+
name: shoulda
|
40
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 3
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
version: "0"
|
49
|
+
requirement: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
type: :development
|
52
|
+
prerelease: false
|
53
|
+
name: bundler
|
54
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ~>
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 23
|
60
|
+
segments:
|
61
|
+
- 1
|
62
|
+
- 0
|
63
|
+
- 0
|
64
|
+
version: 1.0.0
|
65
|
+
requirement: *id003
|
66
|
+
- !ruby/object:Gem::Dependency
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
name: jeweler
|
70
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 7
|
76
|
+
segments:
|
77
|
+
- 1
|
78
|
+
- 5
|
79
|
+
- 2
|
80
|
+
version: 1.5.2
|
81
|
+
requirement: *id004
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
type: :development
|
84
|
+
prerelease: false
|
85
|
+
name: rcov
|
86
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
hash: 3
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
version: "0"
|
95
|
+
requirement: *id005
|
96
|
+
- !ruby/object:Gem::Dependency
|
97
|
+
type: :runtime
|
98
|
+
prerelease: false
|
99
|
+
name: activerecord
|
100
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
hash: 7
|
106
|
+
segments:
|
107
|
+
- 3
|
108
|
+
- 0
|
109
|
+
version: "3.0"
|
110
|
+
requirement: *id006
|
111
|
+
description: Dynashard allows you to shard your ActiveRecord models. Models can be configured to shard based on context that can be defined dynamically.
|
112
|
+
email: nickh@verticalresponse.com
|
113
|
+
executables: []
|
114
|
+
|
115
|
+
extensions: []
|
116
|
+
|
117
|
+
extra_rdoc_files:
|
118
|
+
- LICENSE.txt
|
119
|
+
- README.md
|
120
|
+
files:
|
121
|
+
- .document
|
122
|
+
- Gemfile
|
123
|
+
- Gemfile.lock
|
124
|
+
- LICENSE.txt
|
125
|
+
- README.md
|
126
|
+
- Rakefile
|
127
|
+
- VERSION
|
128
|
+
- lib/dynashard.rb
|
129
|
+
- lib/dynashard/arel_sql_engine.rb
|
130
|
+
- lib/dynashard/associations.rb
|
131
|
+
- lib/dynashard/connection_handler.rb
|
132
|
+
- lib/dynashard/model.rb
|
133
|
+
- lib/dynashard/validations.rb
|
134
|
+
- spec/arel_sql_engine_spec.rb
|
135
|
+
- spec/associations_spec.rb
|
136
|
+
- spec/connection_handler_spec.rb
|
137
|
+
- spec/dynashard_spec.rb
|
138
|
+
- spec/model_spec.rb
|
139
|
+
- spec/spec_helper.rb
|
140
|
+
- spec/support/factories.rb
|
141
|
+
- spec/support/models.rb
|
142
|
+
- spec/validation_spec.rb
|
143
|
+
- spec/db/schema.rb
|
144
|
+
has_rdoc: true
|
145
|
+
homepage: http://github.com/nickh/dynashard
|
146
|
+
licenses:
|
147
|
+
- MIT
|
148
|
+
post_install_message:
|
149
|
+
rdoc_options: []
|
150
|
+
|
151
|
+
require_paths:
|
152
|
+
- lib
|
153
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
154
|
+
none: false
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
hash: 3
|
159
|
+
segments:
|
160
|
+
- 0
|
161
|
+
version: "0"
|
162
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
|
+
none: false
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
hash: 3
|
168
|
+
segments:
|
169
|
+
- 0
|
170
|
+
version: "0"
|
171
|
+
requirements: []
|
172
|
+
|
173
|
+
rubyforge_project:
|
174
|
+
rubygems_version: 1.3.7
|
175
|
+
signing_key:
|
176
|
+
specification_version: 3
|
177
|
+
summary: Dynamic sharding for ActiveRecord
|
178
|
+
test_files:
|
179
|
+
- spec/arel_sql_engine_spec.rb
|
180
|
+
- spec/associations_spec.rb
|
181
|
+
- spec/connection_handler_spec.rb
|
182
|
+
- spec/db/schema.rb
|
183
|
+
- spec/dynashard_spec.rb
|
184
|
+
- spec/model_spec.rb
|
185
|
+
- spec/spec_helper.rb
|
186
|
+
- spec/support/factories.rb
|
187
|
+
- spec/support/models.rb
|
188
|
+
- spec/validation_spec.rb
|