replicat 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +25 -14
- data/lib/replicat.rb +1 -0
- data/lib/replicat/model.rb +5 -0
- data/lib/replicat/replicable.rb +7 -3
- data/lib/replicat/scope_proxy.rb +24 -0
- data/lib/replicat/version.rb +1 -1
- data/replicat.gemspec +1 -0
- data/spec/dummy/app/models/ingredient.rb +5 -0
- data/spec/dummy/app/models/recipe.rb +2 -0
- data/spec/dummy/db/schema.rb +7 -0
- data/spec/replicat/model_spec.rb +43 -0
- data/spec/replicat/replicable_spec.rb +42 -8
- data/spec/spec_helper.rb +15 -3
- metadata +22 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b0943235f899b2c1ae3617e2516a4616a5eb2da8
|
4
|
+
data.tar.gz: 4a793e61900339e0b78259c86f8c9af8a1d2ea6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2ab0acafcf8ff55fa4feb51ccadfbbc068ef5f0ebc4409305ad84d5466fb3319bb80f6806e19663b520c7b93733e053909c3f14d842fb533fe9b389fdcab3bff
|
7
|
+
data.tar.gz: a353681af3ecae8761a906b443df27fccd4b2b7e986eec5b05785dcff62da41bb44ad0a760fc3fd8f099a4ced8d9671fa503f00221451b951c46c31af7fdda67
|
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -45,33 +45,44 @@ production:
|
|
45
45
|
Now SELECT queries of User model will be sent to slave connections.
|
46
46
|
|
47
47
|
```ruby
|
48
|
+
# INSERT query is sent to master.
|
48
49
|
User.create(name: "replicat")
|
49
|
-
|
50
|
+
|
51
|
+
# SELECT query is sent to slave.
|
52
|
+
User.first
|
50
53
|
```
|
51
54
|
|
52
55
|
### using
|
53
56
|
`using` can help you specify particular connection.
|
54
|
-
|
57
|
+
When you want to send queries to master,
|
58
|
+
you can use `using(:master)` to do that (:master is reserved name for `using` method).
|
59
|
+
When you want to send queries to a particular slave,
|
60
|
+
you can use the slave's name on database.yml like `using(:slave1)`.
|
55
61
|
|
56
62
|
```ruby
|
57
|
-
|
58
|
-
User.using(:master)
|
63
|
+
# SELECT query is sent to master.
|
64
|
+
User.using(:master).first
|
65
|
+
|
66
|
+
# INSERT query is sent to slave1.
|
67
|
+
User.using(:slave1).create(name: "replicat")
|
68
|
+
|
69
|
+
# :slave1 is used for User connection in the passed block.
|
70
|
+
User.using(:slave1) { blog.user }
|
59
71
|
```
|
60
72
|
|
61
73
|
### round-robin
|
62
74
|
slave connections are balanced by round-robin way.
|
63
75
|
|
64
76
|
```ruby
|
65
|
-
User.
|
66
|
-
User.first
|
67
|
-
User.first
|
68
|
-
User.first
|
69
|
-
User.first
|
70
|
-
User.first
|
71
|
-
User.first
|
72
|
-
User.first
|
73
|
-
User.first
|
74
|
-
User.first #=> nil
|
77
|
+
User.first # sent to slave1
|
78
|
+
User.first # sent to slave2
|
79
|
+
User.first # sent to slave3
|
80
|
+
User.first # sent to slave1
|
81
|
+
User.first # sent to slave2
|
82
|
+
User.first # sent to slave3
|
83
|
+
User.first # sent to slave1
|
84
|
+
User.first # sent to slave2
|
85
|
+
User.first # sent to slave3
|
75
86
|
```
|
76
87
|
|
77
88
|
### multi master-slave set
|
data/lib/replicat.rb
CHANGED
data/lib/replicat/model.rb
CHANGED
@@ -4,6 +4,11 @@ module Replicat
|
|
4
4
|
raise "You must set `connection_name` of this model class." if !connection_name && !defined?(Rails)
|
5
5
|
include Replicat::Replicable
|
6
6
|
self.connection_name = connection_name || Rails.env.to_s
|
7
|
+
self
|
8
|
+
end
|
9
|
+
|
10
|
+
def replicated?
|
11
|
+
ancestors.include?(Replicable)
|
7
12
|
end
|
8
13
|
end
|
9
14
|
end
|
data/lib/replicat/replicable.rb
CHANGED
@@ -44,10 +44,14 @@ module Replicat
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def using(connection_name)
|
47
|
-
|
48
|
-
|
47
|
+
if block_given?
|
48
|
+
proxy.current_connection_name = connection_name
|
49
|
+
yield
|
50
|
+
else
|
51
|
+
ScopeProxy.new(klass: self, connection_name: connection_name)
|
52
|
+
end
|
49
53
|
ensure
|
50
|
-
proxy.current_connection_name = nil
|
54
|
+
proxy.current_connection_name = nil if block_given?
|
51
55
|
end
|
52
56
|
end
|
53
57
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Replicat
|
2
|
+
class ScopeProxy
|
3
|
+
def initialize(attributes)
|
4
|
+
@klass = attributes[:klass]
|
5
|
+
@connection_name = attributes[:connection_name]
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def method_missing(method_name, *args, &block)
|
11
|
+
result = using { @klass.send(method_name, *args, &block) }
|
12
|
+
if result.respond_to?(:scoped)
|
13
|
+
@klass = result
|
14
|
+
self
|
15
|
+
else
|
16
|
+
result
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def using
|
21
|
+
@klass.using(@connection_name) { yield }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/replicat/version.rb
CHANGED
data/replicat.gemspec
CHANGED
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.add_dependency "activesupport"
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
22
|
spec.add_development_dependency "coffee-rails", ">= 3.0.10"
|
23
|
+
spec.add_development_dependency "database_cleaner", "1.2.0"
|
23
24
|
spec.add_development_dependency "jquery-rails"
|
24
25
|
spec.add_development_dependency "pry"
|
25
26
|
spec.add_development_dependency "pry-rails"
|
data/spec/dummy/db/schema.rb
CHANGED
@@ -23,4 +23,11 @@ ActiveRecord::Schema.define(version: 0) do
|
|
23
23
|
t.datetime "created_at"
|
24
24
|
t.datetime "updated_at"
|
25
25
|
end
|
26
|
+
|
27
|
+
create_table "ingredients", force: true do |t|
|
28
|
+
t.string "name", null: false
|
29
|
+
t.integer "recipe_id", null: false
|
30
|
+
t.datetime "created_at"
|
31
|
+
t.datetime "updated_at"
|
32
|
+
end
|
26
33
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Replicat::Model do
|
4
|
+
let(:model_class) do
|
5
|
+
Class.new(ActiveRecord::Base)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe ".replicate" do
|
9
|
+
context "with no args" do
|
10
|
+
it "includes Replicat::Replicable" do
|
11
|
+
model_class.replicate.ancestors.should include Replicat::Replicable
|
12
|
+
end
|
13
|
+
|
14
|
+
it "assigns connection_name attribute with Rails.env" do
|
15
|
+
model_class.replicate.connection_name.should == Rails.env
|
16
|
+
end
|
17
|
+
|
18
|
+
it "returns itself" do
|
19
|
+
model_class.replicate.should == model_class
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "with args" do
|
24
|
+
it "uses given value as connection_name attribute" do
|
25
|
+
model_class.replicate("master1").connection_name.should == "master1"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe ".replicated?" do
|
31
|
+
context "with replicated model" do
|
32
|
+
it "returns true" do
|
33
|
+
model_class.replicate.should be_replicated
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "with non-replicated model" do
|
38
|
+
it "returns false" do
|
39
|
+
model_class.should_not be_replicated
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,14 +1,6 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Replicat::Replicable do
|
4
|
-
describe ".has_any_replication?" do
|
5
|
-
context "with any replication in connection settings" do
|
6
|
-
it "returns true" do
|
7
|
-
Recipe.should have_any_replication
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
4
|
describe ".connection_with_proxy" do
|
13
5
|
context "with non-replicable model" do
|
14
6
|
it "returns normal connection" do
|
@@ -52,6 +44,48 @@ describe Replicat::Replicable do
|
|
52
44
|
end
|
53
45
|
end
|
54
46
|
end
|
47
|
+
|
48
|
+
context "with no block" do
|
49
|
+
it "can be used as scope" do
|
50
|
+
Recipe.using(:slave1).create(title: "test")
|
51
|
+
Recipe.using(:slave1).first.should_not == nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "with scope" do
|
56
|
+
it "works well" do
|
57
|
+
Recipe.all.using(:slave1).create(title: "test")
|
58
|
+
Recipe.where(title: "test").using(:slave1).first.should_not == nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "with belongs_to association" do
|
63
|
+
let!(:ingredient) do
|
64
|
+
Ingredient.using(:slave1).create(name: "test", recipe_id: recipe.id)
|
65
|
+
end
|
66
|
+
|
67
|
+
let(:recipe) do
|
68
|
+
Recipe.using(:slave1).create(title: "test")
|
69
|
+
end
|
70
|
+
|
71
|
+
it "works well" do
|
72
|
+
Recipe.using(:slave1) { ingredient.recipe.should == recipe }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "with has_many association" do
|
77
|
+
let!(:ingredient) do
|
78
|
+
Ingredient.using(:slave1) { Ingredient.create(name: "test", recipe_id: recipe.id) }
|
79
|
+
end
|
80
|
+
|
81
|
+
let(:recipe) do
|
82
|
+
Recipe.using(:slave1) { Recipe.create(title: "test") }
|
83
|
+
end
|
84
|
+
|
85
|
+
it "works well" do
|
86
|
+
Ingredient.using(:slave1) { recipe.ingredients.should == [ingredient] }
|
87
|
+
end
|
88
|
+
end
|
55
89
|
end
|
56
90
|
|
57
91
|
describe ".proxy" do
|
data/spec/spec_helper.rb
CHANGED
@@ -4,12 +4,24 @@ require "replicat"
|
|
4
4
|
ENV["RAILS_ENV"] ||= "test"
|
5
5
|
require File.expand_path("../dummy/config/environment", __FILE__)
|
6
6
|
require "rspec/rails"
|
7
|
-
|
8
|
-
3.times {|i| FileUtils.copy("#{Rails.root}/db/test.sqlite3", "#{Rails.root}/db/test_slave#{i + 1}.sqlite3") }
|
7
|
+
require "database_cleaner"
|
9
8
|
|
10
9
|
RSpec.configure do |config|
|
11
10
|
config.run_all_when_everything_filtered = true
|
12
11
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
13
|
-
config.use_transactional_fixtures = true
|
14
12
|
config.filter_run :focus
|
13
|
+
|
14
|
+
config.before(:suite) do
|
15
|
+
DatabaseCleaner.strategy = :deletion
|
16
|
+
3.times do |i|
|
17
|
+
FileUtils.copy("#{Rails.root}/db/test.sqlite3", "#{Rails.root}/db/test_slave#{i + 1}.sqlite3")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
config.after do
|
22
|
+
DatabaseCleaner.clean
|
23
|
+
3.times do |i|
|
24
|
+
FileUtils.copy("#{Rails.root}/db/test.sqlite3", "#{Rails.root}/db/test_slave#{i + 1}.sqlite3")
|
25
|
+
end
|
26
|
+
end
|
15
27
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: replicat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryo Nakamura
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-12-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 3.0.10
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: database_cleaner
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.2.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.2.0
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: jquery-rails
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -214,6 +228,7 @@ extensions: []
|
|
214
228
|
extra_rdoc_files: []
|
215
229
|
files:
|
216
230
|
- .gitignore
|
231
|
+
- CHANGELOG.md
|
217
232
|
- Gemfile
|
218
233
|
- LICENSE.txt
|
219
234
|
- README.md
|
@@ -223,6 +238,7 @@ files:
|
|
223
238
|
- lib/replicat/model.rb
|
224
239
|
- lib/replicat/proxy.rb
|
225
240
|
- lib/replicat/replicable.rb
|
241
|
+
- lib/replicat/scope_proxy.rb
|
226
242
|
- lib/replicat/version.rb
|
227
243
|
- replicat.gemspec
|
228
244
|
- spec/dummy/Rakefile
|
@@ -232,6 +248,7 @@ files:
|
|
232
248
|
- spec/dummy/app/helpers/application_helper.rb
|
233
249
|
- spec/dummy/app/mailers/.gitkeep
|
234
250
|
- spec/dummy/app/models/.gitkeep
|
251
|
+
- spec/dummy/app/models/ingredient.rb
|
235
252
|
- spec/dummy/app/models/recipe.rb
|
236
253
|
- spec/dummy/app/models/user.rb
|
237
254
|
- spec/dummy/app/views/layouts/application.html.erb
|
@@ -259,6 +276,7 @@ files:
|
|
259
276
|
- spec/dummy/public/500.html
|
260
277
|
- spec/dummy/public/favicon.ico
|
261
278
|
- spec/dummy/script/rails
|
279
|
+
- spec/replicat/model_spec.rb
|
262
280
|
- spec/replicat/replicable_spec.rb
|
263
281
|
- spec/spec_helper.rb
|
264
282
|
homepage: https://github.com/r7kamura/replicat
|
@@ -293,6 +311,7 @@ test_files:
|
|
293
311
|
- spec/dummy/app/helpers/application_helper.rb
|
294
312
|
- spec/dummy/app/mailers/.gitkeep
|
295
313
|
- spec/dummy/app/models/.gitkeep
|
314
|
+
- spec/dummy/app/models/ingredient.rb
|
296
315
|
- spec/dummy/app/models/recipe.rb
|
297
316
|
- spec/dummy/app/models/user.rb
|
298
317
|
- spec/dummy/app/views/layouts/application.html.erb
|
@@ -320,5 +339,6 @@ test_files:
|
|
320
339
|
- spec/dummy/public/500.html
|
321
340
|
- spec/dummy/public/favicon.ico
|
322
341
|
- spec/dummy/script/rails
|
342
|
+
- spec/replicat/model_spec.rb
|
323
343
|
- spec/replicat/replicable_spec.rb
|
324
344
|
- spec/spec_helper.rb
|