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.
@@ -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